From cede5ea70f47a0ddc284eb895d9e9a0dc277f271 Mon Sep 17 00:00:00 2001 From: Pierre Leroux Date: Tue, 12 Sep 2023 12:30:48 +0200 Subject: [PATCH] fixes: update annotation model to get all LocatorExtended saved and remove name properties --- src/common/redux/states/annotation.ts | 11 +- src/renderer/reader/components/ReaderMenu.tsx | 8 +- .../reader/components/picker/Annotation.tsx | 28 ++--- .../redux/actions/annotationUI/picker.ts | 3 +- src/renderer/reader/redux/sagas/annotation.ts | 104 ++++++++---------- 5 files changed, 66 insertions(+), 88 deletions(-) diff --git a/src/common/redux/states/annotation.ts b/src/common/redux/states/annotation.ts index 96a04d66d3..093efea285 100644 --- a/src/common/redux/states/annotation.ts +++ b/src/common/redux/states/annotation.ts @@ -5,18 +5,19 @@ // that can be found in the LICENSE file exposed on Github (readium) in the project repository. // ==LICENSE-END== -import { IHighlightDefinition } from "@r2-navigator-js/electron/common/highlight"; +import { LocatorExtended } from "@r2-navigator-js/electron/renderer"; +import { IColor } from "r2-navigator-js/dist/es8-es2017/src/electron/common/highlight"; import { TPQueueState } from "readium-desktop/utils/redux-reducers/pqueue.reducer"; export type TAnnotationState = TPQueueState; export interface IAnnotationState { uuid: string; - name: string; // like bookmark name comment: string; // describe annotation mark hash: string; // sha256 ( `${href}:${JSON.stringify(def)}` )) - href: string; // from IHighlightHandlerState - def: IHighlightDefinition; // from IHighlightHandlerState + // def: IHighlightDefinition; // from IHighlightHandlerState + def: LocatorExtended; + color: IColor } -export type IAnnotationStateWithoutUUID = Partial> & Pick; +export type IAnnotationStateWithoutUUID = Partial> & Pick; diff --git a/src/renderer/reader/components/ReaderMenu.tsx b/src/renderer/reader/components/ReaderMenu.tsx index 34ec04ada9..e51b9f01d0 100644 --- a/src/renderer/reader/components/ReaderMenu.tsx +++ b/src/renderer/reader/components/ReaderMenu.tsx @@ -562,11 +562,11 @@ export class ReaderMenu extends React.Component { tabIndex={0} onClick={(e) => { const closeNavPanel = e.shiftKey && e.altKey ? false : true; - this.goToLocator(e, this.createLocatorLink(annotation.href, annotation.def.selectionInfo.rangeInfo), closeNavPanel); + this.goToLocator(e, this.createLocatorLink(annotation.def.locator.href, annotation.def.selectionInfo.rangeInfo), closeNavPanel); this.props.focusAnnotationHighlight(annotation); }} onDoubleClick={(e) => { - this.goToLocator(e, this.createLocatorLink(annotation.href, annotation.def.selectionInfo.rangeInfo), false); + this.goToLocator(e, this.createLocatorLink(annotation.def.locator.href, annotation.def.selectionInfo.rangeInfo), false); this.props.focusAnnotationHighlight(annotation); }} onKeyPress= @@ -574,7 +574,7 @@ export class ReaderMenu extends React.Component { (e) => { if (e.key === "Enter" || e.key === "Space") { const closeNavPanel = e.shiftKey && e.altKey ? false : true; - this.goToLocator(e, this.createLocatorLink(annotation.href, annotation.def.selectionInfo.rangeInfo), closeNavPanel); + this.goToLocator(e, this.createLocatorLink(annotation.def.locator.href, annotation.def.selectionInfo.rangeInfo), closeNavPanel); this.props.focusAnnotationHighlight(annotation); } } @@ -583,7 +583,7 @@ export class ReaderMenu extends React.Component {
-

{annotation.name}

+

{annotation.def.selectionInfo.cleanText.slice(0, 20)}

