Skip to content

Commit

Permalink
picker
Browse files Browse the repository at this point in the history
  • Loading branch information
panaC committed Aug 17, 2023
1 parent d775eb2 commit c1203d3
Show file tree
Hide file tree
Showing 4 changed files with 138 additions and 16 deletions.
5 changes: 2 additions & 3 deletions src/common/redux/states/annotation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
// that can be found in the LICENSE file exposed on Github (readium) in the project repository.
// ==LICENSE-END==

import { IColor, IHighlightDefinition } from "@r2-navigator-js/electron/common/highlight";
import { IHighlightDefinition } from "@r2-navigator-js/electron/common/highlight";
import { TPQueueState } from "readium-desktop/utils/redux-reducers/pqueue.reducer";

export type TAnnotationState = TPQueueState<number, IAnnotationState>;
Expand All @@ -17,7 +17,6 @@ export interface IAnnotationState {
hash: string; // sha256 ( `${href}:${JSON.stringify(def)}` ))
href: string; // from IHighlightHandlerState
def: IHighlightDefinition; // from IHighlightHandlerState
color: IColor
}

export type IAnnotationStateWithoutUUID = Partial<Pick<IAnnotationState, "uuid">> & Pick<IAnnotationState, "name" | "comment" | "def" | "hash" | "href" | "color">;
export type IAnnotationStateWithoutUUID = Partial<Pick<IAnnotationState, "uuid">> & Pick<IAnnotationState, "name" | "comment" | "def" | "hash" | "href">;
98 changes: 89 additions & 9 deletions src/renderer/reader/components/picker/Annotation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,12 @@
import * as React from "react";
import { connect } from "react-redux";
import { IReaderRootState } from "readium-desktop/common/redux/states/renderer/readerRootState";
import { TChangeEventOnInput, TChangeEventOnTextArea } from "readium-desktop/typings/react";
import { TDispatch } from "readium-desktop/typings/redux";
import { readerLocalActionAnnotationUI, readerLocalActionAnnotations, readerLocalActionPicker } from "../../redux/actions";
import { IColor } from "@r2-navigator-js/electron/common/highlight";
import { IAnnotationState } from "readium-desktop/common/redux/states/annotation";
import { IAnnotationUserInterfaceState } from "../../redux/state/annotation";

