Skip to content
This repository was archived by the owner on Apr 7, 2024. It is now read-only.

Commit f196d3f

Browse files
authored
chore: Clean up code (#102)
* Add separate graph component and layout animations settings * Replace hardcoded animation duration in graph components * Fix onComplete callback, add a possibility to specify default settings * Clean up graph component code * Remove unused code * Remove unnecessary useMemo hook
1 parent c26f0dc commit f196d3f

File tree

21 files changed

+358
-471
lines changed

21 files changed

+358
-471
lines changed

src/components/graphs/GraphComponent.tsx

Lines changed: 59 additions & 211 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,34 @@
1-
import { Group, Rect, Vector } from '@shopify/react-native-skia';
1+
import { Group, Rect } from '@shopify/react-native-skia';
22
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
33
import { useAnimatedReaction, useDerivedValue } from 'react-native-reanimated';
44

5-
import { DEFAULT_ANIMATION_SETTINGS } from '@/constants/animations';
6-
import {
7-
ARROW_COMPONENT_SETTINGS,
8-
CURVED_EDGE_COMPONENT_SETTINGS,
9-
LABEL_COMPONENT_SETTINGS,
10-
STRAIGHT_EDGE_COMPONENT_SETTINGS,
11-
VERTEX_COMPONENT_SETTINGS
12-
} from '@/constants/components';
13-
import { RANDOM_PLACEMENT_SETTING } from '@/constants/placement';
145
import { GraphEventsContextType } from '@/context/graphEvents';
156
import { useGraphObserver } from '@/hooks';
167
import {
17-
AnimationSettingsWithDefaults,
18-
AnimationsSettings
19-
} from '@/types/animations';
20-
import { EdgeComponentProps } from '@/types/components';
21-
import { Edge, Graph, Vertex } from '@/types/graphs';
8+
EdgeComponentProps,
9+
GraphData,
10+
GraphEdgeData,
11+
GraphVertexData
12+
} from '@/types/components';
13+
import { Graph } from '@/types/graphs';
2214
import {
2315
AnimatedBoundingRect,
2416
AnimatedVector,
2517
AnimatedVectorCoordinates,
2618
BoundingRect
2719
} from '@/types/layout';
2820
import { GraphRenderers } from '@/types/renderer';
29-
import {
30-
DirectedEdgeSettings,
31-
GraphLayout,
32-
GraphSettings,
33-
GraphSettingsWithDefaults,
34-
RandomPlacementSettings
35-
} from '@/types/settings';
36-
import { GraphAnimationsSettingsWithDefaults } from '@/types/settings/animations';
21+
import { GraphSettings, GraphSettingsWithDefaults } from '@/types/settings';
3722
import { animateVerticesToFinalPositions } from '@/utils/animations';
38-
import { placeVertices } from '@/utils/placement';
23+
import {
24+
updateGraphEdgesData,
25+
updateGraphRenderersWithDefaults,
26+
updateGraphSettingsWithDefaults,
27+
updateGraphVerticesData
28+
} from '@/utils/components';
29+
import { calcContainerBoundingRect, placeVertices } from '@/utils/placement';
3930

40-
import DefaultEdgeArrowRenderer from './arrows/renderers/DefaultEdgeArrowRenderer';
41-
import DefaultCurvedEdgeRenderer from './edges/curved/renderers/DefaultCurvedEdgeRenderer';
4231
import EdgeComponent from './edges/EdgeComponent';
43-
import DefaultStraightEdgeRenderer from './edges/straight/renderers/DefaultStraightEdgeRenderer';
44-
import DefaultVertexRenderer from './vertices/renderers/DefaultVertexRenderer';
4532
import VertexComponent from './vertices/VertexComponent';
4633

