Skip to content

Commit d3d7a7e

Browse files
committed
fix: remove introduced text selection issue and bump version to 1.0.0-beta3
1 parent 675082c commit d3d7a7e

File tree

4 files changed

+54
-14
lines changed

4 files changed

+54
-14
lines changed

.github/workflows/release.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,4 +81,4 @@ jobs:
8181
- name: Build documentation
8282
run: |
8383
git fetch origin gh-pages
84-
mike deploy --push --no-redirect --update-aliases $GITHUB_REF_NAME latest
84+
mike deploy --push --alias-type=copy --update-aliases $GITHUB_REF_NAME latest

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Changelog
22

3+
## v1.0.0.beta3
4+
5+
- Fix AnnotatedText bug in text selection on desktop browsers
6+
37
## v1.0.0.beta2
48

59
- Improved visibility of highlighted spans and layout of boxes with mixed inset/outset nesting

client/components/AnnotatedText/index.tsx

Lines changed: 48 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,11 @@ import {
1818

1919
import "./style.css";
2020

21+
const isMobileDevice = (): boolean => {
22+
if (typeof window === "undefined" || typeof navigator === "undefined") return false;
23+
return /Mobi|Android|iPhone|iPad|iPod|Windows Phone|IEMobile|Opera Mini/i.test(navigator.userAgent || "");
24+
};
25+
2126
const toLuminance = (color: Color, y: number = 0.6) => {
2227
// This is mostly used to adapt to light/dark mode
2328

@@ -539,34 +544,45 @@ export class AnnotatedText extends React.Component<TextData & TextMethods> {
539544
}
540545

541546
componentDidMount() {
542-
document.addEventListener('selectionchange', this._boundSelectionChange);
547+
if (!isMobileDevice()) return;
548+
document.addEventListener("selectionchange", this._boundSelectionChange);
543549
}
544550

545551
componentWillUnmount() {
546-
document.removeEventListener('selectionchange', this._boundSelectionChange);
552+
if (!isMobileDevice()) return;
553+
document.removeEventListener("selectionchange", this._boundSelectionChange);
547554
}
548555

549556
private isNodeInside = (node: Node | null) => {
550557
const container = this.containerRef.current;
551-
return !!container && !!node && (node === container || container.contains(node as Node));
558+
return (
559+
!!container &&
560+
!!node &&
561+
(node === container || container.contains(node as Node))
562+
);
552563
};
553564

554565
handleSelectionChange = () => {
555566
if (this._ignoreSelectionChange) return;
556-
const sel = typeof window !== 'undefined' ? window.getSelection?.() : null;
567+
const sel = typeof window !== "undefined" ? window.getSelection?.() : null;
557568
if (!sel || sel.isCollapsed) return;
558-
if (!this.isNodeInside(sel.anchorNode) && !this.isNodeInside(sel.focusNode)) return;
569+
if (!this.isNodeInside(sel.anchorNode) && !this.isNodeInside(sel.focusNode))
570+
return;
559571
// Wait a tick so the browser finalizes the selection on mobile
560572
setTimeout(() => {
561573
const spans = getDocumentSelectedRanges();
562574
if (spans && spans.length > 0) {
563575
this._ignoreSelectionChange = true;
564576
this.props.onMouseSelect?.(spans, makeModKeys({} as any));
565-
try { window.getSelection()?.removeAllRanges(); } catch {}
566-
setTimeout(() => { this._ignoreSelectionChange = false; }, 0);
577+
try {
578+
window.getSelection()?.removeAllRanges();
579+
} catch {}
580+
setTimeout(() => {
581+
this._ignoreSelectionChange = false;
582+
}, 0);
567583
}
568584
}, 0);
569-
}
585+
};
570586

571587
handleKeyUp = (event: React.KeyboardEvent) => {
572588
// if (event.metaKey || event.key === 'Meta' || event.shiftKey || event.key === 'Shift') {
@@ -590,18 +606,35 @@ export class AnnotatedText extends React.Component<TextData & TextMethods> {
590606
}
591607
};
592608

593-
handleMouseUp = (
609+
handleTouchUp = (
594610
event: React.MouseEvent<HTMLElement> | React.TouchEvent<HTMLElement>
595611
) => {
596612
const spans = getDocumentSelectedRanges();
597613
this._ignoreSelectionChange = true; // prevent our own clear from retriggering
598-
try { window.getSelection()?.removeAllRanges(); } catch {}
614+
try {
615+
window.getSelection()?.removeAllRanges();
616+
} catch {}
599617
if (spans.length > 0) {
600618
this.props.onMouseSelect?.(spans, makeModKeys(event as any));
601619
} else {
602620
this.props.onMouseSelect?.([], makeModKeys(event as any));
603621
}
604-
setTimeout(() => { this._ignoreSelectionChange = false; }, 0);
622+
setTimeout(() => {
623+
this._ignoreSelectionChange = false;
624+
}, 0);
625+
};
626+
627+
handleMouseUp = (event: React.MouseEvent<HTMLElement>) => {
628+
if (event.type === "mouseup") {
629+
const spans = getDocumentSelectedRanges();
630+
window.getSelection().removeAllRanges();
631+
if (spans.length > 0) {
632+
//this.props.onMouseSelect([...this.props.mouse_selection, ...spans]);
633+
this.props.onMouseSelect?.(spans, makeModKeys(event));
634+
} else {
635+
this.props.onMouseSelect?.([], makeModKeys(event));
636+
}
637+
}
605638
};
606639

607640
handleClickSpan = (event, span_id) => {
@@ -669,7 +702,10 @@ export class AnnotatedText extends React.Component<TextData & TextMethods> {
669702
className="metanno-text-view"
670703
ref={this.containerRef}
671704
onMouseUp={this.handleMouseUp}
672-
onTouchEnd={(e) => { e.persist?.(); setTimeout(() => this.handleMouseUp(e as any), 0); }}
705+
onTouchEnd={(e) => {
706+
e.persist?.();
707+
setTimeout(() => this.handleTouchUp(e as any), 0);
708+
}}
673709
onTouchCancel={(e) => this.props.onMouseSelect?.([], makeModKeys(e))}
674710
onKeyDown={this.handleKeyDown}
675711
onKeyUp={this.handleKeyUp}

metanno/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = "1.0.0-beta.2"
1+
__version__ = "1.0.0-beta.3"

0 commit comments

Comments
 (0)