@oxyhq/services
Version:
409 lines (402 loc) • 17.8 kB
JavaScript
;
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