diff --git a/annotations.js b/annotations.js deleted file mode 100644 index dc9a638..0000000 --- a/annotations.js +++ /dev/null @@ -1,65 +0,0 @@ -export class Annotations { - #annotationsByIndex = new Map() - #byValue = new Map() - #anchorsByValue = new Map() - #indicesByValue = new Map() - constructor({ resolve, compare, onAdd, onDelete, onUpdate }) { - this.resolve = resolve - this.compare = compare - this.onAdd = onAdd - this.onDelete = onDelete - this.onUpdate = onUpdate - } - async add(annotation, sorted) { - const { value } = annotation - if (this.#byValue.has(value)) return - const { index, anchor } = await this.resolve(value) - this.#byValue.set(value, annotation) - this.#indicesByValue.set(value, index) - this.#anchorsByValue.set(value, anchor) - if (this.#annotationsByIndex.has(index)) { - const arr = this.#annotationsByIndex.get(index) - if (sorted) { - arr.push(annotation) - this.onAdd?.(annotation, index, arr.length - 1) - } else { - let position = 0 - for (let i = 0; i < arr.length; i++) { - const itemValue = arr[i].value - if (this.compare(value, itemValue) <= 0) break - position = i + 1 - } - arr.splice(position, 0, annotation) - this.onAdd?.(annotation, index, position) - } - } else { - this.#annotationsByIndex.set(index, [annotation]) - this.onAdd?.(annotation, index, 0) - } - } - update(annotation) { - const index = this.#indicesByValue.get(annotation.value) - const old = this.#byValue.get(annotation.value) - Object.assign(old, annotation) - this.onUpdate?.(annotation, index) - } - delete(value) { - const index = this.#indicesByValue.get(value) - const arr = this.#annotationsByIndex.get(index) - const position = arr.findIndex(a => a.value === value) - arr.splice(position, 1) - this.#byValue.delete(value) - this.#indicesByValue.delete(value) - this.#anchorsByValue.delete(value) - this.onDelete?.(value, index, position) - } - getByIndex(index) { - return this.#annotationsByIndex.get(index) ?? [] - } - getAnchor(value) { - return this.#anchorsByValue.get(value) - } - export() { - return Array.from(this.#annotationsByIndex.values()).flat() - } -} diff --git a/view.js b/view.js index ff26729..9fed796 100644 --- a/view.js +++ b/view.js @@ -1,7 +1,6 @@ import * as CFI from './epubcfi.js' import { TOCProgress, SectionProgress } from './progress.js' import { Overlayer } from './overlayer.js' -import { Annotations } from './annotations.js' const textWalker = function* (doc, func) { const filter = NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_TEXT @@ -85,27 +84,6 @@ export class View { textDirection = '' isCJK = false isFixedLayout = false - annotations = new Annotations({ - resolve: value => this.resolveCFI(value), - compare: CFI.compare, - onAdd: (annotation, index, position) => { - const o = this.#getOverlayer(index) - if (o) this.#drawAnnotation(o.doc, o.overlayer, annotation) - const label = this.#tocProgress.getProgress(index)?.label ?? '' - this.emit?.({ type: 'add-annotation', annotation, label, index, position }) - }, - onDelete: (key, index, position) => { - this.#getOverlayer(index)?.overlayer?.remove(key) - this.emit?.({ type: 'delete-annotation', index, position }) - }, - onUpdate: (annotation, index) => { - const o = this.#getOverlayer(index) - if (o) { - o.overlayer.remove(annotation.value) - this.#drawAnnotation(o.doc, o.overlayer, annotation) - } - }, - }) constructor(book, emit) { this.book = book this.emit = emit @@ -149,18 +127,12 @@ export class View { } return this.renderer.element } - async init({ lastLocation, annotations }) { + async init({ lastLocation }) { if (lastLocation) { const resolved = this.resolveNavigation(lastLocation) if (resolved) await this.renderer.goTo(resolved) else await this.renderer.next() } else await this.renderer.next() - - if (annotations) { - annotations.sort((a, b) => CFI.compare(a.value, b.value)) - for (const annotation of annotations) - await this.annotations.add(annotation, true) - } } #onRelocated(range, index, fraction, size) { if (!this.#sectionProgress) return @@ -207,12 +179,24 @@ export class View { this.emit?.({ type: 'loaded', doc, index }) } - #drawAnnotation(doc, overlayer, annotation) { + async addAnnotation(annotation, remove) { const { value } = annotation - const anchor = this.annotations.getAnchor(value) - const range = doc ? anchor(doc) : anchor - const [func, opts] = this.emit({ type: 'draw-annotation', annotation }) - overlayer.add(value, range, func, opts) + const { index, anchor } = await this.resolveNavigation(value) + const obj = this.#getOverlayer(index) + if (obj) { + const { overlayer, doc } = obj + overlayer.remove(value) + if (!remove) { + const range = doc ? anchor(doc) : anchor + const [func, opts] = this.emit({ type: 'draw-annotation', annotation }) + overlayer.add(value, range, func, opts) + } + } + const label = this.#tocProgress.getProgress(index)?.label ?? '' + return { index, label } + } + deleteAnnotation(annotation) { + return this.addAnnotation(annotation, true) } #getOverlayer(index) { const obj = this.renderer.getOverlayer() @@ -220,14 +204,13 @@ export class View { } #createOverlayer(doc, index) { const overlayer = new Overlayer() - for (const annotation of this.annotations.getByIndex(index)) - this.#drawAnnotation(doc, overlayer, annotation) doc.addEventListener('click', e => { const [value, range] = overlayer.hitTest(e) if (value) { this.emit?.({ type: 'show-annotation', value, range }) } }, false) + this.emit?.({ type: 'create-overlay', index }) return overlayer } async showAnnotation(annotation) {