Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Show All Highlights In Context Sidebar #429

Merged
merged 4 commits into from
May 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changeset/violet-moose-float.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'mexit': patch
'mexit-webapp': patch
---

Show all highlights in Extension
20 changes: 19 additions & 1 deletion apps/extension/src/Components/InternalEvents.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useCallback, useEffect, useRef } from 'react'
import React, { useCallback, useEffect, useRef, useState } from 'react'
import { createRoot } from 'react-dom/client'

import { CaptureConsole } from '@sentry/integrations'
Expand Down Expand Up @@ -225,6 +225,8 @@ function initAnalytics() {
}

function handleHighlighter() {
const [mounted, setMounted] = useState(false)

const setTooltipState = useSputlitStore((s) => s.setHighlightTooltipState)
const highlights = useHighlightStore((s) => s.highlights)
const getHighlightsOfUrl = useHighlightStore((s) => s.getHighlightsOfUrl)
Expand All @@ -248,6 +250,18 @@ function handleHighlighter() {

highlightOldRange()

if (!mounted) {
const searchParams = new URLSearchParams(window.location.search)
const scrollTo = searchParams.get('scrollToCapture')

if (scrollTo) {
const element = document.querySelector(`[data-highlight-id="${scrollTo}"]`)
if (element) {
element.scrollIntoView({ behavior: 'smooth', block: 'center' })
}
}
}

highlighter.on(Highlighter.event.CLICK, (e) => {
const element = document.querySelector(`[data-highlight-id="${e.id}"]`)
const coordinates = element.getBoundingClientRect()
Expand All @@ -259,6 +273,10 @@ function handleHighlighter() {

// I want to replace the keys generated by web-highlighter, and re-highlight everything with blockId as their respective id
}, [highlights])

useEffect(() => {
setMounted(true)
}, [])
}

function badgeRenderer() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { Icon } from '@iconify/react'

import { Button, IconButton, PrimaryButton } from '@workduck-io/mex-components'

import { mog, useAuthStore } from '@mexit/core'
import { deleteQueryParams, mog, useAuthStore } from '@mexit/core'
import { useDebounceEffect } from '@mexit/shared'

import { useSaveChanges } from '../../../Hooks/useSaveChanges'
Expand Down Expand Up @@ -327,7 +327,7 @@ const Screenshot = () => {
const appendContent = [
{ children: [{ text: '' }], type: 'img', url: imageURL },
{ text: '\n' },
{ type: 'a', url: window.location.href, children: [{ text: 'Ref' }] }
{ type: 'a', url: deleteQueryParams(window.location.href), children: [{ text: 'Ref' }] }
]
appendAndSave({ nodeid, content: appendContent, saveAndExit: true, notification: true })
resetSpotlitState()
Expand Down
7 changes: 4 additions & 3 deletions apps/extension/src/Components/Sidebar/AddTags.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { MetaHTMLAttributes, useMemo, useState } from 'react'

import { Link, Tag, useLinkStore } from '@mexit/core'
import { deleteQueryParams, Link, Tag, useLinkStore } from '@mexit/core'
import { AddTagMenu, LinkShortenAndTagsWrapper, TagsLabel } from '@mexit/shared'

import { useLinkURLs } from '../../Hooks/useURLs'
Expand All @@ -19,10 +19,11 @@ export const AddTags = () => {
const [root, setRoot] = useState<any>()

const link = useMemo(() => {
const l = links.find((l) => l.url === window.location.href)
const url = deleteQueryParams(window.location.href)
const l = links.find((l) => l.url === url)
return (
l ?? {
url: window.location.href,
url: url,
...getGoodMeta(document)
}
)
Expand Down
57 changes: 40 additions & 17 deletions apps/extension/src/Components/Sidebar/ContextInfoBar.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, { useMemo } from 'react'
import React, { useMemo, useState } from 'react'

import { useHighlightStore } from '@mexit/core'
import { CenteredFlex, DefaultMIcons, getMIcon, List, SnippetCards } from '@mexit/shared'
import { CenteredFlex, DefaultMIcons, getMIcon, List, SnippetCards, Toggle } from '@mexit/shared'

import { AddTags } from './AddTags'
import { GenericCard } from './GenericCard'
Expand Down Expand Up @@ -30,28 +30,35 @@ const basicOnboarding = [
}
]

export function ContextInfoBar() {
const Highlights = () => {
const [showAll, setShowAll] = useState(false)

const highlights = useHighlightStore((state) => state.highlights)
const getHighlightsOfUrl = useHighlightStore((state) => state.getHighlightsOfUrl)

const pageHighlights = useMemo(() => {
return getHighlightsOfUrl(window.location.href)
}, [window.location, highlights])
const list = showAll ? highlights : getHighlightsOfUrl(window.location.href)

return list?.sort((a, b) => {
if (a?.createdAt && b?.createdAt) {
return a.createdAt - b.createdAt
}

return 0
})
}, [window.location, highlights, showAll])

return (
<SnippetCards fullHeight>
<SidebarSection label="Shorten URL" icon={getMIcon('ICON', 'ri:link-m')}>
<ShortenerComponent />
</SidebarSection>
<SidebarSection label="Tags" icon={DefaultMIcons.TAG}>
<AddTags />
</SidebarSection>
<SidebarSection
scrollable
label="Captures"
icon={DefaultMIcons.HIGHLIGHT}
rightComponent={<Toggle size="small" onChange={setShowAll} text="All" />}
>
{pageHighlights?.length > 0 ? (
<SidebarSection scrollable label="Captures" icon={DefaultMIcons.HIGHLIGHT}>
<List $noMargin scrollable>
<HighlightGroups highlights={pageHighlights} />
</List>
</SidebarSection>
<List $noMargin scrollable>
<HighlightGroups highlights={pageHighlights} all={showAll} />
</List>
) : (
<>
<CenteredFlex>
Expand All @@ -65,6 +72,22 @@ export function ContextInfoBar() {
</SnippetCards>
</>
)}
</SidebarSection>
)

return <></>
}

export function ContextInfoBar() {
return (
<SnippetCards fullHeight>
<SidebarSection label="Shorten URL" icon={getMIcon('ICON', 'ri:link-m')}>
<ShortenerComponent />
</SidebarSection>
<SidebarSection label="Tags" icon={DefaultMIcons.TAG}>
<AddTags />
</SidebarSection>
<Highlights />
</SnippetCards>
)
}
102 changes: 85 additions & 17 deletions apps/extension/src/Components/Sidebar/HighlightGroup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,42 @@ import React, { useMemo } from 'react'

import { useTheme } from 'styled-components'

import { camelCase, DrawerType, Highlight, Highlights, useHighlightStore, useLayoutStore } from '@mexit/core'
import {
appendQueryParams,
camelCase,
deleteQueryParams,
DrawerType,
getFavicon,
Highlight,
Highlights,
useHighlightStore,
useLayoutStore
} from '@mexit/core'
import {
CardFooter,
Container,
DefaultMIcons,
DrawerHeaderDesc,
FlexBetween,
FooterFlexButton,
GenericFlex,
getMIcon,
Group,
HighlightGroupWrapper,
IconDisplay,
MexIcon,
PrimaryText,
SingleHighlightWrapper,
SnippetContentPreview,
StickyHeader,
VerticalSeperator
} from '@mexit/shared'

import { useHighlights } from '../../Hooks/useHighlights'
import { useLinks } from '../../Hooks/useLinks'

import { NodeCardHeader } from './NodeCard'
import { DomainWithHighlight } from './styled'

const HIGHLIGHT_TEXT_MAX_LENGTH = 300

Expand Down Expand Up @@ -92,23 +108,29 @@ export const SingleHighlightWithToggle = ({ highlight }: { highlight: Highlight

const toShowText = willCollapse ? (open ? highlightText : strippedText) : highlightText

const openHighlight = () => {
const element = document.querySelector(`[data-highlight-id="${highlight.entityId}"]`)
const handleOpenHighlight = (e) => {
e.stopPropagation()

element?.scrollIntoView({ behavior: 'smooth', block: 'center' })
const onSamePage = highlight.properties?.sourceUrl == deleteQueryParams(window.location.href)
if (onSamePage) {
const element = document.querySelector(`[data-highlight-id="${highlight.entityId}"]`)

if (element) {
element?.scrollIntoView({ behavior: 'smooth', block: 'center' })
}
} else {
if (highlight.properties?.sourceUrl == null) return
window.open(appendQueryParams(highlight.properties.sourceUrl, { scrollToCapture: highlight.entityId }))
}
}

const title = camelCase(toShowText.slice(0, 35))

return (
<SingleHighlightWrapper onClick={() => openHighlight()}>
<SingleHighlightWrapper onClick={handleOpenHighlight}>
<Container>
<NodeCardHeader>
<GenericFlex
onClick={() => {
//
}}
>
<GenericFlex>
<MexIcon color={theme.tokens.colors.primary.default} icon={DefaultMIcons.HIGHLIGHT.value} />
<PrimaryText>{title}</PrimaryText>
</GenericFlex>
Expand All @@ -123,14 +145,60 @@ export const SingleHighlightWithToggle = ({ highlight }: { highlight: Highlight
)
}

export const HighlightGroups = ({ highlights }: { highlights: Highlights }) => {
return open && highlights ? (
<>
{highlights.map((highlight) => {
if (!highlight) return null
export const HighlightGroups = ({ highlights, all }: { highlights: Highlights; all?: boolean }) => {
// group by sourceUrl
const groupedHighlights = useMemo(() => {
const groupedHighlights = {} as Record<string, Highlight[]>

highlights.forEach((highlight) => {
if (!highlight) return

return <SingleHighlightWithToggle key={`${highlight.entityId}`} highlight={highlight} />
const sourceUrl = new URL(highlight.properties?.sourceUrl)?.origin

if (!groupedHighlights[sourceUrl]) {
groupedHighlights[sourceUrl] = []
}

groupedHighlights[sourceUrl].push(highlight)
})

return groupedHighlights
}, [highlights])

const highlightWithDomains = Object.entries(groupedHighlights)

return (
<>
{highlightWithDomains.map(([origin, highlightList]) => {
if (highlightList.length === 0) return null
const faviconURL = getFavicon(origin)

return (
<DomainWithHighlight>
{highlightWithDomains.length > 1 && (
<StickyHeader>
<FlexBetween>
<Group
onClick={(e) => {
e.stopPropagation()
window.open(highlightList.at(0).properties.sourceUrl, '_blank')
}}
>
<img src={faviconURL} />
<DrawerHeaderDesc>{origin}</DrawerHeaderDesc>&nbsp;
</Group>
<DrawerHeaderDesc fade>{highlightList.length}&nbsp;</DrawerHeaderDesc>
</FlexBetween>
</StickyHeader>
)}
<HighlightGroupWrapper>
{highlightList.map((highlight) => {
return <SingleHighlightWithToggle highlight={highlight} />
})}
</HighlightGroupWrapper>
</DomainWithHighlight>
)
})}
</>
) : null
)
}
18 changes: 12 additions & 6 deletions apps/extension/src/Components/Sidebar/ShortenerComponent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import linkM from '@iconify/icons-ri/link-m'
import { Icon } from '@iconify/react'
import styled from 'styled-components'

import { apiURLs, getFavicon, useAuthStore, useLinkStore } from '@mexit/core'
import { apiURLs, deleteQueryParams, getFavicon, useAuthStore, useLinkStore } from '@mexit/core'
import {
CopyButton,
DefaultMIcons,
Expand Down Expand Up @@ -44,7 +44,7 @@ const UrlTitleWrapper = styled(LinkTitleWrapper)`
text-overflow: ellipsis;
`

const FaviconImage = ({ source }: { source: string }) => {
export const FaviconImage = ({ source }: { source: string }) => {
return <img height="20px" width="20px" src={getFavicon(source)} />
}

Expand Down Expand Up @@ -130,7 +130,10 @@ export const URLShortner = ({ alias, url, editable, isDuplicateAlias, updateAlia
}
}

const text = useMemo(() => (alias ? apiURLs.links.shortendLink(alias, workspaceId()) : window.location.href), [alias])
const text = useMemo(
() => (alias ? apiURLs.links.shortendLink(alias, workspaceId()) : deleteQueryParams(window.location.href)),
[alias]
)

return !editable ? (
alias ? (
Expand Down Expand Up @@ -185,10 +188,11 @@ export const ShortenerComponent = () => {
const { updateAlias, saveLink, isDuplicateAlias } = useLinkURLs()

const link = useMemo(() => {
const l = links.find((l) => l.url === window.location.href)
const url = deleteQueryParams(window.location.href)
const l = links.find((l) => l.url === url)
return (
l ?? {
url: window.location.href,
url: url,
...getGoodMeta(document)
}
)
Expand All @@ -203,11 +207,13 @@ export const ShortenerComponent = () => {
}
}

const url = deleteQueryParams(window.location.href)

return (
<UrlTitleWrapper>
{!editable && !link?.alias && (
<InputContainer>
<FaviconImage source={window.location.href} />
<FaviconImage source={url} />
<ShortenerTitle>{window.location.hostname}</ShortenerTitle>
</InputContainer>
)}
Expand Down
Loading