mirror of
https://github.com/tapframe/NuvioStreaming.git
synced 2026-01-11 20:10:25 +00:00
Enhance AddonsScreen UI and functionality; implement reorder mode for addons, improve header layout with back and refresh buttons, and refactor modal for addon installation details. Update styles for better visual consistency and user experience.
This commit is contained in:
parent
9167767a65
commit
c95d9d8093
1 changed files with 591 additions and 253 deletions
|
|
@ -63,7 +63,9 @@ const AddonsScreen = () => {
|
|||
const [showConfirmModal, setShowConfirmModal] = useState(false);
|
||||
const [installing, setInstalling] = useState(false);
|
||||
const [catalogCount, setCatalogCount] = useState(0);
|
||||
// Add state for reorder mode
|
||||
const [reorderMode, setReorderMode] = useState(false);
|
||||
// Force dark mode
|
||||
const isDarkMode = true;
|
||||
|
||||
// State for community addons
|
||||
|
|
@ -500,124 +502,333 @@ const AddonsScreen = () => {
|
|||
);
|
||||
|
||||
return (
|
||||
<SafeAreaView style={[styles.container, { backgroundColor: isDarkMode ? colors.background : colors.white }]}>
|
||||
<StatusBar barStyle={isDarkMode ? 'light-content' : 'dark-content'} />
|
||||
<SafeAreaView style={styles.container}>
|
||||
<StatusBar barStyle="light-content" />
|
||||
|
||||
{/* Header */}
|
||||
<View style={styles.header}>
|
||||
<Text style={styles.title}>Addons</Text>
|
||||
<TouchableOpacity onPress={toggleReorderMode} style={styles.reorderButton}>
|
||||
<MaterialIcons
|
||||
name={reorderMode ? "done" : "reorder"}
|
||||
size={24}
|
||||
color={colors.primary}
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
|
||||
<View style={styles.statsContainer}>
|
||||
<StatsCard value={addons.length} label="Installed" />
|
||||
<StatsCard value={catalogCount} label="Catalogs" />
|
||||
</View>
|
||||
|
||||
<View style={styles.searchContainer}>
|
||||
<TextInput
|
||||
style={styles.searchInput}
|
||||
placeholder="Enter addon URL..."
|
||||
placeholderTextColor={colors.mediumGray}
|
||||
value={addonUrl}
|
||||
onChangeText={setAddonUrl}
|
||||
/>
|
||||
<TouchableOpacity
|
||||
style={[styles.addButton, !addonUrl && styles.disabledButton]}
|
||||
onPress={() => handleAddAddon()}
|
||||
disabled={!addonUrl || installing}
|
||||
style={styles.backButton}
|
||||
onPress={() => navigation.goBack()}
|
||||
>
|
||||
{installing ? (
|
||||
<ActivityIndicator size="small" color={colors.white} />
|
||||
) : (
|
||||
<MaterialIcons name="add" size={24} color={colors.white} />
|
||||
)}
|
||||
<MaterialIcons name="chevron-left" size={28} color={colors.white} />
|
||||
<Text style={styles.backText}>Settings</Text>
|
||||
</TouchableOpacity>
|
||||
|
||||
<View style={styles.headerActions}>
|
||||
{/* Reorder Mode Toggle Button */}
|
||||
<TouchableOpacity
|
||||
style={[styles.headerButton, reorderMode && styles.activeHeaderButton]}
|
||||
onPress={toggleReorderMode}
|
||||
>
|
||||
<MaterialIcons
|
||||
name="swap-vert"
|
||||
size={24}
|
||||
color={reorderMode ? colors.primary : colors.white}
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
|
||||
{/* Refresh Button */}
|
||||
<TouchableOpacity
|
||||
style={styles.headerButton}
|
||||
onPress={refreshAddons}
|
||||
disabled={loading}
|
||||
>
|
||||
<MaterialIcons
|
||||
name="refresh"
|
||||
size={24}
|
||||
color={loading ? colors.mediumGray : colors.white}
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
|
||||
<Text style={styles.headerTitle}>
|
||||
Addons
|
||||
{reorderMode && <Text style={styles.reorderModeText}> (Reorder Mode)</Text>}
|
||||
</Text>
|
||||
|
||||
{reorderMode && (
|
||||
<View style={styles.reorderInfoBanner}>
|
||||
<MaterialIcons name="info-outline" size={18} color={colors.primary} />
|
||||
<Text style={styles.reorderInfoText}>
|
||||
Addons at the top have higher priority when loading content
|
||||
</Text>
|
||||
</View>
|
||||
)}
|
||||
|
||||
{loading ? (
|
||||
<View style={styles.loadingContainer}>
|
||||
<ActivityIndicator size="large" color={colors.primary} />
|
||||
<Text style={styles.loadingText}>Loading addons...</Text>
|
||||
</View>
|
||||
) : (
|
||||
<FlatList
|
||||
data={addons}
|
||||
renderItem={renderAddonItem}
|
||||
keyExtractor={(item) => item.id}
|
||||
style={styles.list}
|
||||
contentContainerStyle={styles.listContent}
|
||||
ListEmptyComponent={() => (
|
||||
<View style={styles.emptyContainer}>
|
||||
<MaterialIcons name="extension-off" size={48} color={colors.mediumGray} />
|
||||
<Text style={styles.emptyText}>No addons installed</Text>
|
||||
<Text style={styles.emptySubtext}>Add an addon using the URL field above</Text>
|
||||
<ScrollView
|
||||
style={styles.scrollView}
|
||||
showsVerticalScrollIndicator={false}
|
||||
contentInsetAdjustmentBehavior="automatic"
|
||||
>
|
||||
{/* Overview Section */}
|
||||
<View style={styles.section}>
|
||||
<Text style={styles.sectionTitle}>OVERVIEW</Text>
|
||||
<View style={styles.statsContainer}>
|
||||
<StatsCard value={addons.length} label="Addons" />
|
||||
<View style={styles.statsDivider} />
|
||||
<StatsCard value={addons.length} label="Active" />
|
||||
<View style={styles.statsDivider} />
|
||||
<StatsCard value={catalogCount} label="Catalogs" />
|
||||
</View>
|
||||
</View>
|
||||
|
||||
{/* Hide Add Addon Section in reorder mode */}
|
||||
{!reorderMode && (
|
||||
<View style={styles.section}>
|
||||
<Text style={styles.sectionTitle}>ADD NEW ADDON</Text>
|
||||
<View style={styles.addAddonContainer}>
|
||||
<TextInput
|
||||
style={styles.addonInput}
|
||||
placeholder="Addon URL"
|
||||
placeholderTextColor={colors.mediumGray}
|
||||
value={addonUrl}
|
||||
onChangeText={setAddonUrl}
|
||||
autoCapitalize="none"
|
||||
autoCorrect={false}
|
||||
/>
|
||||
<TouchableOpacity
|
||||
style={[styles.addButton, {opacity: installing || !addonUrl ? 0.6 : 1}]}
|
||||
onPress={() => handleAddAddon()}
|
||||
disabled={installing || !addonUrl}
|
||||
>
|
||||
<Text style={styles.addButtonText}>
|
||||
{installing ? 'Loading...' : 'Add Addon'}
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</View>
|
||||
)}
|
||||
/>
|
||||
|
||||
{/* Installed Addons Section */}
|
||||
<View style={styles.section}>
|
||||
<Text style={styles.sectionTitle}>
|
||||
{reorderMode ? "DRAG ADDONS TO REORDER" : "INSTALLED ADDONS"}
|
||||
</Text>
|
||||
<View style={styles.addonList}>
|
||||
{addons.length === 0 ? (
|
||||
<View style={styles.emptyContainer}>
|
||||
<MaterialIcons name="extension-off" size={32} color={colors.mediumGray} />
|
||||
<Text style={styles.emptyText}>No addons installed</Text>
|
||||
</View>
|
||||
) : (
|
||||
addons.map((addon, index) => (
|
||||
<View
|
||||
key={addon.id}
|
||||
style={{ marginBottom: index === addons.length - 1 ? 32 : 0 }}
|
||||
>
|
||||
{renderAddonItem({ item: addon, index })}
|
||||
</View>
|
||||
))
|
||||
)}
|
||||
</View>
|
||||
</View>
|
||||
|
||||
{/* Separator */}
|
||||
<View style={styles.sectionSeparator} />
|
||||
|
||||
{/* Community Addons Section */}
|
||||
<View style={styles.section}>
|
||||
<Text style={styles.sectionTitle}>COMMUNITY ADDONS</Text>
|
||||
<View style={styles.addonList}>
|
||||
{communityLoading ? (
|
||||
<View style={styles.loadingContainer}>
|
||||
<ActivityIndicator size="large" color={colors.primary} />
|
||||
</View>
|
||||
) : communityError ? (
|
||||
<View style={styles.emptyContainer}>
|
||||
<MaterialIcons name="error-outline" size={32} color={colors.error} />
|
||||
<Text style={styles.emptyText}>{communityError}</Text>
|
||||
</View>
|
||||
) : communityAddons.length === 0 ? (
|
||||
<View style={styles.emptyContainer}>
|
||||
<MaterialIcons name="extension-off" size={32} color={colors.mediumGray} />
|
||||
<Text style={styles.emptyText}>No community addons available</Text>
|
||||
</View>
|
||||
) : (
|
||||
communityAddons.map((item, index) => (
|
||||
<View
|
||||
key={item.transportUrl}
|
||||
style={{ marginBottom: index === communityAddons.length - 1 ? 32 : 16 }}
|
||||
>
|
||||
<View style={styles.addonItem}>
|
||||
<View style={styles.addonHeader}>
|
||||
{item.manifest.logo ? (
|
||||
<ExpoImage
|
||||
source={{ uri: item.manifest.logo }}
|
||||
style={styles.addonIcon}
|
||||
contentFit="contain"
|
||||
/>
|
||||
) : (
|
||||
<View style={styles.addonIconPlaceholder}>
|
||||
<MaterialIcons name="extension" size={22} color={colors.mediumGray} />
|
||||
</View>
|
||||
)}
|
||||
<View style={styles.addonTitleContainer}>
|
||||
<Text style={styles.addonName}>{item.manifest.name}</Text>
|
||||
<View style={styles.addonMetaContainer}>
|
||||
<Text style={styles.addonVersion}>v{item.manifest.version || 'N/A'}</Text>
|
||||
<Text style={styles.addonDot}>•</Text>
|
||||
<Text style={styles.addonCategory}>
|
||||
{item.manifest.types && item.manifest.types.length > 0
|
||||
? item.manifest.types.map(t => t.charAt(0).toUpperCase() + t.slice(1)).join(' • ')
|
||||
: 'General'}
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
<View style={styles.addonActions}>
|
||||
{item.manifest.behaviorHints?.configurable && (
|
||||
<TouchableOpacity
|
||||
style={styles.configButton}
|
||||
onPress={() => handleConfigureAddon(item.manifest, item.transportUrl)}
|
||||
>
|
||||
<MaterialIcons name="settings" size={20} color={colors.primary} />
|
||||
</TouchableOpacity>
|
||||
)}
|
||||
<TouchableOpacity
|
||||
style={[styles.installButton, installing && { opacity: 0.6 }]}
|
||||
onPress={() => handleAddAddon(item.transportUrl)}
|
||||
disabled={installing}
|
||||
>
|
||||
{installing ? (
|
||||
<ActivityIndicator size="small" color={colors.white} />
|
||||
) : (
|
||||
<MaterialIcons name="add" size={20} color={colors.white} />
|
||||
)}
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
<Text style={styles.addonDescription}>
|
||||
{item.manifest.description
|
||||
? (item.manifest.description.length > 100
|
||||
? item.manifest.description.substring(0, 100) + '...'
|
||||
: item.manifest.description)
|
||||
: 'No description provided.'}
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
))
|
||||
)}
|
||||
</View>
|
||||
</View>
|
||||
</ScrollView>
|
||||
)}
|
||||
|
||||
{/* Community Addons Section */}
|
||||
<View style={styles.communitySection}>
|
||||
<Text style={styles.sectionTitle}>Community Addons</Text>
|
||||
{communityLoading ? (
|
||||
<View style={styles.loadingContainer}>
|
||||
<ActivityIndicator size="small" color={colors.primary} />
|
||||
<Text style={styles.loadingText}>Loading community addons...</Text>
|
||||
</View>
|
||||
) : communityError ? (
|
||||
<View style={styles.errorContainer}>
|
||||
<MaterialIcons name="error-outline" size={24} color={colors.error} />
|
||||
<Text style={styles.errorText}>{communityError}</Text>
|
||||
</View>
|
||||
) : (
|
||||
<FlatList
|
||||
data={communityAddons}
|
||||
renderItem={renderCommunityAddonItem}
|
||||
keyExtractor={(item) => item.manifest.id}
|
||||
horizontal
|
||||
showsHorizontalScrollIndicator={false}
|
||||
style={styles.communityList}
|
||||
contentContainerStyle={styles.communityListContent}
|
||||
/>
|
||||
)}
|
||||
</View>
|
||||
|
||||
{/* Confirmation Modal */}
|
||||
{/* Addon Details Confirmation Modal */}
|
||||
<Modal
|
||||
visible={showConfirmModal}
|
||||
transparent
|
||||
animationType="fade"
|
||||
onRequestClose={() => setShowConfirmModal(false)}
|
||||
onRequestClose={() => {
|
||||
setShowConfirmModal(false);
|
||||
setAddonDetails(null);
|
||||
}}
|
||||
>
|
||||
<BlurView intensity={100} style={styles.modalOverlay}>
|
||||
<BlurView intensity={80} style={styles.modalContainer} tint="dark">
|
||||
<View style={styles.modalContent}>
|
||||
<Text style={styles.modalTitle}>Install Addon</Text>
|
||||
{addonDetails && (
|
||||
<>
|
||||
<Text style={styles.modalAddonName}>{addonDetails.name}</Text>
|
||||
<Text style={styles.modalAddonDesc}>{addonDetails.description}</Text>
|
||||
<View style={styles.modalHeader}>
|
||||
<Text style={styles.modalTitle}>Install Addon</Text>
|
||||
<TouchableOpacity
|
||||
onPress={() => {
|
||||
setShowConfirmModal(false);
|
||||
setAddonDetails(null);
|
||||
}}
|
||||
>
|
||||
<MaterialIcons name="close" size={24} color={colors.white} />
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
|
||||
<ScrollView
|
||||
style={styles.modalScrollContent}
|
||||
showsVerticalScrollIndicator={false}
|
||||
bounces={true}
|
||||
>
|
||||
<View style={styles.addonDetailHeader}>
|
||||
{/* @ts-ignore */}
|
||||
{addonDetails.logo ? (
|
||||
<ExpoImage
|
||||
source={{ uri: addonDetails.logo }}
|
||||
style={styles.addonLogo}
|
||||
contentFit="contain"
|
||||
/>
|
||||
) : (
|
||||
<View style={styles.addonLogoPlaceholder}>
|
||||
<MaterialIcons name="extension" size={40} color={colors.mediumGray} />
|
||||
</View>
|
||||
)}
|
||||
<Text style={styles.addonDetailName}>{addonDetails.name}</Text>
|
||||
<Text style={styles.addonDetailVersion}>v{addonDetails.version || '1.0.0'}</Text>
|
||||
</View>
|
||||
|
||||
<View style={styles.addonDetailSection}>
|
||||
<Text style={styles.addonDetailSectionTitle}>Description</Text>
|
||||
<Text style={styles.addonDetailDescription}>
|
||||
{addonDetails.description || 'No description available'}
|
||||
</Text>
|
||||
</View>
|
||||
|
||||
{addonDetails.types && addonDetails.types.length > 0 && (
|
||||
<View style={styles.addonDetailSection}>
|
||||
<Text style={styles.addonDetailSectionTitle}>Supported Types</Text>
|
||||
<View style={styles.addonDetailChips}>
|
||||
{addonDetails.types.map((type, index) => (
|
||||
<View key={index} style={styles.addonDetailChip}>
|
||||
<Text style={styles.addonDetailChipText}>{type}</Text>
|
||||
</View>
|
||||
))}
|
||||
</View>
|
||||
</View>
|
||||
)}
|
||||
|
||||
{addonDetails.catalogs && addonDetails.catalogs.length > 0 && (
|
||||
<View style={styles.addonDetailSection}>
|
||||
<Text style={styles.addonDetailSectionTitle}>Catalogs</Text>
|
||||
<View style={styles.addonDetailChips}>
|
||||
{addonDetails.catalogs.map((catalog, index) => (
|
||||
<View key={index} style={styles.addonDetailChip}>
|
||||
<Text style={styles.addonDetailChipText}>
|
||||
{catalog.type} - {catalog.id}
|
||||
</Text>
|
||||
</View>
|
||||
))}
|
||||
</View>
|
||||
</View>
|
||||
)}
|
||||
</ScrollView>
|
||||
|
||||
<View style={styles.modalActions}>
|
||||
<TouchableOpacity
|
||||
style={[styles.modalButton, styles.cancelButton]}
|
||||
onPress={() => {
|
||||
setShowConfirmModal(false);
|
||||
setAddonDetails(null);
|
||||
}}
|
||||
>
|
||||
<Text style={styles.modalButtonText}>Cancel</Text>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity
|
||||
style={[styles.modalButton, styles.installButton]}
|
||||
onPress={confirmInstallAddon}
|
||||
disabled={installing}
|
||||
>
|
||||
{installing ? (
|
||||
<ActivityIndicator size="small" color={colors.white} />
|
||||
) : (
|
||||
<Text style={styles.modalButtonText}>Install</Text>
|
||||
)}
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</>
|
||||
)}
|
||||
<View style={styles.modalButtons}>
|
||||
<TouchableOpacity
|
||||
style={[styles.modalButton, styles.cancelButton]}
|
||||
onPress={() => setShowConfirmModal(false)}
|
||||
>
|
||||
<Text style={styles.modalButtonText}>Cancel</Text>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity
|
||||
style={[styles.modalButton, styles.confirmButton]}
|
||||
onPress={confirmInstallAddon}
|
||||
>
|
||||
<Text style={styles.modalButtonText}>Install</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</View>
|
||||
</BlurView>
|
||||
</Modal>
|
||||
|
|
@ -628,156 +839,197 @@ const AddonsScreen = () => {
|
|||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
paddingTop: Platform.OS === 'android' ? ANDROID_STATUSBAR_HEIGHT : 0,
|
||||
backgroundColor: colors.darkBackground,
|
||||
},
|
||||
header: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'center',
|
||||
paddingHorizontal: 16,
|
||||
paddingVertical: 12,
|
||||
paddingTop: Platform.OS === 'android' ? ANDROID_STATUSBAR_HEIGHT + 8 : 8,
|
||||
},
|
||||
title: {
|
||||
fontSize: 24,
|
||||
fontWeight: 'bold',
|
||||
color: colors.white,
|
||||
},
|
||||
statsContainer: {
|
||||
headerActions: {
|
||||
flexDirection: 'row',
|
||||
padding: 16,
|
||||
justifyContent: 'space-around',
|
||||
},
|
||||
searchContainer: {
|
||||
flexDirection: 'row',
|
||||
paddingHorizontal: 16,
|
||||
paddingBottom: 16,
|
||||
alignItems: 'center',
|
||||
},
|
||||
searchInput: {
|
||||
flex: 1,
|
||||
height: 40,
|
||||
backgroundColor: colors.darkGray,
|
||||
borderRadius: 8,
|
||||
paddingHorizontal: 12,
|
||||
marginRight: 8,
|
||||
color: colors.white,
|
||||
headerButton: {
|
||||
padding: 8,
|
||||
marginLeft: 8,
|
||||
},
|
||||
addButton: {
|
||||
width: 40,
|
||||
height: 40,
|
||||
backgroundColor: colors.primary,
|
||||
activeHeaderButton: {
|
||||
backgroundColor: 'rgba(45, 156, 219, 0.2)',
|
||||
borderRadius: 6,
|
||||
},
|
||||
reorderModeText: {
|
||||
color: colors.primary,
|
||||
fontSize: 18,
|
||||
fontWeight: '400',
|
||||
},
|
||||
reorderInfoBanner: {
|
||||
backgroundColor: 'rgba(45, 156, 219, 0.15)',
|
||||
paddingHorizontal: 16,
|
||||
paddingVertical: 10,
|
||||
marginHorizontal: 16,
|
||||
borderRadius: 8,
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
marginBottom: 16,
|
||||
},
|
||||
reorderInfoText: {
|
||||
color: colors.white,
|
||||
fontSize: 14,
|
||||
marginLeft: 8,
|
||||
},
|
||||
reorderButtons: {
|
||||
position: 'absolute',
|
||||
left: -12,
|
||||
top: '50%',
|
||||
marginTop: -40,
|
||||
flexDirection: 'column',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
zIndex: 10,
|
||||
},
|
||||
reorderButton: {
|
||||
backgroundColor: colors.elevation3,
|
||||
width: 30,
|
||||
height: 30,
|
||||
borderRadius: 15,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
marginVertical: 4,
|
||||
},
|
||||
disabledButton: {
|
||||
opacity: 0.5,
|
||||
backgroundColor: colors.elevation2,
|
||||
},
|
||||
list: {
|
||||
flex: 1,
|
||||
},
|
||||
listContent: {
|
||||
paddingHorizontal: 16,
|
||||
},
|
||||
loadingContainer: {
|
||||
flex: 1,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
},
|
||||
loadingText: {
|
||||
marginTop: 12,
|
||||
color: colors.mediumGray,
|
||||
},
|
||||
emptyContainer: {
|
||||
flex: 1,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
paddingVertical: 32,
|
||||
},
|
||||
emptyText: {
|
||||
fontSize: 16,
|
||||
color: colors.mediumGray,
|
||||
marginTop: 16,
|
||||
},
|
||||
emptySubtext: {
|
||||
fontSize: 14,
|
||||
color: colors.mediumGray,
|
||||
marginTop: 8,
|
||||
},
|
||||
modalOverlay: {
|
||||
flex: 1,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
backgroundColor: 'rgba(0, 0, 0, 0.5)',
|
||||
},
|
||||
modalContent: {
|
||||
backgroundColor: colors.darkGray,
|
||||
priorityBadge: {
|
||||
backgroundColor: colors.primary,
|
||||
borderRadius: 12,
|
||||
padding: 24,
|
||||
width: '80%',
|
||||
maxWidth: 400,
|
||||
paddingHorizontal: 8,
|
||||
paddingVertical: 3,
|
||||
},
|
||||
modalTitle: {
|
||||
fontSize: 20,
|
||||
priorityText: {
|
||||
color: colors.white,
|
||||
fontSize: 12,
|
||||
fontWeight: 'bold',
|
||||
color: colors.white,
|
||||
marginBottom: 16,
|
||||
},
|
||||
modalAddonName: {
|
||||
fontSize: 16,
|
||||
color: colors.white,
|
||||
marginBottom: 8,
|
||||
backButton: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
padding: 8,
|
||||
},
|
||||
modalAddonDesc: {
|
||||
fontSize: 14,
|
||||
color: colors.mediumGray,
|
||||
backText: {
|
||||
fontSize: 17,
|
||||
fontWeight: '400',
|
||||
color: colors.primary,
|
||||
},
|
||||
headerTitle: {
|
||||
fontSize: 34,
|
||||
fontWeight: '700',
|
||||
color: colors.white,
|
||||
paddingHorizontal: 16,
|
||||
paddingBottom: 16,
|
||||
paddingTop: 8,
|
||||
},
|
||||
scrollView: {
|
||||
flex: 1,
|
||||
},
|
||||
section: {
|
||||
marginBottom: 24,
|
||||
},
|
||||
modalButtons: {
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'flex-end',
|
||||
},
|
||||
modalButton: {
|
||||
paddingHorizontal: 16,
|
||||
paddingVertical: 8,
|
||||
borderRadius: 6,
|
||||
marginLeft: 12,
|
||||
},
|
||||
modalButtonText: {
|
||||
color: colors.white,
|
||||
fontSize: 14,
|
||||
fontWeight: '500',
|
||||
},
|
||||
cancelButton: {
|
||||
backgroundColor: colors.mediumGray,
|
||||
},
|
||||
confirmButton: {
|
||||
backgroundColor: colors.primary,
|
||||
},
|
||||
communitySection: {
|
||||
paddingTop: 16,
|
||||
},
|
||||
sectionTitle: {
|
||||
fontSize: 18,
|
||||
fontSize: 13,
|
||||
fontWeight: '600',
|
||||
color: colors.mediumGray,
|
||||
marginHorizontal: 16,
|
||||
marginBottom: 8,
|
||||
letterSpacing: 0.5,
|
||||
textTransform: 'uppercase',
|
||||
},
|
||||
statsContainer: {
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-between',
|
||||
marginHorizontal: 16,
|
||||
backgroundColor: colors.elevation2,
|
||||
borderRadius: 12,
|
||||
padding: 16,
|
||||
shadowColor: '#000',
|
||||
shadowOffset: { width: 0, height: 2 },
|
||||
shadowOpacity: 0.1,
|
||||
shadowRadius: 4,
|
||||
elevation: 2,
|
||||
},
|
||||
statsCard: {
|
||||
flex: 1,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
},
|
||||
statsDivider: {
|
||||
width: 1,
|
||||
height: '80%',
|
||||
backgroundColor: 'rgba(150, 150, 150, 0.2)',
|
||||
alignSelf: 'center',
|
||||
},
|
||||
statsValue: {
|
||||
fontSize: 24,
|
||||
fontWeight: 'bold',
|
||||
color: colors.white,
|
||||
paddingHorizontal: 16,
|
||||
marginBottom: 12,
|
||||
marginBottom: 4,
|
||||
},
|
||||
communityList: {
|
||||
height: 160,
|
||||
statsLabel: {
|
||||
fontSize: 13,
|
||||
color: colors.mediumGray,
|
||||
},
|
||||
communityListContent: {
|
||||
paddingHorizontal: 16,
|
||||
},
|
||||
errorContainer: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
addAddonContainer: {
|
||||
marginHorizontal: 16,
|
||||
backgroundColor: colors.elevation2,
|
||||
borderRadius: 12,
|
||||
padding: 16,
|
||||
shadowColor: '#000',
|
||||
shadowOffset: { width: 0, height: 2 },
|
||||
shadowOpacity: 0.1,
|
||||
shadowRadius: 4,
|
||||
elevation: 2,
|
||||
},
|
||||
errorText: {
|
||||
color: colors.error,
|
||||
marginLeft: 8,
|
||||
addonInput: {
|
||||
backgroundColor: colors.elevation1,
|
||||
borderRadius: 8,
|
||||
padding: 12,
|
||||
color: colors.white,
|
||||
marginBottom: 16,
|
||||
fontSize: 15,
|
||||
},
|
||||
addButton: {
|
||||
backgroundColor: colors.primary,
|
||||
borderRadius: 8,
|
||||
padding: 12,
|
||||
alignItems: 'center',
|
||||
},
|
||||
addButtonText: {
|
||||
color: colors.white,
|
||||
fontWeight: '600',
|
||||
fontSize: 16,
|
||||
},
|
||||
addonList: {
|
||||
paddingHorizontal: 16,
|
||||
},
|
||||
emptyContainer: {
|
||||
backgroundColor: colors.elevation2,
|
||||
borderRadius: 12,
|
||||
padding: 32,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
shadowColor: '#000',
|
||||
shadowOffset: { width: 0, height: 2 },
|
||||
shadowOpacity: 0.1,
|
||||
shadowRadius: 4,
|
||||
elevation: 2,
|
||||
},
|
||||
emptyText: {
|
||||
marginTop: 8,
|
||||
color: colors.mediumGray,
|
||||
fontSize: 15,
|
||||
},
|
||||
addonItem: {
|
||||
backgroundColor: colors.elevation2,
|
||||
|
|
@ -847,29 +1099,136 @@ const styles = StyleSheet.create({
|
|||
lineHeight: 20,
|
||||
marginLeft: 48, // Align with title, accounting for icon width
|
||||
},
|
||||
reorderButton: {
|
||||
padding: 8,
|
||||
},
|
||||
reorderButtons: {
|
||||
position: 'absolute',
|
||||
left: -12,
|
||||
top: '50%',
|
||||
marginTop: -40,
|
||||
flexDirection: 'column',
|
||||
alignItems: 'center',
|
||||
loadingContainer: {
|
||||
flex: 1,
|
||||
justifyContent: 'center',
|
||||
zIndex: 10,
|
||||
alignItems: 'center',
|
||||
},
|
||||
priorityBadge: {
|
||||
backgroundColor: colors.primary,
|
||||
modalContainer: {
|
||||
flex: 1,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
},
|
||||
modalContent: {
|
||||
backgroundColor: colors.elevation2,
|
||||
borderRadius: 14,
|
||||
width: '85%',
|
||||
maxHeight: '85%',
|
||||
overflow: 'hidden',
|
||||
shadowColor: '#000',
|
||||
shadowOffset: { width: 0, height: 6 },
|
||||
shadowOpacity: 0.25,
|
||||
shadowRadius: 8,
|
||||
elevation: 5,
|
||||
},
|
||||
modalHeader: {
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'center',
|
||||
padding: 16,
|
||||
borderBottomWidth: 1,
|
||||
borderBottomColor: colors.elevation3,
|
||||
},
|
||||
modalTitle: {
|
||||
fontSize: 17,
|
||||
fontWeight: 'bold',
|
||||
color: colors.white,
|
||||
},
|
||||
modalScrollContent: {
|
||||
maxHeight: 400,
|
||||
},
|
||||
addonDetailHeader: {
|
||||
alignItems: 'center',
|
||||
padding: 24,
|
||||
borderBottomWidth: 1,
|
||||
borderBottomColor: colors.elevation3,
|
||||
},
|
||||
addonLogo: {
|
||||
width: 64,
|
||||
height: 64,
|
||||
borderRadius: 12,
|
||||
marginBottom: 16,
|
||||
backgroundColor: colors.elevation3,
|
||||
},
|
||||
addonLogoPlaceholder: {
|
||||
width: 64,
|
||||
height: 64,
|
||||
borderRadius: 12,
|
||||
backgroundColor: colors.elevation3,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
marginBottom: 16,
|
||||
},
|
||||
addonDetailName: {
|
||||
fontSize: 20,
|
||||
fontWeight: 'bold',
|
||||
color: colors.white,
|
||||
marginBottom: 4,
|
||||
textAlign: 'center',
|
||||
},
|
||||
addonDetailVersion: {
|
||||
fontSize: 14,
|
||||
color: colors.mediumGray,
|
||||
},
|
||||
addonDetailSection: {
|
||||
padding: 16,
|
||||
borderBottomWidth: 1,
|
||||
borderBottomColor: colors.elevation3,
|
||||
},
|
||||
addonDetailSectionTitle: {
|
||||
fontSize: 16,
|
||||
fontWeight: '600',
|
||||
color: colors.white,
|
||||
marginBottom: 8,
|
||||
},
|
||||
addonDetailDescription: {
|
||||
fontSize: 15,
|
||||
color: colors.mediumEmphasis,
|
||||
lineHeight: 20,
|
||||
},
|
||||
addonDetailChips: {
|
||||
flexDirection: 'row',
|
||||
flexWrap: 'wrap',
|
||||
gap: 8,
|
||||
},
|
||||
addonDetailChip: {
|
||||
backgroundColor: colors.elevation3,
|
||||
borderRadius: 12,
|
||||
paddingHorizontal: 8,
|
||||
paddingVertical: 3,
|
||||
paddingVertical: 4,
|
||||
},
|
||||
priorityText: {
|
||||
addonDetailChipText: {
|
||||
fontSize: 13,
|
||||
color: colors.white,
|
||||
fontSize: 12,
|
||||
fontWeight: 'bold',
|
||||
},
|
||||
modalActions: {
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'flex-end',
|
||||
padding: 16,
|
||||
borderTopWidth: 1,
|
||||
borderTopColor: colors.elevation3,
|
||||
},
|
||||
modalButton: {
|
||||
paddingVertical: 8,
|
||||
paddingHorizontal: 16,
|
||||
borderRadius: 8,
|
||||
minWidth: 80,
|
||||
alignItems: 'center',
|
||||
},
|
||||
cancelButton: {
|
||||
backgroundColor: colors.elevation3,
|
||||
marginRight: 8,
|
||||
},
|
||||
installButton: {
|
||||
backgroundColor: colors.success,
|
||||
borderRadius: 6,
|
||||
padding: 8,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
},
|
||||
modalButtonText: {
|
||||
color: colors.white,
|
||||
fontWeight: '600',
|
||||
},
|
||||
addonActions: {
|
||||
flexDirection: 'row',
|
||||
|
|
@ -882,6 +1241,9 @@ const styles = StyleSheet.create({
|
|||
padding: 6,
|
||||
marginRight: 8,
|
||||
},
|
||||
communityAddonsList: {
|
||||
paddingHorizontal: 20,
|
||||
},
|
||||
communityAddonItem: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
|
|
@ -971,30 +1333,6 @@ const styles = StyleSheet.create({
|
|||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
},
|
||||
installButton: {
|
||||
backgroundColor: colors.success,
|
||||
borderRadius: 6,
|
||||
padding: 8,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
},
|
||||
statsCard: {
|
||||
backgroundColor: colors.darkGray,
|
||||
borderRadius: 8,
|
||||
padding: 12,
|
||||
alignItems: 'center',
|
||||
minWidth: 100,
|
||||
},
|
||||
statsValue: {
|
||||
fontSize: 24,
|
||||
fontWeight: 'bold',
|
||||
color: colors.white,
|
||||
marginBottom: 4,
|
||||
},
|
||||
statsLabel: {
|
||||
fontSize: 13,
|
||||
color: colors.mediumGray,
|
||||
},
|
||||
});
|
||||
|
||||
export default AddonsScreen;
|
||||
Loading…
Reference in a new issue