diff --git a/packages/web/components/patterns/HighlightBar.tsx b/packages/web/components/patterns/HighlightBar.tsx
index ee1b16414..98a92a39a 100644
--- a/packages/web/components/patterns/HighlightBar.tsx
+++ b/packages/web/components/patterns/HighlightBar.tsx
@@ -6,7 +6,7 @@ import { StyledText } from '../elements/StyledText'
import { Button } from '../elements/Button'
import { HStack, Box } from '../elements/LayoutPrimitives'
import { PenWithColorIcon } from '../elements/images/PenWithColorIcon'
-import { Note, Tag, Trash } from 'phosphor-react'
+import { Note, Tag, Trash, Copy } from 'phosphor-react'
type PageCoordinates = {
pageX: number
@@ -21,6 +21,7 @@ export type HighlightAction =
| 'post'
| 'unshare'
| 'setHighlightLabels'
+ | 'copy'
type HighlightBarProps = {
anchorCoordinates: PageCoordinates
@@ -31,50 +32,75 @@ type HighlightBarProps = {
}
export function HighlightBar(props: HighlightBarProps): JSX.Element {
- if (props.displayAtBottom) {
- return (
-
-
-
- )
- } else {
- return (
-
-
-
- )
- }
+ }),
+ ...(!props.displayAtBottom && { left: props.anchorCoordinates.pageX }),
+ ...(!props.displayAtBottom && { top: props.anchorCoordinates.pageY }),
+ }}
+ >
+
+
+ )
+}
+
+type BarButtonProps = {
+ title: string
+ onClick: VoidFunction
+ iconElement: JSX.Element
+ text: string
+}
+
+function BarButton({ text, title, iconElement, onClick }: BarButtonProps) {
+ return (
+
+ )
}
function BarContent(props: HighlightBarProps): JSX.Element {
@@ -96,116 +122,51 @@ function BarContent(props: HighlightBarProps): JSX.Element {
}}
>
{props.isNewHighlight ? (
- }
onClick={() => props.handleButtonClick('create')}
- css={{
- flexDirection: 'column',
- height: '100%',
- m: 0,
- p: 0,
- alignItems: 'baseline',
- }}
- >
-
-
-
- Highlight
-
-
-
+ />
) : (
<>
-
+ }
+ onClick={() => props.handleButtonClick('delete')}
+ />
-
-
+ }
+ onClick={() => props.handleButtonClick('setHighlightLabels')}
+ />
>
)}
-
- {/*
- */}
+ }
+ onClick={() => props.handleButtonClick('comment')}
+ />
+
+
+ }
+ onClick={() => props.handleButtonClick('copy')}
+ />
)
}
diff --git a/packages/web/components/templates/article/HighlightsLayer.tsx b/packages/web/components/templates/article/HighlightsLayer.tsx
index a0f13faee..12f4a7fc1 100644
--- a/packages/web/components/templates/article/HighlightsLayer.tsx
+++ b/packages/web/components/templates/article/HighlightsLayer.tsx
@@ -10,6 +10,7 @@ import type { HighlightLocation } from '../../../lib/highlights/highlightGenerat
import { useSelection } from '../../../lib/highlights/useSelection'
import type { Highlight } from '../../../lib/networking/fragments/highlightFragment'
import {
+ getHighlightElements,
highlightIdAttribute,
highlightNoteIdAttribute,
SelectionAttributes,
@@ -19,7 +20,7 @@ import { removeHighlights } from '../../../lib/highlights/deleteHighlight'
import { createHighlight } from '../../../lib/highlights/createHighlight'
import { HighlightNoteModal } from './HighlightNoteModal'
import { NotebookModal } from './NotebookModal'
-import { showErrorToast } from '../../../lib/toastHelpers'
+import { showErrorToast, showSuccessToast } from '../../../lib/toastHelpers'
import { ArticleMutations } from '../../../lib/articleActions'
import { isTouchScreenDevice } from '../../../lib/deviceType'
import { UserBasicData } from '../../../lib/networking/queries/useGetViewerQuery'
@@ -263,7 +264,7 @@ export function HighlightsLayer(props: HighlightsLayerProps): JSX.Element {
}
const createHighlightCallback = useCallback(
- async (successAction: HighlightModalAction, annotation?: string) => {
+ async (annotation?: string) => {
if (!selectionData) {
return
}
@@ -395,7 +396,7 @@ export function HighlightsLayer(props: HighlightsLayerProps): JSX.Element {
)
const handleCloseNotebook = useCallback(
- (updatedHighlights: Highlight[], deletedHighlights: Highlight[]) => {
+ (updatedHighlights: Highlight[]) => {
props.setShowHighlightsModal(false)
// Remove all the existing highlights, then set the new ones
@@ -454,6 +455,41 @@ export function HighlightsLayer(props: HighlightsLayerProps): JSX.Element {
})
}
break
+ case 'copy': {
+ const selection = window.getSelection()
+ if (selection === null) return
+
+ const userSelectionText = selection.toString()
+ let textToCopy = ''
+
+ if (focusedHighlight) {
+ const highlightedElements = getHighlightElements(
+ focusedHighlight.id
+ )
+ highlightedElements.forEach(
+ (element) => (textToCopy += element.textContent)
+ )
+ } else if (userSelectionText) {
+ textToCopy = userSelectionText
+ }
+
+ if (textToCopy) {
+ try {
+ await navigator.clipboard.writeText(textToCopy)
+ showSuccessToast('Highlight copied', {
+ position: 'bottom-right',
+ })
+ } catch (error) {
+ showErrorToast('Error copying highlight, permission denied.', {
+ position: 'bottom-right',
+ })
+ }
+ }
+
+ selection.empty()
+ setSelectionData(null)
+ break
+ }
case 'setHighlightLabels':
if (props.isAppleAppEmbed) {
window?.webkit?.messageHandlers.highlightAction?.postMessage({
@@ -474,6 +510,7 @@ export function HighlightsLayer(props: HighlightsLayerProps): JSX.Element {
props.isAppleAppEmbed,
removeHighlightCallback,
selectionData,
+ setSelectionData,
]
)
@@ -615,7 +652,7 @@ export function HighlightsLayer(props: HighlightsLayerProps): JSX.Element {
dispatchHighlightMessage('noteCreated')
} else {
try {
- await createHighlightCallback('none', event.annotation)
+ await createHighlightCallback('none')
dispatchHighlightMessage('noteCreated')
} catch (error) {
dispatchHighlightError('saveAnnotation', error)