forked from findyourmagic/dber
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathuse-graph-state.js
More file actions
169 lines (157 loc) · 5.14 KB
/
Copy pathuse-graph-state.js
File metadata and controls
169 lines (157 loc) · 5.14 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
import { useState, useEffect, useCallback } from 'react';
import { Modal } from '@arco-design/web-react';
import { db } from '../data/db';
/**
* It returns a state object that contains the graph data, and a set of functions to update the graph
* data
* @returns An object with the following properties:
* {
* tableDict,
* setTableDict,
* linkDict,
* setLinkDict,
* box,
* setBox,
* name,
* setName,
* }
*/
export default function useGraphState() {
const [tableDict, setTableDict] = useState({});
const [linkDict, setLinkDict] = useState({});
const [name, setName] = useState('Untitled graph');
const [theme, setTheme] = useState(null);
// viewbox of svg
const [box, setBox] = useState({
x: 0,
y: 0,
w: 0,
h: 0,
clientW: 0,
clientH: 0,
});
const [id, setId] = useState(null);
const [inited, setInited] = useState(false);
/**
* It takes a graph object and sets the state of the app to match the graph object
*/
const loadGraph = graph => {
if (graph.tableDict) setTableDict(graph.tableDict);
if (graph.linkDict) setLinkDict(graph.linkDict);
if (graph.box) {
const { x, y, w, h, clientH, clientW } = graph.box;
setBox({
x,
y,
w:
w && clientW
? w * (global.innerWidth / clientW)
: global.innerWidth,
h:
h && clientH
? h * (global.innerHeight / clientH)
: global.innerHeight,
clientW: global.innerWidth,
clientH: global.innerHeight,
});
}
if (graph.name) setName(graph.name);
};
useEffect(() => {
setId(new URLSearchParams(global.location.search).get('id'));
}, []);
useEffect(() => {
if (!id) return;
/**
* > If the graph is in the local storage, and the graph in the local storage is newer than the
* graph in the database, then ask the user if they want to load the graph from the local
* storage
*/
const initGraph = async () => {
const graph = await db.graphs.get(id);
const storageGraph = JSON.parse(window.localStorage.getItem(id));
if (graph?.updatedAt < storageGraph?.updatedAt) {
Modal.confirm({
title: 'Unsaved changes',
content:
'You have some unsaved changes after last version, do you want to restore them? Once you press the no button, the unsaved changes will be cleaned immediately. You can’t undo this action.',
cancelButtonProps: { status: 'danger' },
okText: 'Yes, restore them',
cancelText: 'No, ignore them',
onOk: () => {
loadGraph(storageGraph);
},
onCancel: () => {
loadGraph(graph);
window.localStorage.removeItem(id);
},
});
} else if (graph) {
loadGraph(graph);
} else {
resizeHandler();
}
setInited(true);
};
initGraph();
}, [id]);
useEffect(() => {
if (!id || !inited) return;
window.localStorage.setItem(
id,
JSON.stringify({
id,
tableDict,
linkDict,
box,
name,
updatedAt: new Date().valueOf(),
})
);
}, [id, inited, box, linkDict, tableDict, name]);
useEffect(() => {
const t = theme || window.localStorage.getItem('theme') || 'light';
t === 'dark'
? document.body.setAttribute('arco-theme', 'dark')
: document.body.removeAttribute('arco-theme');
window.localStorage.setItem('theme', t);
if (theme === null) setTheme(t);
}, [theme]);
/* A callback function that is used to update the viewbox of the svg. */
const resizeHandler = useCallback(() => {
setBox(state => {
return {
x: state.x,
y: state.y,
w:
state.w && state.clientW
? state.w * (global.innerWidth / state.clientW)
: global.innerWidth,
h:
state.h && state.clientH
? state.h * (global.innerHeight / state.clientH)
: global.innerHeight,
clientW: global.innerWidth,
clientH: global.innerHeight,
};
});
}, []);
useEffect(() => {
global.addEventListener('resize', resizeHandler);
return () => {
global.removeEventListener('resize', resizeHandler);
};
}, []);
return {
tableDict,
setTableDict,
linkDict,
setLinkDict,
box,
setBox,
name,
setName,
theme,
setTheme,
};
}