Fix reader header offset, add labels icon to highlights

This commit is contained in:
Jackson Harper 2024-02-16 15:34:39 +08:00
parent 2615a0d33e
commit 2aa7c1a7d4
6 changed files with 85 additions and 33 deletions

View file

@ -22,20 +22,20 @@ export class FollowingIcon extends React.Component<IconProps> {
d="M12.5 4.5L4.5 8.5L12.5 12.5L20.5 8.5L12.5 4.5Z"
fill={color}
stroke={color}
stroke-linecap="round"
stroke-linejoin="round"
strokeLinecap="round"
strokeLinejoin="round"
/>
<path
d="M4.5 12.5L12.5 16.5L20.5 12.5"
stroke={color}
stroke-linecap="round"
stroke-linejoin="round"
strokeLinecap="round"
strokeLinejoin="round"
/>
<path
d="M4.5 16.5L12.5 20.5L20.5 16.5"
stroke={color}
stroke-linecap="round"
stroke-linejoin="round"
strokeLinecap="round"
strokeLinejoin="round"
/>
</g>
</svg>

View file

@ -12,6 +12,7 @@ import type { Highlight } from '../../../lib/networking/fragments/highlightFragm
import {
getHighlightElements,
highlightIdAttribute,
highlightLabelIdAttribute,
highlightNoteIdAttribute,
SelectionAttributes,
} from '../../../lib/highlights/highlightHelpers'
@ -79,15 +80,13 @@ export function HighlightsLayer(props: HighlightsLayerProps): JSX.Element {
const focusedHighlightMousePos = useRef({ pageX: 0, pageY: 0 })
const [currentHighlightIdx, setCurrentHighlightIdx] = useState(0)
const [focusedHighlight, setFocusedHighlight] = useState<
Highlight | undefined
>(undefined)
const [focusedHighlight, setFocusedHighlight] =
useState<Highlight | undefined>(undefined)
const [selectionData, setSelectionData] = useSelection(highlightLocations)
const [labelsTarget, setLabelsTarget] = useState<Highlight | undefined>(
undefined
)
const [labelsTarget, setLabelsTarget] =
useState<Highlight | undefined>(undefined)
const [
confirmDeleteHighlightWithNoteId,
@ -388,6 +387,13 @@ export function HighlightsLayer(props: HighlightsLayerProps): JSX.Element {
highlight: highlight,
highlightModalAction: 'addComment',
})
} else if ((target as Element).hasAttribute(highlightLabelIdAttribute)) {
const id = (target as HTMLSpanElement).getAttribute(
highlightLabelIdAttribute
)
const highlight = highlights.find(($0) => $0.id === id)
setFocusedHighlight(highlight)
setLabelsTarget(highlight)
} else {
window?.webkit?.messageHandlers.viewerAction?.postMessage({
actionID: 'pageTapped',
@ -395,7 +401,7 @@ export function HighlightsLayer(props: HighlightsLayerProps): JSX.Element {
setFocusedHighlight(undefined)
}
},
[openNoteModal, highlights]
[openNoteModal, highlights, setLabelsTarget]
)
const handleDoubleClick = useCallback(

View file

@ -26,6 +26,7 @@ export function ReaderHeader(props: ReaderHeaderProps): JSX.Element {
left: '0',
zIndex: 1,
pt: '0px',
pb: '15px',
position: 'fixed',
width: '100%',
height: DEFAULT_HEADER_HEIGHT,

View file

@ -4,7 +4,9 @@ import type { Highlight } from '../networking/fragments/highlightFragment'
import { interpolationSearch } from './interpolationSearch'
import {
highlightIdAttribute,
highlightLabelIdAttribute,
highlightNoteIdAttribute,
labelsImage,
noteImage,
} from './highlightHelpers'
@ -80,10 +82,18 @@ function nodeAttributesFromHighlight(
const patch = highlight.patch
const id = highlight.id
const withNote = !!highlight.annotation
const withLabels = (highlight.labels?.length ?? 0) > 0
const tooltip = undefined
const customColor = highlight.color
return makeHighlightNodeAttributes(patch, id, withNote, customColor, tooltip)
return makeHighlightNodeAttributes(
patch,
id,
withNote,
withLabels,
customColor,
tooltip
)
}
/**
@ -100,6 +110,7 @@ export function makeHighlightNodeAttributes(
patch: string,
id: string,
withNote: boolean,
withLabels: boolean,
customColor?: string,
tooltip?: string
): HighlightNodeAttributes {
@ -183,12 +194,10 @@ export function makeHighlightNodeAttributes(
startingTextNodeIndex++
}
if (withNote && lastElement) {
lastElement.classList.add('last_element')
const svg = noteImage(customColor)
svg.setAttribute(highlightNoteIdAttribute, id)
const ctr = document.createElement('div')
const ctr = document.createElement('span')
ctr.className = 'highlight_note_button'
ctr.appendChild(svg)
ctr.setAttribute(highlightNoteIdAttribute, id)
@ -197,6 +206,19 @@ export function makeHighlightNodeAttributes(
lastElement.appendChild(ctr)
}
if (withLabels && lastElement) {
const svg = labelsImage(customColor)
svg.setAttribute(highlightLabelIdAttribute, id)
const ctr = document.createElement('span')
ctr.className = 'highlight_label_button'
ctr.appendChild(svg)
ctr.setAttribute(highlightLabelIdAttribute, id)
ctr.setAttribute('width', '14px')
ctr.setAttribute('height', '14px')
lastElement.appendChild(ctr)
}
return {
prefix,
@ -209,10 +231,10 @@ export function makeHighlightNodeAttributes(
/**
* Given a text selection by user, annotate the article around the selection and
* produce a {@link https://github.com/google/diff-match-patch | diff patch}
*
* produce a {@link https://github.com/google/diff-match-patch | diff patch}
*
* The diff patch is used for identifying the selection/highlight location
*
*
* @param range text selection range
* @returns diff patch
*/
@ -304,11 +326,11 @@ const getArticleTextNodes = (
/**
* Return the offsets to the selection/highlight
*
*
* @param patch {@link generateDiffPatch|diff patch} identifying a selection/highlight location
* @returns
* @returns
* - highlightTextStart - The start of highlight, offset from the start of article by characters
* - highlightTextEnd - The end of highlight (non-inclusive), offset from the start of article by characters
* - highlightTextEnd - The end of highlight (non-inclusive), offset from the start of article by characters
* - matchingHighlightContent - the matched highlight
*/
const selectionOffsetsFromPatch = (

View file

@ -14,6 +14,7 @@ export type SelectionAttributes = {
export const highlightIdAttribute = 'omnivore-highlight-id'
export const highlightNoteIdAttribute = 'omnivore-highlight-note-id'
export const highlightLabelIdAttribute = 'omnivore-highlight-label-id'
export function getHighlightElements(highlightId: string): Element[] {
return Array.from(
@ -46,3 +47,23 @@ export function noteImage(color: string | undefined): SVGSVGElement {
svg.appendChild(path)
return svg
}
export const labelsImage = (color: string | undefined): SVGSVGElement => {
const svgURI = 'http://www.w3.org/2000/svg'
const svg = document.createElementNS(svgURI, 'svg')
svg.setAttribute('viewBox', '0 0 14 14')
svg.setAttribute('width', '14')
svg.setAttribute('height', '14')
svg.setAttribute('fill', 'none')
const path = document.createElementNS(svgURI, 'path')
path.setAttribute(
'd',
'M1.75 3.5V6.517C1.75007 6.82639 1.87303 7.12309 2.09183 7.34183L6.58933 11.8393C6.85297 12.1029 7.21052 12.251 7.58333 12.251C7.95615 12.251 8.3137 12.1029 8.57733 11.8393L11.8393 8.57733C12.1029 8.3137 12.251 7.95615 12.251 7.58333C12.251 7.21052 12.1029 6.85297 11.8393 6.58933L7.34183 2.09183C7.12309 1.87303 6.82639 1.75007 6.517 1.75H3.5C3.03587 1.75 2.59075 1.93437 2.26256 2.26256C1.93437 2.59075 1.75 3.03587 1.75 3.5Z'
)
path.setAttribute('stroke', `rgba(${highlightColorVar(color)}, 0.8)`)
path.setAttribute('stroke-width', '1.8')
path.setAttribute('stroke-linejoin', 'round')
svg.appendChild(path)
return svg
}

View file

@ -44,23 +44,25 @@
font-family: var(--text-font-family);
}
.article-inner-css .highlight_with_note .highlight_note_button {
.article-inner-css .highlight_note_button {
display: unset !important;
margin: 0px !important;
max-width: unset !important;
height: unset !important;
padding: 0px 8px;
cursor: pointer;
margin-left: 5px !important;
}
.article-inner-css .highlight_label_button {
display: unset !important;
margin: 0px !important;
max-width: unset !important;
height: unset !important;
padding: 0px 8px;
cursor: pointer;
margin-left: 4px !important;
}
/*
on smaller screens we display the note icon
@media (max-width: 768px) {
.highlight_with_note.last_element:after {
content: url(/static/icons/highlight-note-icon.svg);
padding: 0 3px;
cursor: pointer;
}
} */
.article-inner-css h1,
.article-inner-css h2,