// eslint-disable-next-line @typescript-eslint/no-empty-interface
interface IBaseProps {
Expand All @@ -31,31 +36,106 @@ class AnnotationPicker extends React.Component<IProps, IState> {

return (
<form id="myForm" style={{ display: 'block' }}>

Check failure on line 38 in src/renderer/reader/components/picker/Annotation.tsx

View workflow job for this annotation

GitHub Actions / build (windows-latest)

Strings must use doublequote
<input type="text" id="name" name="name" value={this.props.annotation.name} maxLength={20} style={{ width: '100px' }} readOnly={true}/>
<input type="text" id="name" name="name" value={this.props.annotation.name} maxLength={20} style={{ width: '100px' }} onChange={this.nameChange}/>

Check failure on line 39 in src/renderer/reader/components/picker/Annotation.tsx

View workflow job for this annotation

GitHub Actions / build (windows-latest)

Strings must use doublequote

<button className="color-button" style={{ width: '20px', height: '20px', backgroundColor: 'red', border: 'none', margin: '5px', cursor: 'pointer' }}></button>
<button className="color-button" style={{ width: '20px', height: '20px', backgroundColor: 'green', border: 'none', margin: '5px', cursor: 'pointer' }}></button>
<button className="color-button" style={{ width: '20px', height: '20px', backgroundColor: 'blue', border: 'none', margin: '5px', cursor: 'pointer' }}></button>
<button className="color-button" style={{ width: '20px', height: '20px', backgroundColor: 'yellow', border: 'none', margin: '5px', cursor: 'pointer' }}></button>
<button className="color-button" style={{ width: '20px', height: '20px', backgroundColor: 'red', border: 'none', margin: '5px', cursor: 'pointer' }} onClick={(e) => (e.preventDefault(),this.colorChange("red"))}></button>

Check failure on line 41 in src/renderer/reader/components/picker/Annotation.tsx

View workflow job for this annotation

GitHub Actions / build (windows-latest)

Strings must use doublequote

Check failure on line 41 in src/renderer/reader/components/picker/Annotation.tsx

View workflow job for this annotation

GitHub Actions / build (windows-latest)

Strings must use doublequote

Check failure on line 41 in src/renderer/reader/components/picker/Annotation.tsx

View workflow job for this annotation

GitHub Actions / build (windows-latest)

Strings must use doublequote

Check failure on line 41 in src/renderer/reader/components/picker/Annotation.tsx

View workflow job for this annotation

GitHub Actions / build (windows-latest)

Strings must use doublequote

Check failure on line 41 in src/renderer/reader/components/picker/Annotation.tsx

View workflow job for this annotation

GitHub Actions / build (windows-latest)

Strings must use doublequote

Check failure on line 41 in src/renderer/reader/components/picker/Annotation.tsx

View workflow job for this annotation

GitHub Actions / build (windows-latest)

Strings must use doublequote
<button className="color-button" style={{ width: '20px', height: '20px', backgroundColor: 'green', border: 'none', margin: '5px', cursor: 'pointer' }} onClick={(e) => (e.preventDefault(),this.colorChange("green"))}></button>

Check failure on line 42 in src/renderer/reader/components/picker/Annotation.tsx

View workflow job for this annotation

GitHub Actions / build (windows-latest)

Strings must use doublequote
<button className="color-button" style={{ width: '20px', height: '20px', backgroundColor: 'blue', border: 'none', margin: '5px', cursor: 'pointer' }} onClick={(e) => (e.preventDefault(),this.colorChange("blue"))}></button>
<button className="color-button" style={{ width: '20px', height: '20px', backgroundColor: 'yellow', border: 'none', margin: '5px', cursor: 'pointer' }} onClick={(e) => (e.preventDefault(),this.colorChange("yellow"))}></button>

<textarea id="comment" name="comment" value={this.props.annotation.comment} style={{ width: '200px' }} readOnly={true}></textarea>
<textarea id="comment" name="comment" value={this.props.annotation.comment} style={{ width: '200px' }} onChange={this.commentChange}></textarea>

<button type="button" id="deleteButton" style={{ backgroundColor: '#f44336', color: 'white', border: 'none', padding: '1px 2px', cursor: 'pointer' }}>Delete</button>
<button type="button" id="submitButton" style={{ backgroundColor: '#f44336', color: 'white', border: 'none', padding: '1px 2px', cursor: 'pointer' }}>Submit</button>
<button type="button" id="deleteButton" style={{ backgroundColor: '#f44336', color: 'white', border: 'none', padding: '1px 2px', cursor: 'pointer' }} onClick={(_e) => (this.props.deleteAnnotation(this.props.annotationItem))}>Delete</button>
<button type="button" id="submitButton" style={{ backgroundColor: '#f44336', color: 'white', border: 'none', padding: '1px 2px', cursor: 'pointer' }} onClick={(_e) => (this.props.updateAnnotation(this.props.annotation, this.props.annotationItem))}>Submit</button>
</form>
);
}

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;

this.props.updateAnnotationPicker(name, v, color, uuid);
}

private colorChange = (localColor: "red"|"green"|"blue"|"yellow") => {
const {name, comment, newFocusAnnotationUUID: uuid} = this.props.annotation;

let color: IColor;
switch (localColor) {

case "red": {
color = {
red: 200,
green: 0,
blue: 0,
}
break;
}
case "green": {
color = {
red: 0,
green: 200,
blue: 0,
}
break;
}
case "blue": {
color = {
red: 0,
green: 0,
blue: 200,
}
break;
}
case "yellow": {
color = {
red: 255,
green: 210,
blue: 1,
}
break;
}
default: {
color = this.props.annotation.color;
}
}

this.props.updateAnnotationPicker(name, comment, color, uuid);
}

}

const mapStateToProps = (state: IReaderRootState, _props: IBaseProps) => {
return {
picker: state.picker,
annotation: state.annotation,
annotationItem: state.reader.annotation.map(([,v]) => v).find((v) => v.uuid === state.annotation.newFocusAnnotationUUID),
};
};

