Browse Source

fix highlights

imwald
Silberengel 2 weeks ago
parent
commit
1eb9e867cc
  1. 72
      src/components/Note/SelectionHighlightTrigger.tsx

72
src/components/Note/SelectionHighlightTrigger.tsx

@ -1,5 +1,6 @@ @@ -1,5 +1,6 @@
import { buildHighlightDataFromEvent } from '@/lib/build-highlight-data'
import { useCreateHighlight } from './CreateHighlightContext'
import { Drawer, DrawerContent, DrawerHeader, DrawerTitle } from '@/components/ui/drawer'
import { useScreenSize } from '@/providers/ScreenSizeProvider'
import { Event } from 'nostr-tools'
import { Highlighter } from 'lucide-react'
@ -7,7 +8,9 @@ import { useCallback, useEffect, useRef, useState } from 'react' @@ -7,7 +8,9 @@ import { useCallback, useEffect, useRef, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { Button } from '@/components/ui/button'
/** After finger lift, wait before treating the gesture as finished (handle drag may still run). */
const MOBILE_TOUCH_END_SETTLE_MS = 600
/** After selection stops changing, wait before opening the drawer so handles can extend the range. */
const MOBILE_SELECTION_STABLE_MS = 1600
const DESKTOP_SELECTION_DELAY_MS = 50
@ -79,6 +82,7 @@ export default function SelectionHighlightTrigger({ @@ -79,6 +82,7 @@ export default function SelectionHighlightTrigger({
const [selectedText, setSelectedText] = useState('')
const [paragraphContext, setParagraphContext] = useState('')
const [toolbarPos, setToolbarPos] = useState<{ top: number; left: number } | null>(null)
const [showMobileDrawer, setShowMobileDrawer] = useState(false)
const debounceRef = useRef<ReturnType<typeof setTimeout> | null>(null)
const touchEndTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null)
@ -90,6 +94,7 @@ export default function SelectionHighlightTrigger({ @@ -90,6 +94,7 @@ export default function SelectionHighlightTrigger({
setSelectedText('')
setParagraphContext('')
setToolbarPos(null)
setShowMobileDrawer(false)
}, [])
const applySelection = useCallback(
@ -101,19 +106,25 @@ export default function SelectionHighlightTrigger({ @@ -101,19 +106,25 @@ export default function SelectionHighlightTrigger({
return
}
if (isSmallScreen && isSelectingRef.current && !forceShow) return
setSelectedText(hit.selectedText)
setParagraphContext(hit.paragraphContext)
const toolbarHeight = isSmallScreen ? 48 : 44
const toolbarWidth = isSmallScreen ? 200 : 176
if (isSmallScreen) {
if (forceShow || !isSelectingRef.current) {
setShowMobileDrawer(true)
setToolbarPos(null)
}
return
}
const toolbarHeight = 44
const margin = 8
const top =
hit.rect.top - toolbarHeight < margin ? hit.rect.bottom + margin : hit.rect.top - toolbarHeight
const rawLeft = hit.rect.left + hit.rect.width / 2 - toolbarWidth / 2
const left = Math.max(margin, Math.min(rawLeft, window.innerWidth - toolbarWidth - margin))
const rawLeft = hit.rect.left + hit.rect.width / 2 - 80
const left = Math.max(margin, Math.min(rawLeft, window.innerWidth - 176 - margin))
setToolbarPos({ top, left })
setShowMobileDrawer(false)
},
[clearUi, isSmallScreen, openHighlight]
)
@ -149,14 +160,14 @@ export default function SelectionHighlightTrigger({ @@ -149,14 +160,14 @@ export default function SelectionHighlightTrigger({
if (!isSmallScreen) return
isSelectingRef.current = true
if (selectionStableTimeoutRef.current) clearTimeout(selectionStableTimeoutRef.current)
setToolbarPos(null)
setShowMobileDrawer(false)
}
const onTouchMove = () => {
if (!isSmallScreen) return
isSelectingRef.current = true
if (selectionStableTimeoutRef.current) clearTimeout(selectionStableTimeoutRef.current)
setToolbarPos(null)
setShowMobileDrawer(false)
}
const onTouchEnd = () => {
@ -186,7 +197,6 @@ export default function SelectionHighlightTrigger({ @@ -186,7 +197,6 @@ export default function SelectionHighlightTrigger({
return
}
setToolbarPos(null)
scheduleMobileStableSelection()
return
}
@ -243,12 +253,12 @@ export default function SelectionHighlightTrigger({ @@ -243,12 +253,12 @@ export default function SelectionHighlightTrigger({
if (!openHighlight) return <>{children}</>
const showToolbar = selectedText && toolbarPos
const showDesktopToolbar = !isSmallScreen && selectedText && toolbarPos
return (
<div ref={containerRef} className="relative select-text">
{children}
{showToolbar ? (
{showDesktopToolbar ? (
<>
<div
className="highlight-button-container fixed z-[150] flex items-center gap-1 rounded-md border bg-background px-2 py-1.5 shadow-lg"
@ -258,8 +268,8 @@ export default function SelectionHighlightTrigger({ @@ -258,8 +268,8 @@ export default function SelectionHighlightTrigger({
<Button
type="button"
variant="ghost"
size={isSmallScreen ? 'default' : 'sm'}
className={isSmallScreen ? 'h-10 gap-1.5' : 'h-8 gap-1.5'}
size="sm"
className="h-8 gap-1.5"
onClick={(e) => {
e.stopPropagation()
handleCreateHighlight()
@ -271,8 +281,8 @@ export default function SelectionHighlightTrigger({ @@ -271,8 +281,8 @@ export default function SelectionHighlightTrigger({
<Button
type="button"
variant="ghost"
size={isSmallScreen ? 'default' : 'sm'}
className={isSmallScreen ? 'h-10 px-3' : 'h-8 px-2'}
size="sm"
className="h-8 px-2"
onClick={(e) => {
e.stopPropagation()
handleDismiss()
@ -281,16 +291,44 @@ export default function SelectionHighlightTrigger({ @@ -281,16 +291,44 @@ export default function SelectionHighlightTrigger({
{t('Cancel')}
</Button>
</div>
{!isSmallScreen ? (
<div
className="fixed inset-0 z-[149]"
aria-hidden
data-selection-highlight-ui
onClick={handleDismiss}
/>
) : null}
</>
) : null}
{isSmallScreen ? (
<Drawer
open={showMobileDrawer && selectedText.length > 0}
onOpenChange={(open) => {
setShowMobileDrawer(open)
if (!open) handleDismiss()
}}
>
<DrawerContent data-selection-highlight-ui>
<DrawerHeader>
<DrawerTitle>{t('Create Highlight')}</DrawerTitle>
</DrawerHeader>
<div className="space-y-4 p-4 pb-8">
<div className="text-sm text-muted-foreground">{t('Selected text')}:</div>
<div className="break-words rounded-lg bg-muted p-3 text-sm">&ldquo;{selectedText}&rdquo;</div>
<Button
className="w-full"
onClick={(e) => {
e.stopPropagation()
handleCreateHighlight()
}}
>
<Highlighter className="mr-2 h-4 w-4" />
{t('Create Highlight')}
</Button>
</div>
</DrawerContent>
</Drawer>
) : null}
</div>
)
}

Loading…
Cancel
Save