@@ -51,22 +49,15 @@ class AnnotationPicker extends React.Component { ); }; - private nameChange = (e: TChangeEventOnInput) => { - const v = e.target.value; - const { comment, color, newFocusAnnotationUUID: uuid } = this.props.annotation; - - this.props.updateAnnotationPicker(v, comment, color, uuid); - }; - private commentChange = (e: TChangeEventOnTextArea) => { const v = e.target.value; - const { name, color, newFocusAnnotationUUID: uuid } = this.props.annotation; + const { color, newFocusAnnotationUUID: uuid } = this.props.annotation; - this.props.updateAnnotationPicker(name, v, color, uuid); + this.props.updateAnnotationPicker(v, color, uuid); }; private colorChange = (localColor: "red" | "green" | "blue" | "yellow") => { - const { name, comment, newFocusAnnotationUUID: uuid } = this.props.annotation; + const { comment, newFocusAnnotationUUID: uuid } = this.props.annotation; let color: IColor; switch (localColor) { @@ -108,7 +99,7 @@ class AnnotationPicker extends React.Component { } } - this.props.updateAnnotationPicker(name, comment, color, uuid); + this.props.updateAnnotationPicker(comment, color, uuid); }; } @@ -122,18 +113,17 @@ const mapStateToProps = (state: IReaderRootState, _props: IBaseProps) => { }; const mapDispatchToProps = (dispatch: TDispatch) => ({ - updateAnnotationPicker: (name: string, comment: string, color: IColor, uuid: string) => { - dispatch(readerLocalActionAnnotationUI.picker.build(name, comment, Object.assign({}, color), uuid)); + updateAnnotationPicker: (comment: string, color: IColor, uuid: string) => { + dispatch(readerLocalActionAnnotationUI.picker.build(comment, Object.assign({}, color), uuid)); }, deleteAnnotation: (annotation: IAnnotationState) => { dispatch(readerLocalActionPicker.manager.build(false)); dispatch(readerLocalActionAnnotations.pop.build(annotation)); }, updateAnnotation: (updatedState: IAnnotationUserInterfaceState, annotation: IAnnotationState) => { - const { color, name, comment } = updatedState; - annotation.def.color = { red: color.red, green: color.green, blue: color.blue }; + const { color, comment } = updatedState; + annotation.color = { red: color.red, green: color.green, blue: color.blue }; annotation.comment = comment; - annotation.name = name; dispatch(readerLocalActionAnnotations.update.build(annotation)); }, }); diff --git a/src/renderer/reader/redux/actions/annotationUI/picker.ts b/src/renderer/reader/redux/actions/annotationUI/picker.ts index ef0ddf10f3..d179e127bf 100644 --- a/src/renderer/reader/redux/actions/annotationUI/picker.ts +++ b/src/renderer/reader/redux/actions/annotationUI/picker.ts @@ -15,13 +15,12 @@ export const ID = "READER_ANNOTATION_UPDATE_PICKER"; interface IPayload extends Partial { } -export function build(name: string, comment: string, color: IColor, uuid: string): +export function build(comment: string, color: IColor, uuid: string): Action { return { type: ID, payload: { - name, comment, color, newFocusAnnotationUUID: uuid, diff --git a/src/renderer/reader/redux/sagas/annotation.ts b/src/renderer/reader/redux/sagas/annotation.ts index 3c2ed90b26..554585b273 100644 --- a/src/renderer/reader/redux/sagas/annotation.ts +++ b/src/renderer/reader/redux/sagas/annotation.ts @@ -5,6 +5,7 @@ // that can be found in the LICENSE file exposed on Github (readium) in the project repository. // ==LICENSE-END== +import * as debug_ from "debug"; import * as assert from "assert"; import { takeSpawnEvery } from "readium-desktop/common/redux/sagas/takeSpawnEvery"; import { SagaIterator } from "redux-saga"; @@ -17,6 +18,11 @@ import { IAnnotationStateWithoutUUID } from "readium-desktop/common/redux/states import { IHighlightDefinition } from "r2-navigator-js/dist/es8-es2017/src/electron/common/highlight"; import { readerActions } from "readium-desktop/common/redux/actions"; +// Logger +const filename_ = "readium-desktop:renderer:reader:saga:annotation"; +const debug = debug_(filename_); +debug("_"); + const hashing = (href: string, def: IHighlightDefinition) => { const defCopy = Object.assign({}, def); @@ -35,25 +41,24 @@ function createAnnotationHighlightObj(uuid: string, href: string, def: IHighligh href, def: JSON.parse(JSON.stringify(def)), }; + debug("Create", highlight); return highlight; } function* createAnnotationHighlightFromAnnotationPush(action: readerLocalActionAnnotations.push.TAction): SagaIterator { const { uuid, - href, - def, - name, + def: { locator: { href }, selectionInfo }, comment, + color, } = action.payload; - const {color} = def; - yield* putTyped(readerLocalActionHighlights.handler.push.build(createAnnotationHighlightObj(uuid, href, def))); + yield* putTyped(readerLocalActionHighlights.handler.push.build(createAnnotationHighlightObj(uuid, href, { selectionInfo, color }))); // need to do an assert annotation mode must be activated assert.equal(yield* selectTyped((store: IReaderRootState) => store.annotation.enable), true); // open picker to update name,color,... - yield* putTyped(readerLocalActionAnnotationUI.picker.build(name, comment, color, uuid)); + yield* putTyped(readerLocalActionAnnotationUI.picker.build(comment, color, uuid)); yield* putTyped(readerLocalActionPicker.manager.build(true, "annotation")); } @@ -62,15 +67,11 @@ function* deleteAnnotationHighlightFromAnnotationPop(action: readerLocalActionAn uuid, } = action.payload; - yield* putTyped(readerLocalActionHighlights.handler.pop.build({uuid})); + yield* putTyped(readerLocalActionHighlights.handler.pop.build({ uuid })); } function* selectionInfoWatcher(action: readerLocalActionSetLocator.TAction): SagaIterator { - const { - selectionInfo, - selectionIsNew, - locator: { href }, - } = action.payload; + const def = action.payload; // 1. Check if annotation mode is enabled if (!(yield* selectTyped((store: IReaderRootState) => store.annotation.enable))) { @@ -78,29 +79,20 @@ function* selectionInfoWatcher(action: readerLocalActionSetLocator.TAction): Sag } const color = yield* selectTyped((store: IReaderRootState) => store.annotation.color); + const colorDefined = color.red == 0 && color.green == 0 && color.red == 0 ? {red: 255, green: 0, blue: 0} : color; // 2. Check if it is a user selection and a new selection if ( - selectionInfo - && selectionIsNew + def.selectionInfo + && def.selectionIsNew ) { - const def: IHighlightDefinition = { - color: color.red == 0 && color.green == 0 && color.red == 0 - ? { - red: 255, - green: 0, - blue: 0, - } - : Object.assign({}, color), - selectionInfo, - }; const annotation: IAnnotationStateWithoutUUID = { - name: selectionInfo.cleanText.slice(0, 20), + // name: selectionInfo.cleanText.slice(0, 20), comment: "no comment", // TODO change this - hash: yield* callTyped(hashing, href, def), - href, + hash: yield* callTyped(hashing, def.locator.href, {selectionInfo: def.selectionInfo, color: colorDefined}), def, + color: colorDefined, }; yield* putTyped(readerLocalActionAnnotations.push.build(annotation)); } @@ -110,7 +102,7 @@ function* annotationUIEnable(_action: readerLocalActionAnnotationUI.enable.TActi // move all anotations from reader.annotations to reader.hightlight.handler const annotations = yield* selectTyped((store: IReaderRootState) => store.reader.annotation.map(([, v]) => v)); - const annotationHightlightArray = annotations.map(({uuid, href, def}) => createAnnotationHighlightObj(uuid, href, def)); + const annotationHightlightArray = annotations.map(({uuid, def: {locator: {href}, selectionInfo}, color}) => createAnnotationHighlightObj(uuid, href, { selectionInfo, color })); yield* putTyped(readerLocalActionHighlights.handler.push.build(...annotationHightlightArray)); } @@ -124,23 +116,23 @@ function* annotationUIDisable(_action: readerLocalActionAnnotationUI.enable.TAct } function* annotationClick(action: readerLocalActionHighlights.click.TAction): SagaIterator { - const {href, type, def} = action.payload; + const {href, type, def: defHighlight} = action.payload; if (type !== "annotation") { return ; } - const hash = yield* callTyped(hashing, href, def); + const hash = yield* callTyped(hashing, href, defHighlight); const annotations = yield* selectTyped((store: IReaderRootState) => store.reader.annotation.map(([, v]) => v)); const annotationFound = annotations.find((v) => v.hash === hash); if (!annotationFound) { - console.log("annotationNotFound on click", def); + debug("annotationNotFound on click", defHighlight); return ; } - assert.deepEqual(href, annotationFound.href); - assert.deepEqual(def, annotationFound.def); + assert.deepEqual(href, annotationFound.def.locator.href); + assert.deepEqual(defHighlight, {selectionInfo: annotationFound.def.selectionInfo, color: annotationFound.color}); yield* putTyped(readerLocalActionAnnotationUI.focus.build(annotationFound.uuid)); } @@ -151,27 +143,22 @@ function* annotationUIFocus(action: readerLocalActionAnnotationUI.focus.TAction) const annotations = yield* selectTyped((store: IReaderRootState) => store.reader.annotation.map(([, v]) => v)); const annotationFound = annotations.find((v) => v.uuid === uuid); if (!annotationFound) { - console.log("annotationNotFound on focus", uuid); + debug("annotationNotFound on focus", uuid); return ; } - const {name, comment, href, def} = annotationFound; - const {color} = def; + const {comment, color, def} = annotationFound; + const { locator: { href }, selectionInfo } = def; - yield* putTyped(readerLocalActionHighlights.handler.push.build({ - uuid, - type: "annotation", - href, - def: JSON.parse(JSON.stringify(def)), - })); + yield* putTyped(readerLocalActionHighlights.handler.push.build(createAnnotationHighlightObj(uuid, href, {selectionInfo, color}))); // update picker info and doesn't force enable annotation mode, view or edit mode allowed - yield* putTyped(readerLocalActionAnnotationUI.picker.build(name, comment, color, uuid)); + yield* putTyped(readerLocalActionAnnotationUI.picker.build(comment, color, uuid)); yield* putTyped(readerLocalActionPicker.manager.build(true, "annotation")); } function* updateAnnotationAndRedrawHightlightIfColorChanged(action: readerLocalActionAnnotations.update.TAction): SagaIterator { - const {def: {color}, uuid} = action.payload; + const {color, uuid} = action.payload; const winId = yield* selectTyped((state: IReaderRootState) => state.win.identifier); assert.ok(winId); @@ -181,22 +168,23 @@ function* updateAnnotationAndRedrawHightlightIfColorChanged(action: readerLocalA const highlights = yield* selectTyped((store: IReaderRootState) => store.reader.highlight.handler.map(([, v]) => v)); const highlightsAnnotation = highlights.find((v) => v.uuid === uuid); + debug("find hightlight:", highlightsAnnotation); if (!highlightsAnnotation) { - console.log("HightlightHandlerAnnotationNotFound on redraw color if updated", uuid); + debug("HightlightHandlerAnnotationNotFound on redraw color if updated", uuid); return ; } if (!color) { - console.error("no color provided; no redraw"); + debug("no color provided; no redraw"); return ; } if (highlightsAnnotation.def.color.red === color.red && highlightsAnnotation.def.color.blue === color.blue && highlightsAnnotation.def.color.green === color.green) { - console.log("same color no redraw needed!"); + debug("same color no redraw needed!"); return ; } - console.log("redraw with color", color); + debug("redraw with color", color); yield* putTyped(readerLocalActionHighlights.handler.pop.build(highlightsAnnotation)); const newHighlightsAnnotation = JSON.parse(JSON.stringify(highlightsAnnotation)) as IHighlightHandlerState; @@ -209,46 +197,46 @@ export const saga = () => takeSpawnEvery( readerLocalActionHighlights.click.ID, annotationClick, - (e) => console.log("readerLocalActionAnnotationUI.cancel", e), + (e) => console.error("readerLocalActionAnnotationUI.click", e), ), takeSpawnEvery( readerLocalActionAnnotationUI.cancel.ID, annotationUIDisable, - (e) => console.log("readerLocalActionAnnotationUI.cancel", e), + (e) => console.error("readerLocalActionAnnotationUI.cancel", e), ), takeSpawnEvery( readerLocalActionAnnotationUI.enable.ID, annotationUIEnable, - (e) => console.log("readerLocalActionAnnotationUI.enable", e), + (e) => console.error("readerLocalActionAnnotationUI.enable", e), ), takeSpawnEvery( readerLocalActionAnnotations.update.ID, updateAnnotationAndRedrawHightlightIfColorChanged, - (e) => console.log("readerLocalActionAnnotations.update", e), + (e) => console.error("readerLocalActionAnnotations.update", e), ), takeSpawnEvery( readerLocalActionAnnotationUI.focus.ID, annotationUIFocus, - (e) => console.log("readerLocalActionAnnotationUI.focus", e), + (e) => console.error("readerLocalActionAnnotationUI.focus", e), ), takeSpawnEvery( readerLocalActionAnnotations.push.ID, createAnnotationHighlightFromAnnotationPush, - (e) => console.log("readerLocalActionAnnotations.push", e), + (e) => console.error("readerLocalActionAnnotations.push", e), ), takeSpawnEvery( readerLocalActionAnnotations.pop.ID, deleteAnnotationHighlightFromAnnotationPop, - (e) => console.log("readerLocalActionAnnotations.push", e), + (e) => console.error("readerLocalActionAnnotations.pop", e), ), takeSpawnEvery( readerLocalActionSetLocator.ID, selectionInfoWatcher, - (e) => console.log("readerLocalActionSetLocator", e), + (e) => console.error("readerLocalActionSetLocator", e), ), takeSpawnEvery( readerLocalActionSetLocator.ID, - () => console.log("hello"), - (e) => console.log("readerLocalActionSetLocator", e), + () => debug("hello"), + (e) => console.error("readerLocalActionSetLocator", e), ), ]);