Skip to content

Commit 28a174b

Browse files
committed
Highlights basically work
1 parent 39dfafa commit 28a174b

File tree

2 files changed

+38
-73
lines changed

2 files changed

+38
-73
lines changed

src/app/content/highlights/components/CardWrapper.tsx

Lines changed: 29 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import ResizeObserver from 'resize-observer-polyfill';
66
import styled from 'styled-components';
77
import { isHtmlElement } from '../../../guards';
88
import { useFocusLost, useKeyCombination, useFocusHighlight } from '../../../reactUtils';
9-
import { AppState } from '../../../types';
9+
import { AppState, Dispatch } from '../../../types';
1010
import { assertDefined, assertDocument } from '../../../utils';
1111
import * as selectSearch from '../../search/selectors';
1212
import * 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

2829
function 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-
9691
function 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
256212
const 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>;

src/app/content/highlights/components/EditCard.tsx

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,12 @@ function LoginOrEdit({
6767
const authenticated = !!useSelector(selectAuth.user);
6868
const element = React.useRef<HTMLElement>(null);
6969
const {formatMessage} = useIntl();
70+
const showCard = React.useCallback((event: React.MouseEvent) => {
71+
if (event.button === 0) {
72+
event.preventDefault();
73+
document?.dispatchEvent(new CustomEvent('showCardEvent', { bubbles: true }));
74+
}
75+
}, []);
7076

7177
return (
7278
<div
@@ -87,7 +93,9 @@ function LoginOrEdit({
8793
<ActiveEditCard props={props} element={element} />
8894
</form>
8995
) :
90-
<i>Press Enter or double-click highlight to edit highlight</i>
96+
<button type="button" onMouseDown={showCard}>
97+
Press Enter or click here to edit highlight
98+
</button>
9199
}
92100
</HiddenOnMobile>
93101
) : <LoginConfirmation onBlur={props.onBlur} />

0 commit comments

Comments
 (0)