Skip to content

Commit 61fdde4

Browse files
YangGuoXuan-0503杨国璇
andauthored
fix: outline style (#215)
* fix: outline style * feat: update version * feat: update version * feat: update version --------- Co-authored-by: 杨国璇 <[email protected]>
1 parent e0ea51d commit 61fdde4

File tree

9 files changed

+145
-139
lines changed

9 files changed

+145
-139
lines changed

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@seafile/seafile-editor",
3-
"version": "1.0.118",
3+
"version": "1.0.121",
44
"description": "",
55
"main": "dist/index.js",
66
"scripts": {

src/constants/event-types.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ export const INTERNAL_EVENTS = {
66
ON_SELECT_ALL_CELL: 'on_select_all_cell',
77
ON_TOGGLE_IMAGE_POPOVER: 'on_toggle_image_popover',
88
OUTLINE_STATE_CHANGED: 'outline_state_changed',
9+
RESIZE_ARTICLE: 'resize_article',
910
};
1011

1112
export const EXTERNAL_EVENTS = {

src/containers/article-info/index.js

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import React, { useCallback, useState, useMemo, useEffect } from 'react';
22
import PropTypes from 'prop-types';
33
import ResizeWidth from './resize-width';
44
import EventBus from '../../utils/event-bus';
5-
import { EXTERNAL_EVENTS } from '../../constants/event-types';
5+
import { EXTERNAL_EVENTS, INTERNAL_EVENTS } from '../../constants/event-types';
66

77
import './style.css';
88

@@ -34,13 +34,16 @@ const ArticleInfo = ({ isVisible }) => {
3434
}, []);
3535

3636
const resizeWidthEnd = useCallback((width) => {
37-
const panelWidth = JSON.parse(window.localStorage.getItem('sf-editor-panel-width') || '{}');
38-
window.localStorage.setItem('sf-editor-panel-width', JSON.stringify({ ...panelWidth, width }));
37+
const settings = JSON.parse(window.localStorage.getItem('sf-editor') || '{}');
38+
window.localStorage.setItem('sf-editor', JSON.stringify({ ...settings, panelWidth: width }));
39+
const eventBus = EventBus.getInstance();
40+
eventBus.dispatch(INTERNAL_EVENTS.RESIZE_ARTICLE);
3941
}, []);
4042

4143
useEffect(() => {
42-
const panelWidth = JSON.parse(window.localStorage.getItem('sf-editor-panel-width', '{}')) || {};
43-
const width = Math.max(MIN_PANEL_WIDTH, Math.min(parseInt(panelWidth.width, 10) || MIN_PANEL_WIDTH, MAX_PANEL_WIDTH));
44+
const settings = JSON.parse(window.localStorage.getItem('sf-editor', '{}')) || {};
45+
const { panelWidth } = settings;
46+
const width = Math.max(MIN_PANEL_WIDTH, Math.min(parseInt(panelWidth, 10) || MIN_PANEL_WIDTH, MAX_PANEL_WIDTH));
4447
setWidth(width);
4548
}, []);
4649

@@ -57,6 +60,11 @@ const ArticleInfo = ({ isVisible }) => {
5760
// eslint-disable-next-line react-hooks/exhaustive-deps
5861
}, []);
5962

63+
useEffect(() => {
64+
const eventBus = EventBus.getInstance();
65+
eventBus.dispatch(INTERNAL_EVENTS.RESIZE_ARTICLE);
66+
}, [isVisible, fileDetails]);
67+
6068
const { component: fileDetailsComponent, props: fileDetailsProps } = fileDetails || {};
6169
return (
6270
<div className="sf-article-info-container-wrapper" style={containerWrapperStyle}>

src/containers/outline/index.js

Lines changed: 58 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import React, { useCallback, useEffect, useState } from 'react';
22
import PropTypes from 'prop-types';
33
import { useTranslation } from 'react-i18next';
4+
import classnames from 'classnames';
45
import OutlineItem from './outline-item';
56
import { useScrollContext } from '../../hooks/use-scroll-context';
67
import { TRANSLATE_NAMESPACE } from '../../constants';
@@ -9,6 +10,20 @@ import { INTERNAL_EVENTS } from '../../constants/event-types';
910

1011
import './style.css';
1112

13+
export const getOutlineSetting = () => {
14+
const currentValue = localStorage.getItem('sf-editor');
15+
const config = currentValue ? JSON.parse(currentValue) : {};
16+
const { outlineOpen = false } = config;
17+
return outlineOpen;
18+
};
19+
20+
export const setOutlineSetting = (isShown) => {
21+
const currentValue = localStorage.getItem('sf-editor');
22+
const config = currentValue ? JSON.parse(currentValue) : {};
23+
config['outlineOpen'] = isShown;
24+
localStorage.setItem('sf-editor', JSON.stringify(config));
25+
};
26+
1227
const getHeaderList = (children) => {
1328
const headerList = [];
1429
children.forEach((node) => {
@@ -23,7 +38,6 @@ const Outline = ({ editor }) => {
2338
const { t } = useTranslation(TRANSLATE_NAMESPACE);
2439
const scrollRef = useScrollContext();
2540
const [headerList, setHeaderList] = useState([]);
26-
const [activeId, setActiveId] = useState('');
2741
const [isShown, setIsShown] = useState(false);
2842
const [scrollLeft, setScrollLeft] = useState(0);
2943

@@ -32,47 +46,19 @@ const Outline = ({ editor }) => {
3246
setHeaderList(headerList);
3347
}, [editor.children]);
3448

35-
const handleScroll = useCallback((e) => {
36-
const scrollTop = scrollRef.current.scrollTop;
37-
const styles = getComputedStyle(scrollRef?.current);
38-
const paddingTop = parseInt(styles.paddingTop);
39-
for (let i = 0; i < headerList.length; i++) {
40-
const headerItem = headerList[i];
41-
const dom = document.getElementById(headerItem.id);
42-
const { offsetTop, offsetHeight } = dom;
43-
const styles = getComputedStyle(dom);
44-
const marginTop = parseInt(styles.marginTop);
45-
if (offsetTop + offsetHeight + marginTop > scrollTop - paddingTop) {
46-
setActiveId(headerItem.id);
47-
break;
48-
}
49-
}
50-
}, [headerList, scrollRef]);
51-
52-
useEffect(() => {
53-
let observerRefValue = null;
54-
if (scrollRef.current) {
55-
scrollRef.current.addEventListener('scroll', handleScroll);
56-
observerRefValue = scrollRef.current;
57-
}
58-
59-
return () => {
60-
observerRefValue.removeEventListener('scroll', handleScroll);
61-
};
62-
}, [handleScroll, scrollRef]);
49+
const updateOutlineState = useCallback((nextState) => {
50+
setOutlineSetting(nextState);
51+
setIsShown(nextState);
52+
const eventBus = EventBus.getInstance();
53+
eventBus.dispatch(INTERNAL_EVENTS.OUTLINE_STATE_CHANGED);
54+
}, []);
6355

6456
const toggleShow = useCallback(() => {
65-
setIsShown(prevIsShown => {
66-
const newIsShown = !prevIsShown;
67-
setTimeout(() => {
68-
const eventBus = EventBus.getInstance();
69-
eventBus.dispatch(INTERNAL_EVENTS.OUTLINE_STATE_CHANGED, newIsShown);
70-
}, 0);
71-
return newIsShown;
72-
});
73-
}, []);
57+
const nextState = !isShown;
58+
updateOutlineState(nextState);
59+
}, [isShown, updateOutlineState]);
7460

75-
useEffect(() => {
61+
useEffect(() => {
7662
if (!scrollRef.current) return;
7763

7864
const updateScrollLeft = () => {
@@ -86,35 +72,42 @@ const Outline = ({ editor }) => {
8672
};
8773
}, [scrollRef]);
8874

75+
useEffect(() => {
76+
const outlineState = getOutlineSetting();
77+
console.log(outlineState);
78+
updateOutlineState(outlineState);
79+
// eslint-disable-next-line react-hooks/exhaustive-deps
80+
}, []);
81+
8982
return (
90-
<div className="sf-editor-outline" style={{ left: -scrollLeft }}>
91-
{isShown && (
92-
<>
93-
<div className="sf-editor-outline-header">
94-
<h2 className="sf-editor-outline-header_title">{t('Outline')}</h2>
95-
<span className="sf-editor-outline-header_close iconfont icon-x" onClick={toggleShow}></span>
96-
</div>
97-
{headerList.length === 0 ? (
98-
<div className="empty-container">{t('No_outline')}</div>
99-
) : (
100-
<div className="sf-editor-outline-list-container">
101-
{headerList.map((node, index) => (
102-
<OutlineItem key={index} node={node} activeId={activeId} />
103-
))}
83+
<div className={classnames('sf-editor-outline-wrapper', { 'active': isShown })} style={{ left: -scrollLeft }}>
84+
<div className="sf-editor-outline" >
85+
{isShown && (
86+
<>
87+
<div className="sf-editor-outline-header">
88+
<h2 className="sf-editor-outline-header_title">{t('Outline')}</h2>
89+
<span className="sf-editor-outline-header_close iconfont icon-x" onClick={toggleShow}></span>
10490
</div>
105-
)}
106-
</>
107-
)}
91+
{headerList.length === 0 ? (
92+
<div className="empty-container">{t('No_outline')}</div>
93+
) : (
94+
<div className="sf-editor-outline-list-container">
95+
{headerList.map((node, index) => (
96+
<OutlineItem key={index} node={node} />
97+
))}
98+
</div>
99+
)}
100+
</>
101+
)}
102+
</div>
108103
{!isShown && (
109-
<>
110-
<span
111-
id="sf-editor-outline-menu"
112-
className="sf-editor-outline-menu sf-edito-tooltip iconfont icon-outline"
113-
onClick={toggleShow}
114-
>
115-
<span className="custom-tooltip">{t('Outline')}</span>
116-
</span>
117-
</>
104+
<span
105+
id="sf-editor-outline-menu"
106+
className="sf-editor-outline-menu sf-editor-tooltip iconfont icon-outline"
107+
onClick={toggleShow}
108+
>
109+
<span className="custom-tooltip">{t('Outline')}</span>
110+
</span>
118111
)}
119112
</div>
120113
);

src/containers/outline/outline-item.js

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,36 @@
1-
import React, { useCallback } from 'react';
1+
import React, { useCallback, useState } from 'react';
22
import PropTypes from 'prop-types';
33
import classNames from 'classnames';
44

5-
const OutlineItem = ({ node, activeId }) => {
5+
const OutlineItem = ({ node }) => {
6+
const [isHighlighted, setIsHighlighted] = useState(false);
7+
8+
const onMouseOver = useCallback(() => {
9+
setIsHighlighted(true);
10+
}, []);
11+
12+
const onMouseOut = useCallback(() => {
13+
setIsHighlighted(false);
14+
}, []);
15+
616
const onItemClick = useCallback(() => {
717
const { id } = node;
818
document.getElementById(id).scrollIntoView();
919
}, [node]);
1020

11-
const className = classNames({
12-
'outline-h2': node.type === 'header2',
13-
'outline-h3': node.type === 'header3',
14-
'active': node.id === activeId,
21+
const className = classNames('sf-editor-outline-item', {
22+
'pl-5': node.type === 'header2',
23+
'pl-7': node.type === 'header3',
24+
'active': isHighlighted,
1525
});
1626

1727
return (
18-
<div className={className} onClick={onItemClick}>
28+
<div
29+
className={className}
30+
onClick={onItemClick}
31+
onMouseOver={onMouseOver}
32+
onMouseOut={onMouseOut}
33+
>
1934
{node.children.map(child => child.text).join('')}
2035
</div>
2136
);

0 commit comments

Comments
 (0)