@@ -6,7 +6,7 @@ import ResizeObserver from 'resize-observer-polyfill';
66import styled from 'styled-components' ;
77import { isHtmlElement } from '../../../guards' ;
88import { useFocusLost , useKeyCombination , useFocusHighlight } from '../../../reactUtils' ;
9- import { AppState } from '../../../types' ;
9+ import { AppState , Dispatch } from '../../../types' ;
1010import { assertDefined , assertDocument } from '../../../utils' ;
1111import * as selectSearch from '../../search/selectors' ;
1212import * as contentSelect from '../../selectors' ;
@@ -23,6 +23,7 @@ export interface WrapperProps {
2323 highlighter : Highlighter ;
2424 highlights : Highlight [ ] ;
2525 className ?: string ;
26+ dispatch : Dispatch ;
2627}
2728
2829function checkIfHiddenByCollapsedAncestor ( highlight : Highlight ) {
@@ -87,64 +88,34 @@ function useCardsHeights() {
8788 return [ cardsHeights , onHeightChange ] as const ;
8889}
8990
90- function rangeString ( { startOffset, endOffset} : Highlight [ 'range' ] ) {
91- return `${ startOffset } -${ endOffset } ` ;
92- }
93-
94- const ELAPSED_LIMIT = 100 ;
95-
9691function useFocusedHighlight (
9792 highlights : Highlight [ ] ,
9893 element : React . RefObject < HTMLElement > ,
99- container : HTMLElement
94+ container : HTMLElement ,
10095) {
10196 const focusedId = useSelector ( focused ) ;
10297 const focusedHighlight = React . useMemo (
10398 ( ) => highlights . find ( ( highlight ) => highlight . id === focusedId ) ,
10499 [ focusedId , highlights ] ) ;
105100 const [ shouldFocusCard , setShouldFocusCard ] = React . useState ( false ) ;
106101 const document = assertDocument ( ) ;
107- const previousRange = React . useRef < string > ( '' ) ;
108- const [ dblclickStamp , setDblclickStamp ] = React . useState < number > ( 0 ) ;
109102
103+ // catches the "click here" event sent by the EditCard
110104 React . useEffect ( ( ) => {
111- const handler = ( ) => setDblclickStamp ( Date . now ( ) ) ;
105+ const handler = ( ) => setShouldFocusCard ( true ) ;
112106
113- document . addEventListener ( 'dblclick ' , handler ) ;
114- return ( ) => document . removeEventListener ( 'dblclick ' , handler ) ;
107+ document . addEventListener ( 'showCardEvent ' , handler ) ;
108+ return ( ) => document . removeEventListener ( 'showCardEvent ' , handler ) ;
115109 } , [ document ] ) ;
116110
117- // Tracking double clicks
118- // double-click events trigger updates to focusedHighlight, but the order and
119- // timing of processing can vary, so we check conditions within a short time
120- // of a double click.
111+ // Ensure focusedHighlight is actually focused
121112 React . useEffect ( ( ) => {
122- if ( focusedHighlight ) {
123- const elapsed = Date . now ( ) - dblclickStamp ;
124- const isDoubleClick = elapsed < ELAPSED_LIMIT ;
125-
126- // Existing highlight
127- if ( focusedHighlight . elements . length > 0 ) {
128- if ( isDoubleClick ) {
129- // Unselect text inside existing highlight.
130- document . getSelection ( ) ?. removeAllRanges ( ) ;
131- setShouldFocusCard ( true ) ;
132- }
133- return ;
134- }
135-
136- // Text selection that could be a highlight
137- const newRange = rangeString ( focusedHighlight . range ) ;
138- const isExistingSelection = newRange === previousRange . current ;
139-
140- if ( isExistingSelection && isDoubleClick ) {
141- setShouldFocusCard ( true ) ;
142- }
143- previousRange . current = newRange ;
113+ if ( focusedHighlight && focusedHighlight . elements . length > 0 ) {
114+ focusedHighlight ?. focus ( ) ;
144115 }
145- } , [ focusedHighlight , document , dblclickStamp ] ) ;
116+ } , [ focusedHighlight ] ) ;
146117
147- // Let Enter go from a highlight to the editor
118+ // Pressing Enter moves the users from a highlight to the editor
148119 const editOnEnter = React . useCallback ( ( ) => {
149120 if ( focusedHighlight ) {
150121 setShouldFocusCard ( true ) ;
@@ -169,41 +140,17 @@ function useFocusedHighlight(
169140 // If we don't do this then card related for the focused highlight will be focused automatically.
170141 useFocusLost ( element , shouldFocusCard , React . useCallback ( ( ) => setShouldFocusCard ( false ) , [ ] ) ) ;
171142
172- // If the user tab-navigates somewhere else, clear the selection
173- React . useEffect ( ( ) => {
174- const handleFocusChange = ( ) => {
175- const selection = document . getSelection ( ) ;
176-
177- if ( ! selection ?. rangeCount ) {
178- return ;
179- }
180- const userRange = selection ?. getRangeAt ( 0 ) ;
181-
182- if ( userRange ?. intersectsNode ( document . activeElement as HTMLElement ) ) {
183- return ;
184- }
185-
186- selection ?. empty ( ) ;
187- setShouldFocusCard ( false ) ;
188- } ;
189-
190- document . addEventListener ( 'focusin' , handleFocusChange ) ;
191- document . addEventListener ( 'focusout' , handleFocusChange ) ;
192-
193- return ( ) => {
194- document . removeEventListener ( 'focusin' , handleFocusChange ) ;
195- document . removeEventListener ( 'focusout' , handleFocusChange ) ;
196- } ;
197- } , [ document ] ) ;
198-
199- return [ focusedHighlight , shouldFocusCard ] as const ;
143+ return [ focusedHighlight , shouldFocusCard , setShouldFocusCard ] as const ;
200144}
201145
202- function CardsForHighlights ( { highlights, container, focusedHighlight, shouldFocusCard, highlighter} : {
146+ function CardsForHighlights ( {
147+ highlights, container, focusedHighlight, shouldFocusCard, setShouldFocusCard, highlighter
148+ } : {
203149 highlights : Highlight [ ] ;
204150 container : HTMLElement ;
205151 focusedHighlight : Highlight | undefined ;
206152 shouldFocusCard : boolean ;
153+ setShouldFocusCard : ( v : boolean ) => void ;
207154 highlighter : Highlighter ;
208155} ) {
209156 const [ cardsHeights , onHeightChange ] = useCardsHeights ( ) ;
@@ -217,9 +164,18 @@ function CardsForHighlights({highlights, container, focusedHighlight, shouldFocu
217164 editCardVisibilityHandler ,
218165 new Map ( highlights . map ( ( highlight ) => [ highlight . id , false ] ) )
219166 ) ;
167+
168+ // First time, Esc closes it to the instructions; second Esc disappears it
220169 const hideCard = ( ) => {
170+ if ( ! focusedHighlight ?. elements . length ) {
171+ return ;
172+ }
221173 focusedHighlight ?. focus ( ) ;
222- dispatch ( { type : 'HIDE' , id : focusedHighlight ?. id } ) ;
174+ if ( shouldFocusCard ) {
175+ setShouldFocusCard ( false ) ;
176+ } else {
177+ dispatch ( { type : 'HIDE' , id : focusedHighlight ?. id } ) ;
178+ }
223179 } ;
224180 const showCard = ( cardId : string | undefined ) => {
225181 dispatch ( { type : 'SHOW' , id : cardId } ) ;
@@ -255,14 +211,15 @@ function CardsForHighlights({highlights, container, focusedHighlight, shouldFocu
255211// tslint:disable-next-line:variable-name
256212const Wrapper = ( { highlights, className, container, highlighter} : WrapperProps ) => {
257213 const element = React . useRef < HTMLElement > ( null ) ;
258- const [ focusedHighlight , shouldFocusCard ] = useFocusedHighlight ( highlights , element , container ) ;
214+ const [ focusedHighlight , shouldFocusCard , setShouldFocusCard ] = useFocusedHighlight ( highlights , element , container ) ;
259215
260216 return < div className = { className } ref = { element } >
261217 < CardsForHighlights
262218 highlights = { highlights }
263219 container = { container }
264220 focusedHighlight = { focusedHighlight }
265221 shouldFocusCard = { shouldFocusCard }
222+ setShouldFocusCard = { setShouldFocusCard }
266223 highlighter = { highlighter }
267224 />
268225 </ div > ;
0 commit comments