UNPKG

@oxyhq/services

Version:

OxyHQ Expo/React Native SDK — UI components, screens, and native features

409 lines (402 loc) 17.8 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.FileViewer = void 0; var _react = _interopRequireWildcard(require("react")); var _reactNative = require("react-native"); var _expoImage = require("expo-image"); var _vectorIcons = require("@expo/vector-icons"); var _fileManagement = require("../../utils/fileManagement.js"); var _styles = require("./styles.js"); var _GroupedSection = require("../GroupedSection.js"); var _jsxRuntime = require("react/jsx-runtime"); function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); } // @ts-ignore - MaterialCommunityIcons is available at runtime const FileViewer = ({ file, fileContent, loadingFileContent, showFileDetailsInViewer, onToggleDetails, onClose, onDownload, onDelete, themeStyles, isOwner }) => { const isImage = file.contentType.startsWith('image/'); const isText = file.contentType.startsWith('text/') || file.contentType.includes('json') || file.contentType.includes('xml') || file.contentType.includes('javascript') || file.contentType.includes('typescript'); const isPDF = file.contentType.includes('pdf'); const isVideo = file.contentType.startsWith('video/'); const isAudio = file.contentType.startsWith('audio/'); const backgroundColor = isImage && fileContent ? 'transparent' : themeStyles.backgroundColor; const borderColor = themeStyles.borderColor; const [containerWidth, setContainerWidth] = (0, _react.useState)(0); const [imageDimensions, setImageDimensions] = (0, _react.useState)(null); // Load image dimensions when image content is available (0, _react.useEffect)(() => { if (isImage && fileContent) { _reactNative.Image.getSize(fileContent, (width, height) => { setImageDimensions({ width, height }); }, () => { // Fallback if dimensions can't be loaded setImageDimensions({ width: 400, height: 400 }); }); } else { setImageDimensions(null); } }, [isImage, fileContent]); // Calculate display size based on natural dimensions and max constraints // Use natural size when smaller, scale down when larger const imageDisplaySize = (0, _react.useMemo)(() => { if (!imageDimensions || !containerWidth) { // Return default size while loading return { width: 400, height: 400 }; } const maxWidth = containerWidth - 24; // Account for padding const maxHeight = 500; const aspectRatio = imageDimensions.width / imageDimensions.height; // Start with natural dimensions let displayWidth = imageDimensions.width; let displayHeight = imageDimensions.height; // Only scale down if exceeds max width if (displayWidth > maxWidth) { displayWidth = maxWidth; displayHeight = displayWidth / aspectRatio; } // Only scale down if exceeds max height if (displayHeight > maxHeight) { displayHeight = maxHeight; displayWidth = displayHeight * aspectRatio; } return { width: displayWidth, height: displayHeight }; }, [imageDimensions, containerWidth]); const fileDetailItems = (0, _react.useMemo)(() => { const items = [{ id: 'filename', icon: 'file-document', iconColor: themeStyles.colors.iconSecurity, title: 'File Name', subtitle: file.filename }, { id: 'size', icon: 'server', iconColor: themeStyles.colors.iconStorage, title: 'Size', subtitle: (0, _fileManagement.formatFileSize)(file.length) }, { id: 'type', icon: 'code-tags', iconColor: themeStyles.colors.iconData, title: 'Type', subtitle: file.contentType }, { id: 'uploaded', icon: 'clock', iconColor: themeStyles.colors.iconPersonalInfo, title: 'Uploaded', subtitle: new Date(file.uploadDate).toLocaleString() }]; if (file.metadata?.description) { items.push({ id: 'description', icon: 'text', iconColor: themeStyles.colors.iconData, title: 'Description', subtitle: file.metadata.description }); } items.push({ id: 'fileId', icon: 'key', iconColor: themeStyles.colors.iconSecurity, title: 'File ID', subtitle: file.id }); return items; }, [file, themeStyles.colors]); return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, { style: [_styles.fileManagementStyles.fileViewerContainer, { backgroundColor }], children: [isImage && fileContent && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, { children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_expoImage.Image, { source: { uri: fileContent }, style: _styles.fileManagementStyles.backgroundImage, contentFit: "cover", blurRadius: 50, transition: 120, cachePolicy: "memory-disk" }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, { style: [_styles.fileManagementStyles.backgroundOverlay, { backgroundColor: themeStyles.isDarkTheme ? 'rgba(0, 0, 0, 0.6)' : 'rgba(255, 255, 255, 0.85)' }] })] }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, { style: [_styles.fileManagementStyles.floatingBackButton, { backgroundColor: themeStyles.colors.card }], onPress: onClose, children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_vectorIcons.MaterialCommunityIcons, { name: "arrow-left", size: 20, color: themeStyles.textColor }) }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, { style: [_styles.fileManagementStyles.floatingDownloadButton, { backgroundColor: themeStyles.colors.card }], onPress: () => onDownload(file.id, file.filename), children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_vectorIcons.MaterialCommunityIcons, { name: "download", size: 20, color: themeStyles.primaryColor }) }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.ScrollView, { style: _styles.fileManagementStyles.fileViewerContent, contentContainerStyle: _styles.fileManagementStyles.fileViewerContentContainer, children: loadingFileContent ? /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, { style: _styles.fileManagementStyles.fileViewerLoading, children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.ActivityIndicator, { size: "large", color: themeStyles.primaryColor }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, { style: [_styles.fileManagementStyles.fileViewerLoadingText, { color: themeStyles.textColor }], children: "Loading file content..." })] }) : isImage && fileContent ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, { style: _styles.fileManagementStyles.imageContainer, onLayout: e => { const width = e.nativeEvent.layout.width; if (width > 0) { setContainerWidth(width); } }, children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, { style: [_styles.fileManagementStyles.imageWrapper, { width: imageDisplaySize.width, height: imageDisplaySize.height }], children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_expoImage.Image, { source: { uri: fileContent }, style: { width: imageDisplaySize.width, height: imageDisplaySize.height }, contentFit: "contain", transition: 120, cachePolicy: "memory-disk", onError: () => { // Image failed to load }, accessibilityLabel: file.filename }) }) }) : isText && fileContent ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, { style: [_styles.fileManagementStyles.textContainer, { backgroundColor: themeStyles.colors.card }], children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.ScrollView, { style: { flex: 1 }, nestedScrollEnabled: true, children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, { style: [_styles.fileManagementStyles.textContent, { color: themeStyles.textColor }], children: fileContent }) }) }) : isPDF && fileContent ? /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, { style: _styles.fileManagementStyles.unsupportedFileContainer, children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_vectorIcons.MaterialCommunityIcons, { name: "file-pdf-box", size: 64, color: themeStyles.colors.secondaryText }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, { style: [_styles.fileManagementStyles.unsupportedFileTitle, { color: themeStyles.textColor }], children: "PDF Preview Not Available" }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.Text, { style: [_styles.fileManagementStyles.unsupportedFileDescription, { color: themeStyles.colors.secondaryText }], children: ["PDF files cannot be previewed in this viewer.", '\n', "Download the file to view its contents."] }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.TouchableOpacity, { style: [_styles.fileManagementStyles.downloadButtonLarge, { backgroundColor: themeStyles.primaryColor }], onPress: () => onDownload(file.id, file.filename), children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_vectorIcons.MaterialCommunityIcons, { name: "download", size: 18, color: "#FFFFFF" }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, { style: _styles.fileManagementStyles.downloadButtonText, children: "Download PDF" })] })] }) : isVideo && fileContent ? /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, { style: _styles.fileManagementStyles.unsupportedFileContainer, children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_vectorIcons.MaterialCommunityIcons, { name: "video-outline", size: 64, color: themeStyles.colors.secondaryText }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, { style: [_styles.fileManagementStyles.unsupportedFileTitle, { color: themeStyles.textColor }], children: "Video Playback Not Available" }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.Text, { style: [_styles.fileManagementStyles.unsupportedFileDescription, { color: themeStyles.colors.secondaryText }], children: ["Video playback is not supported in this viewer.", '\n', "Download the file to view it."] }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.TouchableOpacity, { style: [_styles.fileManagementStyles.downloadButtonLarge, { backgroundColor: themeStyles.primaryColor }], onPress: () => onDownload(file.id, file.filename), children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_vectorIcons.MaterialCommunityIcons, { name: "download", size: 18, color: "#FFFFFF" }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, { style: _styles.fileManagementStyles.downloadButtonText, children: "Download Video" })] })] }) : isAudio && fileContent ? /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, { style: _styles.fileManagementStyles.unsupportedFileContainer, children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_vectorIcons.MaterialCommunityIcons, { name: "music-note-outline", size: 64, color: themeStyles.colors.secondaryText }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, { style: [_styles.fileManagementStyles.unsupportedFileTitle, { color: themeStyles.textColor }], children: "Audio Playback Not Available" }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.Text, { style: [_styles.fileManagementStyles.unsupportedFileDescription, { color: themeStyles.colors.secondaryText }], children: ["Audio playback is not supported in this viewer.", '\n', "Download the file to listen to it."] }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.TouchableOpacity, { style: [_styles.fileManagementStyles.downloadButtonLarge, { backgroundColor: themeStyles.primaryColor }], onPress: () => onDownload(file.id, file.filename), children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_vectorIcons.MaterialCommunityIcons, { name: "download", size: 18, color: "#FFFFFF" }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, { style: _styles.fileManagementStyles.downloadButtonText, children: "Download Audio" })] })] }) : /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, { style: _styles.fileManagementStyles.unsupportedFileContainer, children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_vectorIcons.MaterialCommunityIcons, { name: "file-outline", size: 64, color: themeStyles.colors.secondaryText }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, { style: [_styles.fileManagementStyles.unsupportedFileTitle, { color: themeStyles.textColor }], children: "Preview Not Available" }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.Text, { style: [_styles.fileManagementStyles.unsupportedFileDescription, { color: themeStyles.colors.secondaryText }], children: ["This file type cannot be previewed.", '\n', "Download the file to view its contents."] }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.TouchableOpacity, { style: [_styles.fileManagementStyles.downloadButtonLarge, { backgroundColor: themeStyles.primaryColor }], onPress: () => onDownload(file.id, file.filename), children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_vectorIcons.MaterialCommunityIcons, { name: "download", size: 18, color: "#FFFFFF" }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, { style: _styles.fileManagementStyles.downloadButtonText, children: "Download File" })] })] }) }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, { style: [_styles.fileManagementStyles.fileDetailsSection, { backgroundColor: themeStyles.colors.card }], children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, { style: _styles.fileManagementStyles.fileDetailsSectionHeader, children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, { style: [_styles.fileManagementStyles.fileDetailsSectionTitle, { color: themeStyles.textColor }], children: "File Details" }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, { style: _styles.fileManagementStyles.fileDetailsSectionToggle, onPress: onToggleDetails, children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_vectorIcons.MaterialCommunityIcons, { name: showFileDetailsInViewer ? "chevron-up" : "chevron-down", size: 20, color: themeStyles.colors.secondaryText }) })] }), showFileDetailsInViewer && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, { children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, { style: _styles.fileManagementStyles.fileDetailsSectionContent, children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_GroupedSection.GroupedSection, { items: fileDetailItems }) }), isOwner && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, { style: _styles.fileManagementStyles.fileDetailsActions, children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.TouchableOpacity, { style: [_styles.fileManagementStyles.fileDetailsActionButton, { backgroundColor: themeStyles.dangerColor }], onPress: () => { onClose(); onDelete(file.id, file.filename); }, children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_vectorIcons.MaterialCommunityIcons, { name: "delete", size: 16, color: "#FFFFFF" }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, { style: _styles.fileManagementStyles.fileDetailsActionText, children: "Delete" })] }) })] })] })] }); }; exports.FileViewer = FileViewer; //# sourceMappingURL=FileViewer.js.map