Skip to content

Commit d422b65

Browse files
authoredJul 16, 2021
Merge pull request #14 from BUPTlhuanyu/restructure
Restructure
2 parents a028ec2 + 1e37234 commit d422b65

File tree

8 files changed

+503
-369
lines changed

8 files changed

+503
-369
lines changed
 

‎packages/views/src/components/useCodemirror/code.ts

+20
Original file line numberDiff line numberDiff line change
@@ -119,4 +119,24 @@ export function createCodemirror(ele: any) {
119119
});
120120
}
121121

122+
export const scrollToLine = (editor: codemirror.Editor, line: number) => {
123+
if (!editor || !editor.getDoc) {
124+
return;
125+
}
126+
// @ts-ignore
127+
editor.scrollTo(0, editor.charCoords({line}, 'local').top - editor.charCoords({line}, 'line').top);
128+
const textMarker = editor.getDoc().markText(
129+
// @ts-ignore
130+
{line: line - 1},
131+
{line},
132+
{
133+
css: 'background-color: #FFFAAA',
134+
atomic: true
135+
}
136+
);
137+
setTimeout(() => {
138+
textMarker.clear();
139+
}, 500);
140+
};
141+
122142
export default codemirror;

‎packages/views/src/electron/menu/index.ts

-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ export function registerContextMenu() {
3333

3434
export function registerTopMenuListener() {
3535
pandora.ipcRenderer.on(`pandora:${CREATE_FILE}`, () => {
36-
console.log('pandora:pandora:');
3736
fileEvent.emit(FS_CREATE_FILE);
3837
});
3938
pandora.ipcRenderer.on(`pandora:${CREATE_DIR}`, () => {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
.sider-panel-header {
2+
line-height: 30px;
3+
height: 30px;
4+
background-color: #f3f3f7;
5+
display: flex;
6+
justify-content: space-between;
7+
align-items: center;
8+
box-shadow: rgba(17, 17, 26, 0.1) 0px 2px 4px, rgba(17, 17, 26, 0.05) 0px 4px 8px;
9+
&-icon {
10+
display: flex;
11+
cursor: pointer;
12+
}
13+
&-back {
14+
&:hover {
15+
background: #e1e1e1;
16+
border-radius: 6px;
17+
}
18+
}
19+
.ant-input-affix-wrapper {
20+
border: none;
21+
width: 0%;
22+
animation: widthSpread .3s ease-in forwards;
23+
}
24+
.ant-input-affix-wrapper :focus{
25+
border-color: #FFB531;
26+
box-shadow: none;
27+
}
28+
.ant-input-affix-wrapper-focused {
29+
// border-color: #FFB531;
30+
border: none;
31+
box-shadow: none;
32+
}
33+
&-input {
34+
height: 20px;
35+
background: transparent;
36+
padding: 0;
37+
margin-right: 4px;
38+
margin-left: 4px;
39+
border-radius: 0;
40+
border-top: 0;
41+
border-left: 0;
42+
border-right: 0;
43+
&:focus, &:hover {
44+
border-color: #FFB531;
45+
box-shadow: none;
46+
}
47+
&-selected {
48+
background: #e1e1e1;
49+
border-radius: 6px;
50+
}
51+
.ant-input {
52+
font-size: 12px;
53+
background: transparent;
54+
}
55+
.ant-input-suffix {
56+
display: flex;
57+
}
58+
}
59+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
// 非受控,减少外层代码量
2+
import * as React from 'react';
3+
import './index.scss';
4+
import getClassname from 'views/src/utils/classMaker';
5+
6+
import Icon from 'views/src/components/icon';
7+
import {Input} from 'antd';
8+
9+
interface ISiderProps {
10+
className?: string;
11+
onBack?: React.MouseEventHandler<HTMLSpanElement>;
12+
onPressEnter?: (value: string, caseSensitive: boolean, wholeWord: boolean) => void;
13+
onCaseSensitive?: React.MouseEventHandler<HTMLSpanElement>;
14+
onCheckWholeWord?: React.MouseEventHandler<HTMLSpanElement>;
15+
focused?: boolean;
16+
}
17+
18+
export default function Header(props: ISiderProps) {
19+
const [caseSensitive, setCaseSensitive] = React.useState<boolean>(false);
20+
const [wholeWord, setWholeWord] = React.useState<boolean>(false);
21+
const inputRef = React.useRef<Input>(null);
22+
23+
const [className] = React.useState(() => {
24+
return getClassname([
25+
'sider-panel-header',
26+
props.className
27+
]);
28+
});
29+
30+
const onCaseSensitive = React.useCallback(() => {
31+
setCaseSensitive(!caseSensitive);
32+
}, [caseSensitive, setCaseSensitive, props.onCaseSensitive]);
33+
34+
const onCheckWholeWord = React.useCallback(() => {
35+
setWholeWord(!wholeWord);
36+
}, [wholeWord, setWholeWord, props.onCheckWholeWord]);
37+
38+
const onPressEnter = React.useCallback(
39+
e => {
40+
if (!e || !e.target) {
41+
return;
42+
}
43+
const value = e.target.value;
44+
typeof props.onPressEnter === 'function' && props.onPressEnter(value, caseSensitive, wholeWord);
45+
},
46+
[props.onPressEnter, caseSensitive, wholeWord]
47+
);
48+
49+
React.useEffect(() => {
50+
props.focused && inputRef.current && inputRef.current?.focus();
51+
}, [props.focused]);
52+
53+
return (
54+
<div className={className}>
55+
{/* TODO: renderProp */}
56+
<span className="sider-panel-header-icon sider-panel-header-back" onClick={props.onBack}>
57+
<Icon type="left" style={{fontSize: '20px'}} />
58+
</span>
59+
<Input
60+
ref={inputRef}
61+
onPressEnter={onPressEnter}
62+
placeholder="查找"
63+
className="sider-panel-header-input"
64+
suffix={
65+
<>
66+
<span
67+
title="区分大小写"
68+
className={`sider-panel-header-icon ${
69+
caseSensitive ? 'sider-panel-header-input-selected' : ''
70+
}`}
71+
onClick={onCaseSensitive}
72+
>
73+
<Icon type="case" style={{fontSize: '20px'}} />
74+
</span>
75+
<span
76+
title="查找整个单词"
77+
className={`sider-panel-header-icon ${
78+
wholeWord ? 'sider-panel-header-input-selected' : ''
79+
}`}
80+
onClick={onCheckWholeWord}
81+
>
82+
<Icon type="word" style={{fontSize: '20px'}} />
83+
</span>
84+
</>
85+
}
86+
/>
87+
</div>
88+
);
89+
};
90+
91+
function noop() {}
92+
Header.defaultProps = {
93+
className: '',
94+
onBack: noop,
95+
onPressEnter: noop,
96+
onCaseSensitive: noop,
97+
onCheckWholeWord: noop,
98+
focused: noop
99+
};

‎packages/views/src/pages/editor/components/sider/index.scss

+8
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,14 @@
148148
border-top-width: 1px;
149149
border-top-style: solid;
150150
}
151+
.sider-file-empty {
152+
display: flex;
153+
flex: 1;
154+
height: 100%;
155+
justify-content: center;
156+
align-items: center;
157+
color: #7a7a7a;
158+
}
151159
.sider-file-folder {
152160
background: transparent;
153161
overflow-x: auto;

‎packages/views/src/pages/editor/components/sider/index.tsx

+171-367
Large diffs are not rendered by default.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
/**
2+
* @file
3+
*/
4+
import produce from 'immer';
5+
6+
export function getRootPath(path: string) {
7+
if (typeof path !== 'string') {
8+
return '';
9+
}
10+
const lastIndex = path.lastIndexOf('/');
11+
let rootPath = path;
12+
if (path.indexOf('.') > 0) {
13+
rootPath = path.substring(0, lastIndex);
14+
}
15+
return rootPath;
16+
}
17+
18+
export function updateNodeData(nodeData: Record<string, any>, newName: string) {
19+
if (!nodeData || !nodeData.path || !newName) {
20+
return;
21+
}
22+
const lastIndexPath = nodeData.path.lastIndexOf('/');
23+
const parentPath = nodeData.path.substring(0, lastIndexPath);
24+
const newPath = `${parentPath}/${newName}`;
25+
const lastIndexExt = newName.lastIndexOf('.');
26+
nodeData.extension = lastIndexExt > 0 ? newName.substring(newName.lastIndexOf('.')) : '';
27+
nodeData.key = newPath;
28+
nodeData.path = newPath;
29+
nodeData.title = newName;
30+
nodeData.name = newName;
31+
nodeData.exist = true;
32+
}
33+
34+
function createFile(path: string, index: number) {
35+
return {
36+
extension: '.md',
37+
index: [],
38+
isLeaf: true,
39+
key: `${path}/Untitled${index}.md`,
40+
name: `Untitled${index}.md`,
41+
path: `${path}/Untitled${index}.md`,
42+
size: 0,
43+
title: `Untitled${index}.md`,
44+
type: 'file',
45+
exist: false
46+
};
47+
}
48+
49+
function createDir(path: string, index: number) {
50+
return {
51+
children: [],
52+
exist: false,
53+
size: 0,
54+
name: `Untitled Folder${index}`,
55+
title: `Untitled Folder${index}`,
56+
key: `${path}/Untitled Folder${index}`,
57+
path: `${path}/Untitled Folder${index}`,
58+
type: 'directory'
59+
};
60+
}
61+
62+
export function addToTreeData(tree: any, path: string, type: 'file' | 'directory') {
63+
let addedNode: Record<string, any> = {};
64+
let nextTree = produce(tree, (draftTree: any) => {
65+
let item = null;
66+
let root = draftTree[0];
67+
if (root) {
68+
let stack: Record<string, any> = [root];
69+
while (stack.length > 0) {
70+
let node = stack.pop();
71+
if (node.type === 'directory' && Array.isArray(node.children) && node.path === path) {
72+
let maxIndex = 1;
73+
for (let i of node.children) {
74+
let reg = type === 'file' ? /Untitled([^/]*)\.md$/ : /Untitled\sFolder([^/]*)$/;
75+
const match = reg.exec(i.path);
76+
if (match && match[1] && typeof +match[1] === 'number') {
77+
let curIndex = +match[1];
78+
if (!Number.isNaN(curIndex) && typeof curIndex === 'number' && curIndex > maxIndex) {
79+
maxIndex = curIndex;
80+
}
81+
}
82+
}
83+
maxIndex += 1;
84+
item = type === 'file' ? createFile(path, maxIndex) : createDir(path, maxIndex);
85+
node.children.push(item);
86+
addedNode = item;
87+
stack.length = 0;
88+
return;
89+
}
90+
if (node.children && node.children.length > 0) {
91+
let len = node.children.length;
92+
for (let i = 0; i < len; i++) {
93+
stack.push(node.children[i]);
94+
}
95+
}
96+
}
97+
}
98+
});
99+
return {
100+
nextTree,
101+
node: addedNode
102+
};
103+
}
104+
105+
export function deleteToTreeData(tree: any, path: string) {
106+
let rootPath = getRootPath(path);
107+
let selectedFile = '';
108+
let nextTree = produce(tree, (draftTree: any) => {
109+
let root = draftTree[0];
110+
if (root) {
111+
let stack: Record<string, any> = [root];
112+
while (stack.length > 0) {
113+
let node = stack.pop();
114+
if (Array.isArray(node.children) && node.path === rootPath) {
115+
let len = node.children.length;
116+
for (let i = 0; i < len; i++) {
117+
if (node.children[i].path === path) {
118+
if (node.children[i + 1]) {
119+
selectedFile = node.children[i + 1].key;
120+
} else if (node.children[i - 1]) {
121+
selectedFile = node.children[i - 1].key;
122+
} else {
123+
selectedFile = node.key;
124+
}
125+
node.children.splice(i, 1);
126+
break;
127+
}
128+
}
129+
stack.length = 0;
130+
return;
131+
}
132+
if (node.children && node.children.length > 0) {
133+
let len = node.children.length;
134+
for (let i = 0; i < len; i++) {
135+
stack.push(node.children[i]);
136+
}
137+
}
138+
}
139+
}
140+
});
141+
return {
142+
nextTree,
143+
selectedFile
144+
};
145+
}

‎packages/workbench-electron/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "workbench-electron",
3-
"version": "0.0.8",
3+
"version": "0.0.9",
44
"description": "Pandora Workbench",
55
"productName": "Pandora Workbench",
66
"private": true,

0 commit comments

Comments
 (0)
Please sign in to comment.