diff --git a/frontend/src/components/file-view/comment-panel.js b/frontend/src/components/file-view/comment-panel.js
index 9bf0aec521..d5d496f857 100644
--- a/frontend/src/components/file-view/comment-panel.js
+++ b/frontend/src/components/file-view/comment-panel.js
@@ -6,10 +6,14 @@ import { Utils } from '../../utils/utils';
import toaster from '../toast';
import CommentList from './comment-widget/comment-list';
import ReplyList from './comment-widget/reply-list';
+import LocalStorage from '../../utils/local-storage-utils';
+import ResizeWidth from './resize-width';
import '../../css/comments-list.css';
-const { username, repoID, filePath, fileUuid } = window.app.pageOptions;
+const { username, repoID, filePath, fileUuid, fileName } = window.app.pageOptions;
+const MIN_PANEL_WIDTH = 360;
+const MAX_PANEL_WIDTH = 620;
const CommentPanelPropTypes = {
toggleCommentPanel: PropTypes.func.isRequired,
@@ -28,10 +32,27 @@ class CommentPanel extends React.Component {
participants: null,
relatedUsers: null,
currentComment: null,
+ width: MIN_PANEL_WIDTH,
};
this.toBeAddedParticipant = [];
}
+ 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;
+ };
+
forceUpdate = () => {
this.listComments();
this.getParticipants();
@@ -163,6 +184,15 @@ class CommentPanel extends React.Component {
this.listComments();
this.getParticipants();
this.listRepoRelatedUsers();
+
+ const newfileType = fileName?.split('.').pop();
+ const settings = LocalStorage.getItem(`${newfileType}_comment_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 });
}
onClickComment = (currentComment) => {
@@ -173,10 +203,21 @@ class CommentPanel extends React.Component {
this.setState({ currentComment: null });
};
+ resizeWidth = (width) => {
+ this.setState({ width: width });
+ };
+
+ resizeWidthEnd = (width) => {
+ const newfileType = fileName?.split('.').pop();
+ const settings = LocalStorage.getItem(`${newfileType}_comment_storage`) || {};
+ LocalStorage.setItem(`${newfileType}_comment_storage`, JSON.stringify({ ...settings, panelWidth: width }));
+ };
+
render() {
const { commentsList } = this.state;
return (
-
+
+
{
this.state.currentComment ?
{
@@ -144,6 +158,31 @@ class FileView extends React.Component {
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;
@@ -209,13 +248,17 @@ class FileView extends React.Component {
{isDetailsPanelOpen && (
-
+
+
+
+
)}
diff --git a/frontend/src/components/file-view/resize-width.js b/frontend/src/components/file-view/resize-width.js
new file mode 100644
index 0000000000..29ca27b56b
--- /dev/null
+++ b/frontend/src/components/file-view/resize-width.js
@@ -0,0 +1,148 @@
+import React, { useCallback, useEffect, useRef, useState } from 'react';
+import PropTypes from 'prop-types';
+
+import '../../css/resize-width.css';
+
+const ResizeWidth = ({ minWidth, maxWidth, resizeWidth: resizeWidthAPI, resizeWidthEnd }) => {
+ const [isShowHandlerBar, setIsShowHandlerBar] = useState(false);
+ const [drag, setDrag] = useState(null);
+
+ const handlerRef = useRef(null);
+ const handlerBarRef = useRef(null);
+
+
+ const setHandlerBarTop = (handlerTop) => {
+ if (!handlerBarRef.current || handlerTop < 0) return;
+ handlerBarRef.current.style.top = handlerTop + 'px';
+ };
+
+ const setHandlerBarPosition = (event) => {
+ if (!handlerRef.current) return;
+ const { top } = handlerRef.current.getBoundingClientRect();
+ const handlerTop = event.pageY - top - 26 / 2;
+ setHandlerBarTop(handlerTop);
+ };
+
+ const getWidthFromMouseEvent = (event) => {
+ return event.pageX || (event.touches && event.touches[0] && event.touches[0].pageX) ||
+ (event.changedTouches && event.changedTouches[event.changedTouches.length - 1].pageX);
+ };
+
+ const calculateResizedWidth = (event) => {
+ const width = getWidthFromMouseEvent(event);
+ const resizedWidth = document.body.clientWidth - width;
+ if ((minWidth && resizedWidth < minWidth) || (maxWidth && resizedWidth > maxWidth)) return -1;
+ return resizedWidth;
+ };
+
+ const onResizeWidth = (event) => {
+ const resizedWidth = calculateResizedWidth(event);
+ if (resizedWidth < 0) return;
+ if (resizeWidthAPI) {
+ resizeWidthAPI(resizedWidth);
+ }
+ };
+
+ const onDrag = (event) => {
+ onResizeWidth(event);
+ };
+
+ const onDragStart = useCallback((event) => {
+ if (event && event.dataTransfer && event.dataTransfer.setData) {
+ event.dataTransfer.setData('text/plain', 'dummy');
+ }
+ }, []);
+
+ const onDragEnd = (event) => {
+ onResizeWidth(event);
+ };
+
+ const onMouseLeave = () => {
+ setIsShowHandlerBar(false);
+ };
+
+ const onMouseEnter = (event) => {
+ setIsShowHandlerBar(true);
+ setHandlerBarPosition(event);
+ if (handlerRef.current) {
+ handlerRef.current.addEventListener('mouseleave', onMouseLeave);
+ }
+ };
+
+ const onMouseOver = (event) => {
+ setHandlerBarPosition(event);
+ };
+
+ const onMouseDown = (event) => {
+ event.preventDefault && event.preventDefault();
+ const currDrag = onDragStart(event);
+ if (currDrag === null && event.button !== 0) return;
+
+ window.addEventListener('mouseup', onMouseUp);
+ window.addEventListener('mousemove', onMouseMove);
+
+ if (handlerRef.current) {
+ handlerRef.current.removeEventListener('mouseleave', onMouseLeave);
+ }
+
+ setDrag(currDrag);
+ };
+
+ const onMouseMove = (event) => {
+ event.preventDefault && event.preventDefault();
+ if (!drag === null) return;
+ onDrag(event);
+ };
+
+ const onMouseUp = (event) => {
+ window.removeEventListener('mouseup', onMouseUp);
+ window.removeEventListener('mousemove', onMouseMove);
+ onDragEnd(event, drag);
+ setHandlerBarTop(-9999);
+ setDrag(null);
+ setIsShowHandlerBar(false);
+ if (resizeWidthEnd) {
+ const resizeWidth = calculateResizedWidth(event);
+ if (resizeWidth < 0) return;
+ resizeWidthEnd(resizeWidth);
+ }
+ };
+
+ useEffect(() => {
+ return () => {
+ window.removeEventListener('mouseup', onMouseUp);
+ window.removeEventListener('mousemove', onMouseMove);
+ };
+
+ // eslint-disable-next-line
+ }, []);
+
+ return (
+
+
+ {isShowHandlerBar && (
+
+ )}
+
+
+ );
+};
+
+ResizeWidth.propTypes = {
+ minWidth: PropTypes.number,
+ maxWidth: PropTypes.number,
+ resizeWidth: PropTypes.func,
+ resizeWidthEnd: PropTypes.func,
+};
+
+export default ResizeWidth;
diff --git a/frontend/src/css/comments-list.css b/frontend/src/css/comments-list.css
index c1b1479194..d138dc8a1a 100644
--- a/frontend/src/css/comments-list.css
+++ b/frontend/src/css/comments-list.css
@@ -2,6 +2,7 @@
background: var(--bs-body-bg);
display: flex;
flex-direction: column;
+ position: relative;
}
.seafile-comment-title {
@@ -19,7 +20,7 @@
font-weight: 500;
}
-.seafile-comment-title .sdoc-icon-btn {
+.seafile-comment-title .sdoc-icon-btn {
display: inline-flex;
align-items: center;
justify-content: center;
diff --git a/frontend/src/css/file-view.css b/frontend/src/css/file-view.css
index 31b32a0fd0..0f4267003f 100644
--- a/frontend/src/css/file-view.css
+++ b/frontend/src/css/file-view.css
@@ -154,6 +154,11 @@ body {
z-index: 50;
}
+.seafile-file-detail-right-panel-wrapper {
+ display: flex;
+ position: relative;
+}
+
@keyframes move {
from {
right: -500px;
diff --git a/frontend/src/css/resize-width.css b/frontend/src/css/resize-width.css
new file mode 100644
index 0000000000..069829a6c1
--- /dev/null
+++ b/frontend/src/css/resize-width.css
@@ -0,0 +1,37 @@
+.seafile-resize-width-handler {
+ height: 100%;
+ position: absolute;
+ right: 0;
+ top: 0;
+ width: 6px;
+}
+
+.seafile-resize-width-handler.resize-handler-placement-right {
+ left: 0;
+ right: auto;
+}
+
+.seafile-resize-width-handler:hover {
+ cursor: col-resize;
+}
+
+.seafile-resize-width-handler .seafile-resize-width-handler-content {
+ background-color: initial;
+ height: 100%;
+ position: relative;
+ width: 2px;
+}
+
+.seafile-resize-width-handler:hover .seafile-resize-width-handler-content {
+ background-color: #ccc;
+}
+
+.seafile-resize-width-handler .seafile-resize-width-handler-bar {
+ background-color: #2d7ff9;
+ border-radius: 3px;
+ content: "";
+ left: 50%;
+ margin-left: -3px;
+ position: absolute;
+ width: 6px;
+}