import React, { Suspense } from 'react'; import PropTypes from 'prop-types'; import watermark from 'watermark-dom'; import { I18nextProvider } from 'react-i18next'; import i18n from '../../_i18n/i18n-sdoc-editor'; import { seafileAPI } from '../../utils/seafile-api'; import { gettext, siteName } from '../../utils/constants'; import { Utils } from '../../utils/utils'; import toaster from '../toast'; import IconButton from '../icon-button'; import FileInfo from './file-info'; import FileToolbar from './file-toolbar'; import CommentPanel from './comment-panel'; import OnlyofficeFileToolbar from './onlyoffice-file-toolbar'; import EmbeddedFileDetails from '../dirent-detail/embedded-file-details'; import { MetadataMiddlewareProvider, MetadataStatusProvider } from '../../hooks'; import Loading from '../loading'; import WebSocketClient from '../../utils/websocket-service'; import ResizeWidth from './resize-width'; import LocalStorage from '../../utils/local-storage-utils'; import '../../css/file-view.css'; const propTypes = { onSave: PropTypes.func, content: PropTypes.object.isRequired, isSaving: PropTypes.bool, needSave: PropTypes.bool, isOnlyofficeFile: PropTypes.bool, setImageScale: PropTypes.func, rotateImage: PropTypes.func }; const { isStarred, isLocked, lockedByMe, repoID, fileUuid, filePath, filePerm, enableWatermark, userNickName, fileName, repoEncrypted, isRepoAdmin, fileType } = window.app.pageOptions; const MIN_PANEL_WIDTH = 360; const MAX_PANEL_WIDTH = 620; class FileView extends React.Component { constructor(props) { super(props); const storedIsHeaderShown = localStorage.getItem('sf_onlyoffile_file_view_header_shown'); this.state = { isStarred: isStarred, isLocked: isLocked, lockedByMe: lockedByMe, isCommentPanelOpen: false, isHeaderShown: (storedIsHeaderShown === null) || (storedIsHeaderShown == 'true'), isDetailsPanelOpen: false, isCommentUpdated: false, width: MIN_PANEL_WIDTH, }; this.socketManager = new WebSocketClient(this.onMessageCallback, repoID); } componentDidMount() { const fileIcon = Utils.getFileIconUrl(fileName); document.getElementById('favicon').href = fileIcon; const newfileType = fileName?.split('.').pop(); const settings = LocalStorage.getItem(`${newfileType}_detail_storage`) || {}; const { panelWidth } = settings; const width = Math.max( MIN_PANEL_WIDTH, Math.min(parseInt(panelWidth, 10) || MIN_PANEL_WIDTH, MAX_PANEL_WIDTH) ); this.setState({ width }); } onMessageCallback = (data) => { const { type, content } = data; if (type === 'comment-update') { const { repo_id, file_uuid } = content; if (repoID === repo_id && file_uuid === fileUuid) { if (!this.state.isCommentPanelOpen) { this.setState({ isCommentUpdated: true }); } else { this.commentPanelRef.forceUpdate(); } } } }; toggleCommentPanel = () => { this.setState({ isCommentPanelOpen: !this.state.isCommentPanelOpen, isDetailsPanelOpen: false, isCommentUpdated: false, }); }; toggleDetailsPanel = () => { this.setState({ isDetailsPanelOpen: !this.state.isDetailsPanelOpen, isCommentPanelOpen: false, }); }; toggleStar = () => { if (this.state.isStarred) { seafileAPI.unstarItem(repoID, filePath).then((res) => { this.setState({ isStarred: false }); }).catch((error) => { const errorMsg = Utils.getErrorMsg(error); toaster.danger(errorMsg); }); } else { seafileAPI.starItem(repoID, filePath).then((res) => { this.setState({ isStarred: true }); }).catch((error) => { const errorMsg = Utils.getErrorMsg(error); toaster.danger(errorMsg); }); } }; toggleLockFile = () => { if (this.state.isLocked) { seafileAPI.unlockfile(repoID, filePath).then((res) => { this.setState({ isLocked: false, lockedByMe: false }); }).catch((error) => { const errorMsg = Utils.getErrorMsg(error); toaster.danger(errorMsg); }); } else { seafileAPI.lockfile(repoID, filePath).then((res) => { this.setState({ isLocked: true, lockedByMe: true }); }).catch((error) => { const errorMsg = Utils.getErrorMsg(error); toaster.danger(errorMsg); }); } }; toggleHeader = () => { this.setState({ isHeaderShown: !this.state.isHeaderShown }, () => { localStorage.setItem('sf_onlyoffile_file_view_header_shown', String(this.state.isHeaderShown)); }); }; setCommentPanelRef = (ref) => { this.commentPanelRef = ref; }; panelWrapperStyle = () => { let style = { width: this.state.width, zIndex: 101, }; if (!style.width || style.width < MIN_PANEL_WIDTH) { style.width = MIN_PANEL_WIDTH; } else if (style.width > MAX_PANEL_WIDTH) { style.width = MAX_PANEL_WIDTH; } return style; }; resizeWidth = (width) => { this.setState({ width: width }); }; resizeWidthEnd = (width) => { const newfileType = fileName?.split('.').pop(); const settings = LocalStorage.getItem(`${newfileType}_detail_storage`) || {}; LocalStorage.setItem(`${newfileType}_detail_storage`, JSON.stringify({ ...settings, panelWidth: width })); }; render() { const { isOnlyofficeFile = false } = this.props; const { isDetailsPanelOpen, isHeaderShown } = this.state; const repoInfo = { permission: filePerm, encrypted: repoEncrypted, is_admin: isRepoAdmin, }; return ( }>
{isOnlyofficeFile ? : }
{(isOnlyofficeFile && !isHeaderShown) && } {this.props.content} {this.state.isCommentPanelOpen && } {isDetailsPanelOpen && (
)}
); } } if (enableWatermark) { watermark.init({ watermark_txt: `${siteName} ${userNickName}`, watermark_alpha: 0.075 }); } FileView.propTypes = propTypes; export default FileView;