diff --git a/src/screens/AddonsScreen.tsx b/src/screens/AddonsScreen.tsx index 0d1f0a8..4af15cd 100644 --- a/src/screens/AddonsScreen.tsx +++ b/src/screens/AddonsScreen.tsx @@ -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 ( - - + + + {/* Header */} - Addons - - - - - - - - - - - - handleAddAddon()} - disabled={!addonUrl || installing} + style={styles.backButton} + onPress={() => navigation.goBack()} > - {installing ? ( - - ) : ( - - )} + + Settings + + + {/* Reorder Mode Toggle Button */} + + + + + {/* Refresh Button */} + + + + - + + + Addons + {reorderMode && (Reorder Mode)} + + + {reorderMode && ( + + + + Addons at the top have higher priority when loading content + + + )} + {loading ? ( - Loading addons... ) : ( - item.id} - style={styles.list} - contentContainerStyle={styles.listContent} - ListEmptyComponent={() => ( - - - No addons installed - Add an addon using the URL field above + + {/* Overview Section */} + + OVERVIEW + + + + + + + + + + {/* Hide Add Addon Section in reorder mode */} + {!reorderMode && ( + + ADD NEW ADDON + + + handleAddAddon()} + disabled={installing || !addonUrl} + > + + {installing ? 'Loading...' : 'Add Addon'} + + + )} - /> + + {/* Installed Addons Section */} + + + {reorderMode ? "DRAG ADDONS TO REORDER" : "INSTALLED ADDONS"} + + + {addons.length === 0 ? ( + + + No addons installed + + ) : ( + addons.map((addon, index) => ( + + {renderAddonItem({ item: addon, index })} + + )) + )} + + + + {/* Separator */} + + + {/* Community Addons Section */} + + COMMUNITY ADDONS + + {communityLoading ? ( + + + + ) : communityError ? ( + + + {communityError} + + ) : communityAddons.length === 0 ? ( + + + No community addons available + + ) : ( + communityAddons.map((item, index) => ( + + + + {item.manifest.logo ? ( + + ) : ( + + + + )} + + {item.manifest.name} + + v{item.manifest.version || 'N/A'} + + + {item.manifest.types && item.manifest.types.length > 0 + ? item.manifest.types.map(t => t.charAt(0).toUpperCase() + t.slice(1)).join(' • ') + : 'General'} + + + + + {item.manifest.behaviorHints?.configurable && ( + handleConfigureAddon(item.manifest, item.transportUrl)} + > + + + )} + handleAddAddon(item.transportUrl)} + disabled={installing} + > + {installing ? ( + + ) : ( + + )} + + + + + + {item.manifest.description + ? (item.manifest.description.length > 100 + ? item.manifest.description.substring(0, 100) + '...' + : item.manifest.description) + : 'No description provided.'} + + + + )) + )} + + + )} - {/* Community Addons Section */} - - Community Addons - {communityLoading ? ( - - - Loading community addons... - - ) : communityError ? ( - - - {communityError} - - ) : ( - item.manifest.id} - horizontal - showsHorizontalScrollIndicator={false} - style={styles.communityList} - contentContainerStyle={styles.communityListContent} - /> - )} - - - {/* Confirmation Modal */} + {/* Addon Details Confirmation Modal */} setShowConfirmModal(false)} + onRequestClose={() => { + setShowConfirmModal(false); + setAddonDetails(null); + }} > - + - Install Addon {addonDetails && ( <> - {addonDetails.name} - {addonDetails.description} + + Install Addon + { + setShowConfirmModal(false); + setAddonDetails(null); + }} + > + + + + + + + {/* @ts-ignore */} + {addonDetails.logo ? ( + + ) : ( + + + + )} + {addonDetails.name} + v{addonDetails.version || '1.0.0'} + + + + Description + + {addonDetails.description || 'No description available'} + + + + {addonDetails.types && addonDetails.types.length > 0 && ( + + Supported Types + + {addonDetails.types.map((type, index) => ( + + {type} + + ))} + + + )} + + {addonDetails.catalogs && addonDetails.catalogs.length > 0 && ( + + Catalogs + + {addonDetails.catalogs.map((catalog, index) => ( + + + {catalog.type} - {catalog.id} + + + ))} + + + )} + + + + { + setShowConfirmModal(false); + setAddonDetails(null); + }} + > + Cancel + + + {installing ? ( + + ) : ( + Install + )} + + )} - - setShowConfirmModal(false)} - > - Cancel - - - Install - - @@ -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; \ No newline at end of file