4734
export type GraphComponentPrivateProps<V, E> = {
@@ -84,28 +71,11 @@ export default function GraphComponent<
8471
// GRAPH STATE
8572
// Vertices
8673
const [verticesData, setVerticesData] = useState<
87-
Record<
88-
string,
89-
{
90-
vertex: Vertex<V, E>;
91-
targetPlacementPosition: Vector;
92-
animationSettings: AnimationSettingsWithDefaults;
93-
removed: boolean;
94-
}
95-
>
74+
Record<string, GraphVertexData<V, E>>
9675
>({});
9776
// Edges
9877
const [edgesData, setEdgesData] = useState<
99-
Record<
100-
string,
101-
{
102-
edge: Edge<E, V>;
103-
order: number;
104-
edgesCount: number;
105-
animationSettings: AnimationSettingsWithDefaults;
106-
removed: boolean;
107-
}
108-
>
78+
Record<string, GraphEdgeData<E, V>>
10979
>({});
11080

11181
// ANIMATED VALUES
@@ -119,81 +89,25 @@ export default function GraphComponent<
11989
);
12090

12191
const memoSettings = useMemo(() => {
122-
const newSettings: GraphSettingsWithDefaults<V, E> = {
123-
...settings,
124-
placement: {
125-
...(RANDOM_PLACEMENT_SETTING as RandomPlacementSettings),
126-
...settings?.placement
127-
},
128-
components: {
129-
...settings?.components,
130-
vertex: {
131-
...VERTEX_COMPONENT_SETTINGS,
132-
...settings?.components?.vertex
133-
},
134-
edge: {
135-
...(settings?.components?.edge?.type === 'curved'
136-
? CURVED_EDGE_COMPONENT_SETTINGS
137-
: STRAIGHT_EDGE_COMPONENT_SETTINGS),
138-
...settings?.components?.edge,
139-
...(graph.isDirected()
140-
? {
141-
arrow: {
142-
...ARROW_COMPONENT_SETTINGS,
143-
...(settings?.components?.edge as DirectedEdgeSettings)?.arrow
144-
}
145-
}
146-
: {}),
147-
148-
label: {
149-
...LABEL_COMPONENT_SETTINGS,
150-
...settings?.components?.edge?.label
151-
}
152-
}
153-
},
154-
animations: {
155-
layout: {
156-
...DEFAULT_ANIMATION_SETTINGS,
157-
...settings?.animations?.layout
158-
},
159-
vertices: {
160-
...DEFAULT_ANIMATION_SETTINGS,
161-
...settings?.animations?.vertices
162-
},
163-
edges: {
164-
...DEFAULT_ANIMATION_SETTINGS,
165-
...settings?.animations?.edges
166-
}
167-
}
168-
};
92+
const newSettings: GraphSettingsWithDefaults<V, E> =
93+
updateGraphSettingsWithDefaults(graph.isDirected(), settings);
16994

17095
graphEventsContext.setGraphSettings(newSettings);
17196

17297
return newSettings;
17398
}, [settings]);
17499

175100
const memoRenderers = useMemo(
176-
() => ({
177-
vertex: DefaultVertexRenderer,
178-
edge: {
179-
arrow: graph.isDirected() ? DefaultEdgeArrowRenderer : undefined,
180-
edge:
181-
renderers?.edge || settings?.components?.edge?.type === 'curved'
182-
? DefaultCurvedEdgeRenderer
183-
: DefaultStraightEdgeRenderer,
184-
label: renderers?.label
185-
}
186-
}),
187-
[graph, settings, renderers]
101+
() =>
102+
updateGraphRenderersWithDefaults(
103+
graph.isDirected(),
104+
memoSettings.components.edge.type,
105+
renderers
106+
),
107+
[graph, memoSettings, renderers]
188108
);
189109

