summaryrefslogtreecommitdiff
path: root/pages/index.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'pages/index.tsx')
-rw-r--r--pages/index.tsx109
1 files changed, 50 insertions, 59 deletions
diff --git a/pages/index.tsx b/pages/index.tsx
index 12c42a1..42170a1 100644
--- a/pages/index.tsx
+++ b/pages/index.tsx
@@ -40,7 +40,6 @@ import { ThemeContext, ThemeContextProps } from '../util/themecontext'
import SpriteText from 'three-spritetext'
import ReconnectingWebSocket from 'reconnecting-websocket'
-import { sendJson } from 'next/dist/next-server/server/api-utils'
// react-force-graph fails on import when server-rendered
// https://github.com/vasturiano/react-force-graph/issues/155
@@ -73,16 +72,6 @@ export default function Home() {
return <GraphPage />
}
-function normalizeLinkEnds(link: OrgRoamLink | LinkObject): [string, string] {
- // we need to cover both because force-graph modifies the original data
- // but if we supply the original data on each render, the graph will re-render sporadically
- const sourceId =
- typeof link.source === 'object' ? (link.source.id! as string) : (link.source as string)
- const targetId =
- typeof link.target === 'object' ? (link.target.id! as string) : (link.target as string)
- return [sourceId, targetId]
-}
-
export function GraphPage() {
const [threeDim, setThreeDim] = usePersistantState('3d', false)
const [tagColors, setTagColors] = usePersistantState<TagColors>('tagCols', {})
@@ -104,7 +93,6 @@ export function GraphPage() {
const currentGraphDataRef = useRef<GraphData>({ nodes: [], links: [] })
const updateGraphData = (orgRoamGraphData: OrgRoamGraphReponse) => {
- const currentGraphData = currentGraphDataRef.current
const oldNodeById = nodeByIdRef.current
tagsRef.current = orgRoamGraphData.tags ?? []
const nodesByFile = orgRoamGraphData.nodes.reduce<NodesByFile>((acc, node) => {
@@ -177,30 +165,29 @@ export function GraphPage() {
}, {})
const nodes = [...orgRoamGraphData.nodes, ...nonExistantNodes]
- const orgRoamGraphDataWithFileLinksAndBadNdes = {
+ const orgRoamGraphDataProcessed = {
nodes,
links,
}
- if (!currentGraphData.nodes.length) {
+ const currentGraphData = currentGraphDataRef.current
+ if (currentGraphData.nodes.length === 0) {
// react-force-graph modifies the graph data implicitly,
// so we make sure there's no overlap between the objects we pass it and
// nodeByIdRef, linksByNodeIdRef
- const orgRoamGraphDataClone = JSON.parse(
- JSON.stringify(orgRoamGraphDataWithFileLinksAndBadNdes),
- )
+ const orgRoamGraphDataClone = JSON.parse(JSON.stringify(orgRoamGraphDataProcessed))
currentGraphDataRef.current = orgRoamGraphDataClone
setGraphData(orgRoamGraphDataClone)
return
}
const newNodes = [
- ...currentGraphData.nodes.map((node: NodeObject) => {
+ ...currentGraphData.nodes.flatMap((node: NodeObject) => {
const newNode = nodeByIdRef.current[node?.id!] ?? false
if (!newNode) {
- return
+ return []
}
- return { ...node, ...newNode }
+ return [{ ...node, ...newNode }]
}),
...Object.keys(nodeByIdRef.current)
.filter((id) => !oldNodeById[id])
@@ -225,7 +212,7 @@ export function GraphPage() {
target: newNodes[nodeIndex![target]],
}
})
- const fg = graphRef.current
+
setGraphData({ nodes: newNodes as NodeObject[], links: newerLinks })
}
useEffect(() => {
@@ -240,7 +227,7 @@ export function GraphPage() {
const scopeRef = useRef<Scope>({ nodeIds: [] })
const behaviorRef = useRef(initialBehavior)
behaviorRef.current = behavior
- const WebSocketRef = useRef<any>(null)
+ const WebSocketRef = useRef<ReconnectingWebSocket | null>(null)
scopeRef.current = scope
const followBehavior = (
@@ -288,7 +275,7 @@ export function GraphPage() {
return
}
- // if the node is in the scopednodes, add it to scope instead of replacing it
+ // if the node is in the scoped nodes, add it to scope instead of replacing it
if (
!sr.nodeIds.includes(emacsNode) ||
!sr.nodeIds.some((scopeId: string) => {
@@ -315,11 +302,10 @@ export function GraphPage() {
useEffect(() => {
// initialize websocket
WebSocketRef.current = new ReconnectingWebSocket('ws://localhost:35903')
- WebSocketRef.current.addEventListener('open', (event: any) => {
+ WebSocketRef.current.addEventListener('open', () => {
console.log('Connection with Emacs established')
})
WebSocketRef.current.addEventListener('message', (event: any) => {
- const fg = graphRef.current
const bh = behaviorRef.current
const message = JSON.parse(event.data)
switch (message.type) {
@@ -359,7 +345,8 @@ export function GraphPage() {
if (!fg || scope.nodeIds.length > 1) {
return
}
- if (!scope.nodeIds.length) {
+ if (!scope.nodeIds.length && physics.gravityOn) {
+ fg.zoomToFit()
return
}
setTimeout(() => {
@@ -499,15 +486,16 @@ export const Graph = forwardRef(function (props: GraphProps, graphRef: any) {
sendMessageToEmacs('create', { id: node.id, title: node.title, ref: node.properties.ROAM_REFS })
}
+ const contextMenu = useDisclosure()
+
const openContextMenu = (node: OrgRoamNode, event: any) => {
setContextPos([event.pageX, event.pageY])
setRightClickedNode(node)
- onOpen()
+ contextMenu.onOpen()
}
const handleClick = (click: string, node: OrgRoamNode, event: any) => {
switch (click) {
- //mouse.highlight:
case mouse.local: {
handleLocal(node, behavior.localSame)
break
@@ -523,6 +511,7 @@ export const Graph = forwardRef(function (props: GraphProps, graphRef: any) {
break
}
}
+
const findNthNeighbors = (ids: string[], n: number) => {
let queue = [ids[0]]
let todo: string[] = []
@@ -583,11 +572,6 @@ export const Graph = forwardRef(function (props: GraphProps, graphRef: any) {
hiddenNodeIdsRef.current = {}
const filteredNodes = graphData?.nodes
?.filter((nodeArg) => {
- //sometimes there will be some undefined nodes in the mix
- // should probably fix the actual issue, but this is a fix
- if (!nodeArg) {
- return
- }
const node = nodeArg as OrgRoamNode
if (
filter.tagsBlacklist.length &&
@@ -739,7 +723,7 @@ export const Graph = forwardRef(function (props: GraphProps, graphRef: any) {
graphRef.current?.d3ReheatSimulation()
}, [physics, scope.nodeIds.length])
- //shitty handler to check for doubleClicks
+ // shitty handler to check for doubleClicks
const lastNodeClickRef = useRef(0)
const [opacity, setOpacity] = useState(1)
@@ -821,9 +805,6 @@ export const Graph = forwardRef(function (props: GraphProps, graphRef: any) {
}
const getLinkColor = (sourceId: string, targetId: string, needsHighlighting: boolean) => {
- // I'm so sorry
- // if we are matching the node color and don't have a highlight color
- // or we don't have our own scheme and we're not being highlighted
if (!visuals.linkHighlight && !visuals.linkColorScheme && !needsHighlighting) {
const nodeColor = getLinkNodeColor(sourceId, targetId)
return getThemeColor(nodeColor)
@@ -857,7 +838,6 @@ export const Graph = forwardRef(function (props: GraphProps, graphRef: any) {
}
const getNodeColor = (node: OrgRoamNode) => {
- const isHighlightingHappening = !!highlightedNodes.length
const needsHighlighting = highlightedNodes[node.id!] || previouslyHighlightedNodes[node.id!]
// if we are matching the node color and don't have a highlight color
// or we don't have our own scheme and we're not being highlighted
@@ -893,17 +873,6 @@ export const Graph = forwardRef(function (props: GraphProps, graphRef: any) {
return highlightColors[getNodeColorById(node.id as string)][visuals.nodeHighlight](opacity)
}
- const hexToRGBA = (hex: string, opacity: number) =>
- 'rgba(' +
- (hex = hex.replace('#', ''))
- .match(new RegExp('(.{' + hex.length / 3 + '})', 'g'))!
- .map(function (l) {
- return parseInt(hex.length % 2 ? l + l : l, 16)
- })
- .concat(isFinite(opacity) ? opacity : 1)
- .join(',') +
- ')'
-
const labelTextColor = useMemo(
() => getThemeColor(visuals.labelTextColor),
[visuals.labelTextColor, emacsTheme],
@@ -929,14 +898,13 @@ export const Graph = forwardRef(function (props: GraphProps, graphRef: any) {
}
const [dragging, setDragging] = useState(false)
- const { isOpen, onOpen, onClose } = useDisclosure()
const graphCommonProps: ComponentPropsWithoutRef<typeof TForceGraph2D> = {
graphData: scope.nodeIds.length ? scopedGraphData : filteredGraphData,
width: windowWidth,
height: windowHeight,
backgroundColor: theme.colors.gray[visuals.backgroundColor],
- warmupTicks: scope.nodeIds.length === 1 ? 100 : 0,
+ warmupTicks: scope.nodeIds.length === 1 ? 100 : scope.nodeIds.length > 1 ? 20 : 0,
nodeLabel: (node) => (node as OrgRoamNode).title,
nodeColor: (node) => {
return getNodeColor(node as OrgRoamNode)
@@ -971,7 +939,6 @@ export const Graph = forwardRef(function (props: GraphProps, graphRef: any) {
nodeTitle.length > visuals.labelLength
? nodeTitle.substring(0, visuals.labelLength) + '...'
: nodeTitle
- // const label = 'label'
const fontSize = visuals.labelFontSize / (0.75 * Math.min(Math.max(0.5, globalScale), 3))
const textWidth = ctx.measureText(label).width
const bckgDimensions = [textWidth * 1.1, fontSize].map((n) => n + fontSize * 0.5) as [
@@ -1020,7 +987,7 @@ export const Graph = forwardRef(function (props: GraphProps, graphRef: any) {
linkDirectionalArrowLength: visuals.arrows ? visuals.arrowsLength : undefined,
linkDirectionalArrowRelPos: visuals.arrowsPos,
linkDirectionalArrowColor: visuals.arrowsColor
- ? (link) => getThemeColor(visuals.arrowsColor)
+ ? () => getThemeColor(visuals.arrowsColor)
: undefined,
linkColor: (link) => {
const sourceId = typeof link.source === 'object' ? link.source.id! : (link.source as string)
@@ -1070,7 +1037,7 @@ export const Graph = forwardRef(function (props: GraphProps, graphRef: any) {
onNodeClick: (nodeArg: NodeObject, event: any) => {
const node = nodeArg as OrgRoamNode
- onClose()
+ contextMenu.onClose()
const isDoubleClick = event.timeStamp - lastNodeClickRef.current < 400
lastNodeClickRef.current = event.timeStamp
if (isDoubleClick) {
@@ -1079,7 +1046,7 @@ export const Graph = forwardRef(function (props: GraphProps, graphRef: any) {
return handleClick('click', node, event)
},
onBackgroundClick: () => {
- onClose()
+ contextMenu.onClose()
setHoverNode(null)
if (scope.nodeIds.length === 0) {
return
@@ -1106,11 +1073,11 @@ export const Graph = forwardRef(function (props: GraphProps, graphRef: any) {
handleClick('right', node, event)
},
onNodeDrag: (node) => {
- onClose()
+ contextMenu.onClose()
setHoverNode(node)
setDragging(true)
},
- onNodeDragEnd: (node) => {
+ onNodeDragEnd: () => {
setHoverNode(null)
setDragging(false)
},
@@ -1118,7 +1085,7 @@ export const Graph = forwardRef(function (props: GraphProps, graphRef: any) {
return (
<Box overflow="hidden">
- {isOpen && (
+ {contextMenu.isOpen && (
<ContextMenu
scope={scope}
node={rightClickedNode!}
@@ -1126,7 +1093,7 @@ export const Graph = forwardRef(function (props: GraphProps, graphRef: any) {
background={false}
coordinates={contextPos}
handleLocal={handleLocal}
- menuClose={onClose}
+ menuClose={contextMenu.onClose.bind(contextMenu)}
openNodeInEmacs={openNodeInEmacs}
deleteNodeInEmacs={deleteNodeInEmacs}
createNodeInEmacs={createNodeInEmacs}
@@ -1186,3 +1153,27 @@ function isLinkRelatedToNode(link: LinkObject, node: NodeObject | null) {
function numberWithinRange(num: number, min: number, max: number) {
return Math.min(Math.max(num, min), max)
}
+
+function normalizeLinkEnds(link: OrgRoamLink | LinkObject): [string, string] {
+ // we need to cover both because force-graph modifies the original data
+ // but if we supply the original data on each render, the graph will re-render sporadically
+ const sourceId =
+ typeof link.source === 'object' ? (link.source.id! as string) : (link.source as string)
+ const targetId =
+ typeof link.target === 'object' ? (link.target.id! as string) : (link.target as string)
+ return [sourceId, targetId]
+}
+
+function hexToRGBA(hex: string, opacity: number) {
+ return (
+ 'rgba(' +
+ (hex = hex.replace('#', ''))
+ .match(new RegExp('(.{' + hex.length / 3 + '})', 'g'))!
+ .map(function (l) {
+ return parseInt(hex.length % 2 ? l + l : l, 16)
+ })
+ .concat(isFinite(opacity) ? opacity : 1)
+ .join(',') +
+ ')'
+ )
+}