From 2384b30a244c7d6477e54de5385fe7f1cc62d43a Mon Sep 17 00:00:00 2001
From: "Thomas F. K. Jorna" <hello@tefkah.com>
Date: Fri, 8 Oct 2021 23:39:37 +0200
Subject: feat(preview): proper file preview with api routing

---
 components/Sidebar/Link.tsx | 208 +++++++++++++++++++++++++++++++++++---------
 1 file changed, 168 insertions(+), 40 deletions(-)

(limited to 'components/Sidebar/Link.tsx')

diff --git a/components/Sidebar/Link.tsx b/components/Sidebar/Link.tsx
index ff812ef..9515b6d 100644
--- a/components/Sidebar/Link.tsx
+++ b/components/Sidebar/Link.tsx
@@ -1,6 +1,7 @@
 import {
   Box,
   Button,
+  Link,
   Popover,
   PopoverArrow,
   PopoverBody,
@@ -10,9 +11,9 @@ import {
   PopoverTrigger,
   Portal,
   Text,
+  useTheme,
 } from '@chakra-ui/react'
-import React, { useState } from 'react'
-import UniOrg from '../../util/uniorg'
+import React, { ReactElement, useContext, useEffect, useMemo, useState } from 'react'
 
 import unified from 'unified'
 //import createStream from 'unified-stream'
@@ -22,57 +23,184 @@ import uniorg2rehype from 'uniorg-rehype'
 import katex from 'rehype-katex'
 import 'katex/dist/katex.css'
 import rehype2react from 'rehype-react'
+import { ThemeContext } from '../../util/themecontext'
+import { NodeByCite, NodeById } from '../../pages'
 
 export interface LinkProps {
-  href: string
+  href: any
   children: any
-  testProp: string
-  getText: any
   previewNode?: any
   setPreviewNode: any
+  setSidebarHighlightedNode: any
+  nodeByCite: NodeByCite
+  nodeById: NodeById
 }
 
-export const PreviewLink = (props: any) => {
-  const { href, children, nodeById, getText, previewNode, setPreviewNode } = props
-  const [previewText, setPreviewText] = useState('')
-  const [whatever, type, uri] = [...href.matchAll(/(.*?)\:(.*)/g)][0]
+export interface NormalLinkProps {
+  setPreviewNode: any
+  nodeById: NodeById
+  nodeByCite: NodeByCite
+  href: any
+  children: any
+  setSidebarHighlightedNode: any
+}
 
-  const processor = unified().use(uniorgParse).use(uniorg2rehype).use(katex).use(rehype2react, {
-    createElement: React.createElement,
-    // eslint-disable-next-line react/display-name
-  })
+import { hexToRGBA, getThemeColor } from '../../pages/index'
+import noteStyle from './noteStyle'
 
-  type === 'id' && getText(uri, setPreviewText)
+export const NormalLink = (props: NormalLinkProps) => {
+  const { setSidebarHighlightedNode, setPreviewNode, nodeById, href, children } = props
+  const { highlightColor } = useContext(ThemeContext)
 
+  const theme = useTheme()
+  const coolHighlightColor = getThemeColor(highlightColor, theme)
+  const [whatever, type, uri] = [...href.matchAll(/(.*?)\:(.*)/g)][0]
   return (
-    <>
-      <Popover trigger="hover" isLazy position="relative" zIndex="tooltip">
-        <PopoverTrigger>
-          <Button size="sm" onClick={() => setPreviewNode(nodeById[uri])} variant="link">
-            {children}
-          </Button>
-        </PopoverTrigger>
-        <Portal zIndex={100000} position="relative">
-          <PopoverContent boxShadow="xl" position="relative" zIndex="tooltip">
-            <PopoverHeader pl={5} fontSize="sm" zIndex="tooltip" fontWeight="semibold">
-              {children}
-            </PopoverHeader>
-            <PopoverArrow zIndex={10000} />
-            <PopoverCloseButton zIndex={10000} />
-            <PopoverBody
-              pb={5}
-              fontSize="xs"
-              px={5}
+    <Text
+      onMouseEnter={() => setSidebarHighlightedNode(nodeById[uri])}
+      onMouseLeave={() => setSidebarHighlightedNode({})}
+      tabIndex={0}
+      display="inline"
+      overflow="hidden"
+      fontWeight={500}
+      color={highlightColor}
+      textDecoration="underline"
+      onClick={() => setPreviewNode(nodeById[uri])}
+      _hover={{ textDecoration: 'none', cursor: 'pointer', bgColor: coolHighlightColor + '22' }}
+      _focus={{ outlineColor: highlightColor }}
+    >
+      {children}
+    </Text>
+  )
+}
+
+export const PreviewLink = (props: LinkProps) => {
+  const {
+    href,
+    children,
+    nodeById,
+    setSidebarHighlightedNode,
+    previewNode,
+    setPreviewNode,
+    nodeByCite,
+  } = props
+  // TODO figure out how to properly type this
+  // see https://github.com/rehypejs/rehype-react/issues/25
+  const [orgText, setOrgText] = useState<any>()
+  const [whatever, type, uri] = [...href.matchAll(/(.*?)\:(.*)/g)][0]
+
+  const getId = (type: string, uri: string) => {
+    if (type === 'id') {
+      return uri
+    }
+
+    if (type.includes('cite')) {
+      const node = nodeByCite[uri] ?? false
+      if (!node) {
+        return ''
+      }
+      if (node?.properties.FILELESS) {
+        return ''
+      }
+      return node?.id
+    }
+    return ''
+  }
+
+  const id = getId(type, uri)
+
+  const processor = unified()
+    .use(uniorgParse)
+    .use(uniorg2rehype)
+    .use(katex)
+    .use(rehype2react, {
+      createElement: React.createElement,
+      components: {
+        // eslint-disable-next-line react/display-name
+        a: ({ children, href }) => (
+          <NormalLink
+            setSidebarHighlightedNode={setSidebarHighlightedNode}
+            nodeById={nodeById}
+            nodeByCite={nodeByCite}
+            setPreviewNode={setPreviewNode}
+            {...{ children, href }}
+          />
+        ),
+      },
+    })
+
+  const file = encodeURIComponent(nodeById[id]?.file as string)
+  const getText = () => {
+    console.log(nodeById[id]?.title)
+    fetch(`api/notes/${file}`)
+      .then((res) => {
+        return res.text()
+      })
+      .then((res) => {
+        if (res !== 'error') {
+          const text = processor.processSync(res).result
+          setOrgText(text)
+          return
+        }
+      })
+      .catch((e) => {
+        console.log(e)
+        return 'Could not fetch the text for some reason, sorry!\n\n This can happen because you have an id with forward slashes (/) in it.'
+      })
+  }
+
+  useMemo(() => {
+    getText()
+  }, [id])
+  if (id) {
+    return (
+      <>
+        <Popover gutter={12} trigger="hover" placement="top-start">
+          <PopoverTrigger>
+            <Box display="inline">
+              <NormalLink
+                key={nodeById[id]?.title ?? id}
+                {...{
+                  setSidebarHighlightedNode,
+                  setPreviewNode,
+                  nodeById,
+                  href,
+                  children,
+                  nodeByCite,
+                }}
+              />
+            </Box>
+          </PopoverTrigger>
+          <Portal>
+            <PopoverContent
+              key={nodeById[id]?.title ?? id}
+              boxShadow="xl"
               position="relative"
               zIndex="tooltip"
-              maxHeight={300}
-              overflow="scroll"
+              onMouseEnter={() => setSidebarHighlightedNode(nodeById[id] ?? {})}
+              onMouseLeave={() => setSidebarHighlightedNode({})}
             >
-              {uri && <Box>{processor.processSync(previewText).result}</Box>}
-            </PopoverBody>
-          </PopoverContent>
-        </Portal>
-      </Popover>
-    </>
+              <PopoverArrow />
+              <PopoverBody
+                pb={5}
+                fontSize="xs"
+                px={5}
+                position="relative"
+                zIndex="tooltip"
+                maxHeight={300}
+                overflow="scroll"
+              >
+                <Box sx={noteStyle}>{orgText}</Box>
+              </PopoverBody>
+            </PopoverContent>
+          </Portal>
+        </Popover>
+      </>
+    )
+  }
+  return (
+    <Text display="inline" color="base.700" cursor="not-allowed">
+      {children}
+    </Text>
   )
 }
-- 
cgit v1.2.3