190-
const memoGraphData = useMemo<{
191-
vertices: Array<Vertex<V, E>>;
192-
edges: Array<Edge<E, V>>;
193-
layout: GraphLayout;
194-
animations: AnimationsSettings;
195-
defaultAnimations: GraphAnimationsSettingsWithDefaults;
196-
}>(
110+
const memoGraphData = useMemo<GraphData<V, E>>(
197111
() => ({
198112
...graphData,
199113
layout: placeVertices(
@@ -213,42 +127,12 @@ export default function GraphComponent<
213127

214128
useEffect(() => {
215129
// UPDATE VERTICES DATA
216-
const newVerticesData = { ...verticesData };
217-
// Add new vertices to vertex data
218-
graphData.vertices.forEach(vertex => {
219-
const targetPlacementPosition =
220-
memoGraphData.layout.verticesPositions[vertex.key];
221-
if (
222-
targetPlacementPosition &&
223-
(!newVerticesData[vertex.key] || newVerticesData[vertex.key]?.removed)
224-
) {
225-
newVerticesData[vertex.key] = {
226-
vertex,
227-
animationSettings: {
228-
...memoGraphData.defaultAnimations.vertices,
229-
...memoGraphData.animations.vertices[vertex.key]
230-
},
231-
targetPlacementPosition,
232-
removed: false
233-
};
234-
}
235-
});
236-
// Mark vertices as removed if there were removed from the graph model
237-
Object.keys(newVerticesData).forEach(key => {
238-
if (!graph.hasVertex(key)) {
239-
newVerticesData[key] = {
240-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
241-
...newVerticesData[key]!,
242-
removed: true,
243-
animationSettings: {
244-
...memoGraphData.defaultAnimations.vertices,
245-
...memoGraphData.animations.vertices[key]
246-
}
247-
};
248-
}
249-
});
130+
const updatedVerticesData = updateGraphVerticesData(
131+
verticesData,
132+
memoGraphData
133+
);
250134
// Set new vertices graphData
251-
setVerticesData(newVerticesData);
135+
setVerticesData(updatedVerticesData);
252136

253137
// Call onRender callback on the first render
254138
if (isFirstRenderRef.current) {
@@ -259,42 +143,9 @@ export default function GraphComponent<
259143

260144
useEffect(() => {
261145
// UPDATE EDGES DATA
262-
// Add new edges to edges data
263-
const newEdgesData = { ...edgesData };
264-
graphData.orderedEdges.forEach(({ edge, order, edgesCount }) => {
265-
if (
266-
!newEdgesData[edge.key] ||
267-
newEdgesData[edge.key]?.removed ||
268-
newEdgesData[edge.key]?.edgesCount !== edgesCount
269-
) {
270-
newEdgesData[edge.key] = {
271-
edge,
272-
order,
273-
edgesCount,
274-
removed: false,
275-
animationSettings: {
276-
...memoGraphData.defaultAnimations.edges,
277-
...memoGraphData.animations.edges[edge.key]
278-
}
279-
};
280-
}
281-
});
282-
// Mark edges as removed if there were removed from the graph model
283-
Object.keys(newEdgesData).forEach(key => {
284-
if (!graph.hasEdge(key)) {
285-
newEdgesData[key] = {
286-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
287-
...newEdgesData[key]!,
288-
removed: true,
289-
animationSettings: {
290-
...memoGraphData.defaultAnimations.edges,
291-
...memoGraphData.animations.edges[key]
292-
}
293-
};
294-
}
295-
});
146+
const updatedEdgesData = updateGraphEdgesData(edgesData, memoGraphData);
296147
// Set the new edges graphData
297-
setEdgesData(newEdgesData);
148+
setEdgesData(updatedEdgesData);
298149
}, [memoGraphData]);
299150

300151
useEffect(() => {
@@ -308,34 +159,29 @@ export default function GraphComponent<
308159
}, [animatedEdgeLabelsPositions]);
309160

310161
useAnimatedReaction(
311-
() => ({ positions: animatedVerticesPositions }),
162+
() => ({
163+
positions: Object.fromEntries(
164+
Object.entries(animatedVerticesPositions).map(([key, coordinates]) => [
165+
key,
166+
{
167+
x: coordinates.x.value,
168+
y: coordinates.y.value
169+
}
170+
])
171+
)
172+
}),
312173
({ positions }) => {
313-
// Update the bounding rect on every vertex position change
314-
let top = Infinity;
315-
let bottom = -Infinity;
316-
let left = Infinity;
317-
let right = -Infinity;
318-
319-
Object.values(positions).forEach(({ x, y }) => {
320-
if (x.value < left) {
321-
left = x.value;
322-
}
323-
if (x.value > right) {
324-
right = x.value;
325-
}
326-
if (y.value < top) {
327-
top = y.value;
328-
}
329-
if (y.value > bottom) {
330-
bottom = y.value;
331-
}
332-
});
333-
334-
const vertexRadius = memoSettings.components.vertex.radius;
335-
boundingRect.top.value = top - vertexRadius;
336-
boundingRect.bottom.value = bottom + vertexRadius;
337-
boundingRect.left.value = left - vertexRadius;
338-
boundingRect.right.value = right + vertexRadius;
174+
Object.entries(
175+
calcContainerBoundingRect(
176+
positions,
177+
// Padding near the edges of the container
178+
memoSettings.components.vertex.radius,
179+
memoSettings.components.vertex.radius
180+
)
181+
).forEach(
182+
([key, value]) =>
183+
(boundingRect[key as keyof AnimatedBoundingRect].value = value)
184+
);
339185
}
340186
);
341187

@@ -418,7 +264,9 @@ export default function GraphComponent<
418264
order,
419265
edgesCount,
420266
vertexRadius: memoSettings.components.vertex.radius,
421-
renderers: memoRenderers.edge,
267+
edgeRenderer: memoRenderers.edge,
268+
arrowRenderer: memoRenderers.arrow,
269+
labelRenderer: memoRenderers.label,
422270
settings: memoSettings.components.edge,
423271
onRemove: handleEdgeRemove,
424272
onLabelRender: handleEdgeLabelRender,

src/components/graphs/edges/EdgeComponent.tsx

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import {
88
UndirectedCurvedEdgeComponentProps,
99
UndirectedStraightEdgeComponentProps
1010
} from '@/types/components/edges';
11-
import { updateComponentAnimationState } from '@/utils/animations';
11+
import { updateComponentAnimationState } from '@/utils/components';
1212

1313
import DirectedCurvedEdgeComponent from './curved/DirectedCurvedEdgeComponent';
1414
import UndirectedCurvedEdgeComponent from './curved/UndirectedCurvedEdgeComponent';
@@ -22,11 +22,15 @@ function EdgeComponent<E, V>({
2222
removed,
2323
onRemove,
2424
animationSettings,
25+
edgeRenderer,
26+
arrowRenderer,
27+
labelRenderer,
2528
...restProps
2629
}: EdgeComponentProps<E, V>) {
2730
// ANIMATION
2831
// Edge render animation progress
2932
const animationProgress = useSharedValue(0);
33+
3034
// EDGE ORDERING
3135
// Target edge order
3236
const animatedOrder = useSharedValue(order);
@@ -58,7 +62,17 @@ function EdgeComponent<E, V>({
5862
edge,
5963
animationProgress,
6064
animatedOrder,
61-
animatedEdgesCount
65+
animatedEdgesCount,
66+
renderers: arrowRenderer
67+
? {
68+
edge: edgeRenderer,
69+
arrow: arrowRenderer,
70+
label: labelRenderer
71+
}
72+
: {
73+
edge: edgeRenderer,
74+
label: labelRenderer
75+
}
6276
};
6377

6478
switch (sharedProps.settings.type) {

src/components/graphs/vertices/VertexComponent.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { Vertex } from '@/types/graphs';
66
import { AnimatedVectorCoordinates } from '@/types/layout';
77
import { VertexRenderFunction } from '@/types/renderer';
88
import { VertexSettings } from '@/types/settings';
9-
import { updateComponentAnimationState } from '@/utils/animations';
9+
import { updateComponentAnimationState } from '@/utils/components';
1010

1111
type VertexComponentProps<V, E> = {
1212
vertex: Vertex<V, E>;

0 commit comments

Comments
 (0)