const mapDispatchToProps = (_dispatch: TDispatch) => ({
const mapDispatchToProps = (dispatch: TDispatch) => ({
updateAnnotationPicker: (name: string, comment: string, color: IColor, uuid: string) => {
dispatch(readerLocalActionAnnotationUI.picker.build(name, comment, 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 = color || annotation.def.color;
annotation.comment = comment;
annotation.name = name;
dispatch(readerLocalActionAnnotations.update.build(annotation));
}
});

export default connect(mapStateToProps, mapDispatchToProps)(AnnotationPicker);
49 changes: 45 additions & 4 deletions src/renderer/reader/redux/sagas/annotation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { all, put as putTyped, select as selectTyped, call as callTyped } from "
import { IReaderRootState } from "readium-desktop/common/redux/states/renderer/readerRootState";
import { IAnnotationStateWithoutUUID } from "readium-desktop/common/redux/states/annotation";
import { IHighlightDefinition } from "r2-navigator-js/dist/es8-es2017/src/electron/common/highlight";
import { readerActions } from "readium-desktop/common/redux/actions";

function createAnnotationHighlightObj(uuid: string, href: string, def: IHighlightDefinition): IHighlightHandlerState {
const highlight: IHighlightHandlerState = {
Expand All @@ -33,8 +34,8 @@ function* createAnnotationHighlightFromAnnotationPush(action: readerLocalActionA
def,
name,
comment,
color,
} = action.payload;
const {color} = def;
yield* putTyped(readerLocalActionHighlights.handler.push.build(createAnnotationHighlightObj(uuid, href, def)));

// need to do an assert annotation mode must be activated
Expand Down Expand Up @@ -90,7 +91,6 @@ function* selectionInfoWatcher(action: readerLocalActionSetLocator.TAction): Sag
.then((a) => Buffer.from(a).toString("hex"))),
href,
def,
color,
}
yield* putTyped(readerLocalActionAnnotations.push.build(annotation));
}
Expand Down Expand Up @@ -147,7 +147,8 @@ function* annotationUIFocus(action: readerLocalActionAnnotationUI.focus.TAction)
return ;
}

const {name, comment, color, href, def} = annotationFound;
const {name, comment, href, def} = annotationFound;
const {color} = def;

yield* putTyped(readerLocalActionHighlights.handler.push.build({
uuid,
Expand All @@ -161,6 +162,41 @@ function* annotationUIFocus(action: readerLocalActionAnnotationUI.focus.TAction)
yield* putTyped(readerLocalActionPicker.manager.build(true, "annotation"));
}

function* updateAnnotationAndRedrawHightlightIfColorChanged(action: readerLocalActionAnnotations.update.TAction): SagaIterator {
const {def: {color}, uuid} = action.payload;

const highlights = yield* selectTyped((store: IReaderRootState) => store.reader.highlight.handler.map(([, v]) => v));
const highlightsAnnotation = highlights.find((v) => v.uuid === uuid);
if (!highlightsAnnotation) {
console.log("HightlightHandlerAnnotationNotFound on redraw color if updated", uuid);
return ;
}

if (!color) {
console.error("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!");
return ;
}

console.log("redraw with color", color);
yield* putTyped(readerLocalActionHighlights.handler.pop.build(highlightsAnnotation));

const newHighlightsAnnotation = JSON.parse(JSON.stringify(highlightsAnnotation)) as IHighlightHandlerState;
newHighlightsAnnotation.def.color = {red: color.red, blue: color.blue, green: color.green};
yield* putTyped(readerLocalActionHighlights.handler.push.build(newHighlightsAnnotation));

const winId = yield* selectTyped((state: IReaderRootState) => state.win.identifier);
assert.ok(winId);

const readerAnnotations = yield* selectTyped((state: IReaderRootState) => state.reader.annotation);
const state = {annotation: readerAnnotations};
yield* putTyped(readerActions.setReduxState.build(winId, state));
}

export const saga = () =>
all([
takeSpawnEvery(
Expand All @@ -178,10 +214,15 @@ export const saga = () =>
annotationUIEnable,
(e) => console.log("readerLocalActionAnnotationUI.enable", e),
),
takeSpawnEvery(
readerLocalActionAnnotations.update.ID,
updateAnnotationAndRedrawHightlightIfColorChanged,
(e) => console.log("readerLocalActionAnnotations.update", e),
),
takeSpawnEvery(
readerLocalActionAnnotationUI.focus.ID,
annotationUIFocus,
(e) => console.log("readerLocalActionAnnotationUI.enable", e),
(e) => console.log("readerLocalActionAnnotationUI.focus", e),
),
takeSpawnEvery(
readerLocalActionAnnotations.push.ID,
Expand Down
2 changes: 2 additions & 0 deletions src/typings/react.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,6 @@ export type TFormEvent = React.FormEvent<HTMLFormElement>;

export type TChangeEventOnInput = React.ChangeEvent<HTMLInputElement>;

export type TChangeEventOnTextArea = React.ChangeEvent<HTMLTextAreaElement>;

export type TChangeEventOnSelect = React.ChangeEvent<HTMLSelectElement>;

0 comments on commit c1203d3

Please sign in to comment.