import { Component } from 'preact'; import type { IAnnotationWithSource } from '../storage/Annotation'; import { RpcClient } from 'webextension-rpc'; import { describeTextQuote } from '@apache-annotator/dom'; import type { WebAnnotation } from 'web-annotation-utils'; import type { backgroundRpcServer } from '../background'; const backgroundRpc = new RpcClient(); const createAnnotation = backgroundRpc.func('createAnnotation'); export async function annotateSelection() { // TODO Use something else than document, so the page’s own scripts cannot observe the reader’s annotation activity. document.dispatchEvent(new CustomEvent('createAnnotation')); } function deselect() { const selection = window.getSelection(); if (selection) selection.removeAllRanges(); } interface AnnotationCreationHelperProps { onAnnotationCreated: (annotation: IAnnotationWithSource) => void; } interface AnnotationCreationHelperState {} export class AnnotationCreationHelper extends Component< AnnotationCreationHelperProps, AnnotationCreationHelperState > { state: AnnotationCreationHelperState = {}; constructor() { super(); this.onCreateAnnotation = this.onCreateAnnotation.bind(this); } override componentDidMount(): void { document.addEventListener('createAnnotation', this.onCreateAnnotation); } override componentWillUnmount(): void { document.removeEventListener('createAnnotation', this.onCreateAnnotation); } async onCreateAnnotation() { const target: WebAnnotation['target'] = { source: document.URL.split('#')[0], }; const selection = window.getSelection(); if (selection && !selection.isCollapsed) { const range = selection.getRangeAt(0); const selector = await describeTextQuote(range); target.selector = selector; deselect(); } let createdAnnotation; const annotationStub = { target } try { createdAnnotation = await createAnnotation(annotationStub); } catch (error: any) { const newError = new Error(`Error creating the annotation: ${error.message}`) alert(newError.message); throw newError; } this.props.onAnnotationCreated(createdAnnotation); } render() { return undefined; } }