From b952b3aa76b6fe1b98f452c5d4f866fe5cc74d4c Mon Sep 17 00:00:00 2001 From: Oleksandr Danylchenko Date: Fri, 9 Aug 2024 18:48:11 +0300 Subject: [PATCH] Added spatial tree recalculate completion event --- package-lock.json | 2 ++ packages/text-annotator/package.json | 3 ++- .../src/state/TextAnnotationStore.ts | 6 ++++++ .../src/state/TextAnnotatorState.ts | 4 +++- .../text-annotator/src/state/spatialTree.ts | 19 +++++++++++++++++-- 5 files changed, 30 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index 1530d74c..98fc9d92 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3132,6 +3132,7 @@ "version": "9.0.0", "resolved": "https://registry.npmjs.org/nanoevents/-/nanoevents-9.0.0.tgz", "integrity": "sha512-X8pU7IOpgKXVLPxYUI55ymXc8XuBE+uypfEyEFBtHkD1EX9KavYTVc+vXZHFyHKzA1TaZoVDqklLdQBBrxIuAw==", + "license": "MIT", "engines": { "node": "^18.0.0 || >=20.0.0" } @@ -4371,6 +4372,7 @@ "@annotorious/core": "^3.0.0-rc.31", "colord": "^2.9.3", "dequal": "^2.0.3", + "nanoevents": "^9.0.0", "rbush": "^4.0.0", "uuid": "^10.0.0" }, diff --git a/packages/text-annotator/package.json b/packages/text-annotator/package.json index 81cb5be9..2bc80611 100644 --- a/packages/text-annotator/package.json +++ b/packages/text-annotator/package.json @@ -40,7 +40,8 @@ "@annotorious/core": "^3.0.0-rc.31", "colord": "^2.9.3", "dequal": "^2.0.3", + "nanoevents": "^9.0.0", "rbush": "^4.0.0", "uuid": "^10.0.0" } -} \ No newline at end of file +} diff --git a/packages/text-annotator/src/state/TextAnnotationStore.ts b/packages/text-annotator/src/state/TextAnnotationStore.ts index c8c643db..1e45c595 100644 --- a/packages/text-annotator/src/state/TextAnnotationStore.ts +++ b/packages/text-annotator/src/state/TextAnnotationStore.ts @@ -1,5 +1,9 @@ +import type { Unsubscribe } from 'nanoevents'; import type { Filter, Origin, Store } from '@annotorious/core'; + import type { TextAnnotation } from '../model'; +import type { SpatialTreeEvents } from './spatialTree'; + export interface TextAnnotationStore extends Omit, 'addAnnotation' | 'bulkAddAnnotation'> { @@ -19,6 +23,8 @@ export interface TextAnnotationStore extends Omit, 'addAnn recalculatePositions(): void; + onRecalculatePositions(callback: SpatialTreeEvents['recalculate']): Unsubscribe; + } export interface AnnotationRects { diff --git a/packages/text-annotator/src/state/TextAnnotatorState.ts b/packages/text-annotator/src/state/TextAnnotatorState.ts index 3824b7fd..22af6487 100644 --- a/packages/text-annotator/src/state/TextAnnotatorState.ts +++ b/packages/text-annotator/src/state/TextAnnotatorState.ts @@ -9,7 +9,7 @@ import { Origin, createViewportState } from '@annotorious/core'; -import { createSpatialTree } from './spatialTree'; +import { createSpatialTree, type SpatialTreeEvents } from './spatialTree'; import type { TextAnnotation, TextAnnotationTarget } from '../model'; import type { TextAnnotationStore } from './TextAnnotationStore'; import { isRevived, reviveAnnotation, reviveTarget } from '../utils'; @@ -129,6 +129,7 @@ export const createTextAnnotatorState = ( } const recalculatePositions = () => tree.recalculate(); + const onRecalculatePositions = (callback: SpatialTreeEvents['recalculate']) => tree.on('recalculate', callback); store.observe(({ changes }) => { const deleted = (changes.deleted || []).filter(a => isRevived(a.target.selector)); @@ -156,6 +157,7 @@ export const createTextAnnotatorState = ( getAt, getIntersecting: tree.getIntersecting, recalculatePositions, + onRecalculatePositions, updateTarget }, selection, diff --git a/packages/text-annotator/src/state/spatialTree.ts b/packages/text-annotator/src/state/spatialTree.ts index 675ffe76..cfec5ad8 100644 --- a/packages/text-annotator/src/state/spatialTree.ts +++ b/packages/text-annotator/src/state/spatialTree.ts @@ -1,5 +1,7 @@ import RBush from 'rbush'; import type { Store } from '@annotorious/core'; +import { createNanoEvents, type Unsubscribe } from 'nanoevents'; + import type { TextAnnotation, TextAnnotationTarget } from '../model'; import { isRevived, mergeClientRects } from '../utils'; import { getClientRectsPonyfill } from '../utils/getClientRectsPonyfill'; @@ -30,12 +32,20 @@ interface IndexedHighlightRect { } +export interface SpatialTreeEvents { + + recalculate(): void; + +} + export const createSpatialTree = (store: Store, container: HTMLElement) => { const tree = new RBush(); const index = new Map(); + const emitter = createNanoEvents(); + // Helper: converts a single text annotation target to a list of hightlight rects const toItems = (target: TextAnnotationTarget, offset: DOMRect): IndexedHighlightRect[] => { const rects = target.selector.flatMap(s => { @@ -184,8 +194,12 @@ export const createSpatialTree = (store: Store, container: HTMLE const size = () => tree.all().length; - const recalculate = () => + const recalculate = () => { set(store.all().map(a => a.target), true); + emitter.emit('recalculate'); + }; + + const on = (event: E, callback: SpatialTreeEvents[E]): Unsubscribe => emitter.on(event, callback); return { all, @@ -199,7 +213,8 @@ export const createSpatialTree = (store: Store, container: HTMLE remove, set, size, - update + update, + on } }