mirror of
https://github.com/tapframe/NuvioStreaming.git
synced 2026-04-26 11:02:53 +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 [showConfirmModal, setShowConfirmModal] = useState(false);
|
||||||
const [installing, setInstalling] = useState(false);
|
const [installing, setInstalling] = useState(false);
|
||||||
const [catalogCount, setCatalogCount] = useState(0);
|
const [catalogCount, setCatalogCount] = useState(0);
|
||||||
|
// Add state for reorder mode
|
||||||
const [reorderMode, setReorderMode] = useState(false);
|
const [reorderMode, setReorderMode] = useState(false);
|
||||||
|
// Force dark mode
|
||||||
const isDarkMode = true;
|
const isDarkMode = true;
|
||||||
|
|
||||||
// State for community addons
|
// State for community addons
|
||||||
|
|
@ -500,124 +502,333 @@ const AddonsScreen = () => {
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SafeAreaView style={[styles.container, { backgroundColor: isDarkMode ? colors.background : colors.white }]}>
|
<SafeAreaView style={styles.container}>
|
||||||
<StatusBar barStyle={isDarkMode ? 'light-content' : 'dark-content'} />
|
<StatusBar barStyle="light-content" />
|
||||||
|
|
||||||
|
{/* Header */}
|
||||||
<View style={styles.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
|
<TouchableOpacity
|
||||||
style={[styles.addButton, !addonUrl && styles.disabledButton]}
|
style={styles.backButton}
|
||||||
onPress={() => handleAddAddon()}
|
onPress={() => navigation.goBack()}
|
||||||
disabled={!addonUrl || installing}
|
|
||||||
>
|
>
|
||||||
{installing ? (
|
<MaterialIcons name="chevron-left" size={28} color={colors.white} />
|
||||||
<ActivityIndicator size="small" color={colors.white} />
|
<Text style={styles.backText}>Settings</Text>
|
||||||
) : (
|
|
||||||
<MaterialIcons name="add" size={24} color={colors.white} />
|
|
||||||
)}
|
|
||||||
</TouchableOpacity>
|
</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>
|
</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 ? (
|
{loading ? (
|
||||||
<View style={styles.loadingContainer}>
|
<View style={styles.loadingContainer}>
|
||||||
<ActivityIndicator size="large" color={colors.primary} />
|
<ActivityIndicator size="large" color={colors.primary} />
|
||||||
<Text style={styles.loadingText}>Loading addons...</Text>
|
|
||||||
</View>
|
</View>
|
||||||
) : (
|
) : (
|
||||||
<FlatList
|
<ScrollView
|
||||||
data={addons}
|
style={styles.scrollView}
|
||||||
renderItem={renderAddonItem}
|
showsVerticalScrollIndicator={false}
|
||||||
keyExtractor={(item) => item.id}
|
contentInsetAdjustmentBehavior="automatic"
|
||||||
style={styles.list}
|
>
|
||||||
contentContainerStyle={styles.listContent}
|
{/* Overview Section */}
|
||||||
ListEmptyComponent={() => (
|
<View style={styles.section}>
|
||||||
<View style={styles.emptyContainer}>
|
<Text style={styles.sectionTitle}>OVERVIEW</Text>
|
||||||
<MaterialIcons name="extension-off" size={48} color={colors.mediumGray} />
|
<View style={styles.statsContainer}>
|
||||||
<Text style={styles.emptyText}>No addons installed</Text>
|
<StatsCard value={addons.length} label="Addons" />
|
||||||
<Text style={styles.emptySubtext}>Add an addon using the URL field above</Text>
|
<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>
|
</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 */}
|
{/* Addon Details Confirmation Modal */}
|
||||||
<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 */}
|
|
||||||
<Modal
|
<Modal
|
||||||
visible={showConfirmModal}
|
visible={showConfirmModal}
|
||||||
transparent
|
transparent
|
||||||
animationType="fade"
|
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}>
|
<View style={styles.modalContent}>
|
||||||
<Text style={styles.modalTitle}>Install Addon</Text>
|
|
||||||
{addonDetails && (
|
{addonDetails && (
|
||||||
<>
|
<>
|
||||||
<Text style={styles.modalAddonName}>{addonDetails.name}</Text>
|
<View style={styles.modalHeader}>
|
||||||
<Text style={styles.modalAddonDesc}>{addonDetails.description}</Text>
|
<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>
|
</View>
|
||||||
</BlurView>
|
</BlurView>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|
@ -628,156 +839,197 @@ const AddonsScreen = () => {
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
container: {
|
container: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
paddingTop: Platform.OS === 'android' ? ANDROID_STATUSBAR_HEIGHT : 0,
|
backgroundColor: colors.darkBackground,
|
||||||
},
|
},
|
||||||
header: {
|
header: {
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
|
alignItems: 'center',
|
||||||
justifyContent: 'space-between',
|
justifyContent: 'space-between',
|
||||||
alignItems: 'center',
|
|
||||||
paddingHorizontal: 16,
|
paddingHorizontal: 16,
|
||||||
paddingVertical: 12,
|
paddingTop: Platform.OS === 'android' ? ANDROID_STATUSBAR_HEIGHT + 8 : 8,
|
||||||
},
|
},
|
||||||
title: {
|
headerActions: {
|
||||||
fontSize: 24,
|
|
||||||
fontWeight: 'bold',
|
|
||||||
color: colors.white,
|
|
||||||
},
|
|
||||||
statsContainer: {
|
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
padding: 16,
|
|
||||||
justifyContent: 'space-around',
|
|
||||||
},
|
|
||||||
searchContainer: {
|
|
||||||
flexDirection: 'row',
|
|
||||||
paddingHorizontal: 16,
|
|
||||||
paddingBottom: 16,
|
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
},
|
},
|
||||||
searchInput: {
|
headerButton: {
|
||||||
flex: 1,
|
padding: 8,
|
||||||
height: 40,
|
marginLeft: 8,
|
||||||
backgroundColor: colors.darkGray,
|
|
||||||
borderRadius: 8,
|
|
||||||
paddingHorizontal: 12,
|
|
||||||
marginRight: 8,
|
|
||||||
color: colors.white,
|
|
||||||
},
|
},
|
||||||
addButton: {
|
activeHeaderButton: {
|
||||||
width: 40,
|
backgroundColor: 'rgba(45, 156, 219, 0.2)',
|
||||||
height: 40,
|
borderRadius: 6,
|
||||||
backgroundColor: colors.primary,
|
},
|
||||||
|
reorderModeText: {
|
||||||
|
color: colors.primary,
|
||||||
|
fontSize: 18,
|
||||||
|
fontWeight: '400',
|
||||||
|
},
|
||||||
|
reorderInfoBanner: {
|
||||||
|
backgroundColor: 'rgba(45, 156, 219, 0.15)',
|
||||||
|
paddingHorizontal: 16,
|
||||||
|
paddingVertical: 10,
|
||||||
|
marginHorizontal: 16,
|
||||||
borderRadius: 8,
|
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',
|
justifyContent: 'center',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
|
marginVertical: 4,
|
||||||
},
|
},
|
||||||
disabledButton: {
|
disabledButton: {
|
||||||
opacity: 0.5,
|
opacity: 0.5,
|
||||||
|
backgroundColor: colors.elevation2,
|
||||||
},
|
},
|
||||||
list: {
|
priorityBadge: {
|
||||||
flex: 1,
|
backgroundColor: colors.primary,
|
||||||
},
|
|
||||||
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,
|
|
||||||
borderRadius: 12,
|
borderRadius: 12,
|
||||||
padding: 24,
|
paddingHorizontal: 8,
|
||||||
width: '80%',
|
paddingVertical: 3,
|
||||||
maxWidth: 400,
|
|
||||||
},
|
},
|
||||||
modalTitle: {
|
priorityText: {
|
||||||
fontSize: 20,
|
color: colors.white,
|
||||||
|
fontSize: 12,
|
||||||
fontWeight: 'bold',
|
fontWeight: 'bold',
|
||||||
color: colors.white,
|
|
||||||
marginBottom: 16,
|
|
||||||
},
|
},
|
||||||
modalAddonName: {
|
backButton: {
|
||||||
fontSize: 16,
|
flexDirection: 'row',
|
||||||
color: colors.white,
|
alignItems: 'center',
|
||||||
marginBottom: 8,
|
padding: 8,
|
||||||
},
|
},
|
||||||
modalAddonDesc: {
|
backText: {
|
||||||
fontSize: 14,
|
fontSize: 17,
|
||||||
color: colors.mediumGray,
|
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,
|
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: {
|
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',
|
fontWeight: 'bold',
|
||||||
color: colors.white,
|
color: colors.white,
|
||||||
paddingHorizontal: 16,
|
marginBottom: 4,
|
||||||
marginBottom: 12,
|
|
||||||
},
|
},
|
||||||
communityList: {
|
statsLabel: {
|
||||||
height: 160,
|
fontSize: 13,
|
||||||
|
color: colors.mediumGray,
|
||||||
},
|
},
|
||||||
communityListContent: {
|
addAddonContainer: {
|
||||||
paddingHorizontal: 16,
|
marginHorizontal: 16,
|
||||||
},
|
backgroundColor: colors.elevation2,
|
||||||
errorContainer: {
|
borderRadius: 12,
|
||||||
flexDirection: 'row',
|
|
||||||
alignItems: 'center',
|
|
||||||
padding: 16,
|
padding: 16,
|
||||||
|
shadowColor: '#000',
|
||||||
|
shadowOffset: { width: 0, height: 2 },
|
||||||
|
shadowOpacity: 0.1,
|
||||||
|
shadowRadius: 4,
|
||||||
|
elevation: 2,
|
||||||
},
|
},
|
||||||
errorText: {
|
addonInput: {
|
||||||
color: colors.error,
|
backgroundColor: colors.elevation1,
|
||||||
marginLeft: 8,
|
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: {
|
addonItem: {
|
||||||
backgroundColor: colors.elevation2,
|
backgroundColor: colors.elevation2,
|
||||||
|
|
@ -847,29 +1099,136 @@ const styles = StyleSheet.create({
|
||||||
lineHeight: 20,
|
lineHeight: 20,
|
||||||
marginLeft: 48, // Align with title, accounting for icon width
|
marginLeft: 48, // Align with title, accounting for icon width
|
||||||
},
|
},
|
||||||
reorderButton: {
|
loadingContainer: {
|
||||||
padding: 8,
|
flex: 1,
|
||||||
},
|
|
||||||
reorderButtons: {
|
|
||||||
position: 'absolute',
|
|
||||||
left: -12,
|
|
||||||
top: '50%',
|
|
||||||
marginTop: -40,
|
|
||||||
flexDirection: 'column',
|
|
||||||
alignItems: 'center',
|
|
||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
zIndex: 10,
|
alignItems: 'center',
|
||||||
},
|
},
|
||||||
priorityBadge: {
|
modalContainer: {
|
||||||
backgroundColor: colors.primary,
|
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,
|
borderRadius: 12,
|
||||||
paddingHorizontal: 8,
|
paddingHorizontal: 8,
|
||||||
paddingVertical: 3,
|
paddingVertical: 4,
|
||||||
},
|
},
|
||||||
priorityText: {
|
addonDetailChipText: {
|
||||||
|
fontSize: 13,
|
||||||
color: colors.white,
|
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: {
|
addonActions: {
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
|
|
@ -882,6 +1241,9 @@ const styles = StyleSheet.create({
|
||||||
padding: 6,
|
padding: 6,
|
||||||
marginRight: 8,
|
marginRight: 8,
|
||||||
},
|
},
|
||||||
|
communityAddonsList: {
|
||||||
|
paddingHorizontal: 20,
|
||||||
|
},
|
||||||
communityAddonItem: {
|
communityAddonItem: {
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
|
|
@ -971,30 +1333,6 @@ const styles = StyleSheet.create({
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
alignItems: 'center',
|
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;
|
export default AddonsScreen;
|
||||||
Loading…
Reference in a new issue