box-annotations 5.2.1-beta.8 → 5.3.1-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/annotations.css +1 -1
- package/dist/annotations.js +1 -1
- package/dist/annotations.js.LICENSE.txt +1 -10
- package/i18n/bn-IN.js +6 -0
- package/i18n/bn-IN.properties +12 -0
- package/i18n/da-DK.js +6 -0
- package/i18n/da-DK.properties +12 -0
- package/i18n/de-DE.js +6 -0
- package/i18n/de-DE.properties +12 -0
- package/i18n/en-AU.js +6 -0
- package/i18n/en-AU.properties +12 -0
- package/i18n/en-CA.js +6 -0
- package/i18n/en-CA.properties +12 -0
- package/i18n/en-GB.js +6 -0
- package/i18n/en-GB.properties +12 -0
- package/i18n/es-419.js +6 -0
- package/i18n/es-419.properties +12 -0
- package/i18n/es-ES.js +6 -0
- package/i18n/es-ES.properties +12 -0
- package/i18n/fi-FI.js +6 -0
- package/i18n/fi-FI.properties +12 -0
- package/i18n/fr-CA.js +6 -0
- package/i18n/fr-CA.properties +12 -0
- package/i18n/fr-FR.js +6 -0
- package/i18n/fr-FR.properties +12 -0
- package/i18n/hi-IN.js +6 -0
- package/i18n/hi-IN.properties +12 -0
- package/i18n/it-IT.js +6 -0
- package/i18n/it-IT.properties +12 -0
- package/i18n/ja-JP.js +7 -1
- package/i18n/ja-JP.properties +13 -1
- package/i18n/ko-KR.js +6 -0
- package/i18n/ko-KR.properties +12 -0
- package/i18n/nb-NO.js +6 -0
- package/i18n/nb-NO.properties +12 -0
- package/i18n/nl-NL.js +6 -0
- package/i18n/nl-NL.properties +12 -0
- package/i18n/pl-PL.js +6 -0
- package/i18n/pl-PL.properties +12 -0
- package/i18n/pt-BR.js +6 -0
- package/i18n/pt-BR.properties +12 -0
- package/i18n/ru-RU.js +6 -0
- package/i18n/ru-RU.properties +12 -0
- package/i18n/sv-SE.js +6 -0
- package/i18n/sv-SE.properties +12 -0
- package/i18n/tr-TR.js +6 -0
- package/i18n/tr-TR.properties +12 -0
- package/i18n/zh-CN.js +6 -0
- package/i18n/zh-CN.properties +12 -0
- package/i18n/zh-TW.js +6 -0
- package/i18n/zh-TW.properties +12 -0
- package/index.js +1 -1
- package/package.json +54 -42
- package/src/@types/api.ts +3 -2
- package/src/@types/events.ts +27 -10
- package/src/@types/global.ts +0 -9
- package/src/@types/model.ts +9 -0
- package/src/BoxAnnotations.ts +6 -2
- package/src/adapters/threadedAnnotationsAdapters.ts +49 -28
- package/src/api/APIFactory.ts +6 -1
- package/src/api/types.ts +23 -1
- package/src/boundingBoxHighlight/BoundingBoxHighlightContainer.tsx +4 -1
- package/src/common/AnnotationCallbacksContext.ts +7 -0
- package/src/common/BaseAnnotator.scss +12 -0
- package/src/common/BaseAnnotator.ts +32 -2
- package/src/common/BaseManager.ts +2 -0
- package/src/common/DeselectListener.tsx +1 -1
- package/src/common/withProviders.tsx +6 -2
- package/src/components/BoundingBoxHighlight/BoundingBoxHighlightNav.scss +3 -3
- package/src/components/BoundingBoxHighlight/BoundingBoxHighlightRect.scss +11 -6
- package/src/components/Popups/PopupBase.scss +2 -2
- package/src/components/Popups/PopupDrawingToolbar.scss +4 -4
- package/src/components/Popups/PopupDrawingToolbar.tsx +0 -7
- package/src/components/Popups/PopupList.scss +1 -1
- package/src/components/Popups/PopupV2.scss +2 -2
- package/src/components/Popups/PopupV2.tsx +128 -72
- package/src/components/ReplyForm/ReplyForm.tsx +1 -8
- package/src/constants.ts +2 -3
- package/src/document/DocumentAnnotator.ts +29 -5
- package/src/document/docUtil.ts +8 -1
- package/src/drawing/DrawingAnnotations.tsx +30 -21
- package/src/drawing/DrawingAnnotationsContainer.tsx +3 -0
- package/src/drawing/DrawingCreator.tsx +9 -16
- package/src/drawing/DrawingCursor.ts +2 -1
- package/src/drawing/DrawingManager.tsx +21 -2
- package/src/highlight/HighlightAnnotations.tsx +28 -14
- package/src/highlight/HighlightContainer.tsx +3 -0
- package/src/highlight/HighlightCreator.scss +9 -2
- package/src/highlight/HighlightCreatorManager.ts +8 -5
- package/src/highlight/HighlightListener.ts +4 -2
- package/src/highlight/HighlightManager.tsx +13 -2
- package/src/image/ImageAnnotator.ts +2 -1
- package/src/media/MediaAnnotator.ts +39 -16
- package/src/popup/PopupLayer.tsx +38 -11
- package/src/popup/PopupManager.tsx +4 -2
- package/src/region/RegionAnnotations.tsx +2 -3
- package/src/region/RegionCreation.tsx +15 -9
- package/src/region/RegionCreationContainer.tsx +2 -2
- package/src/region/RegionCreationManager.tsx +8 -1
- package/src/region/RegionCreator.scss +9 -3
- package/src/region/RegionCreator.tsx +9 -17
- package/src/region/RegionManager.tsx +8 -1
- package/src/region/RegionRect.scss +17 -9
- package/src/store/annotations/actions.ts +104 -33
- package/src/store/annotations/reducer.ts +49 -1
- package/src/store/creator/selectors.ts +6 -6
- package/src/store/eventing/create.ts +6 -4
- package/src/store/eventing/delete.ts +26 -0
- package/src/store/eventing/middleware.ts +53 -15
- package/src/store/eventing/replyCreate.ts +30 -0
- package/src/store/eventing/replyDelete.ts +31 -0
- package/src/store/eventing/replyUpdate.ts +35 -0
- package/src/store/eventing/types.ts +4 -4
- package/src/store/eventing/update.ts +28 -0
- package/src/store/highlight/actions.ts +50 -19
- package/src/store/highlight/types.ts +1 -0
- package/src/store/options/selectors.ts +2 -2
- package/src/store/options/types.ts +2 -2
- package/src/test-utils/videoAnnotations.tsx +11 -11
- package/src/utils/rotate.ts +43 -0
- package/src/utils/useVideoTiming.ts +9 -13
|
@@ -1,9 +1,20 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import * as ReactDOM from 'react-dom/client';
|
|
3
|
-
import BaseManager, { Props } from '../common/BaseManager';
|
|
3
|
+
import BaseManager, { Options as BaseOptions, Props } from '../common/BaseManager';
|
|
4
4
|
import DrawingAnnotationsContainer from './DrawingAnnotationsContainer';
|
|
5
5
|
|
|
6
|
+
export type Options = BaseOptions & {
|
|
7
|
+
popupPortalEl?: HTMLElement | null;
|
|
8
|
+
};
|
|
9
|
+
|
|
6
10
|
export default class DrawingListManager extends BaseManager {
|
|
11
|
+
popupPortalEl?: HTMLElement | null;
|
|
12
|
+
|
|
13
|
+
constructor({ popupPortalEl, ...options }: Options) {
|
|
14
|
+
super(options);
|
|
15
|
+
this.popupPortalEl = popupPortalEl;
|
|
16
|
+
}
|
|
17
|
+
|
|
7
18
|
decorate(): void {
|
|
8
19
|
this.reactEl.classList.add('ba-Layer--drawing');
|
|
9
20
|
this.reactEl.dataset.testid = 'ba-Layer--drawing';
|
|
@@ -14,6 +25,14 @@ export default class DrawingListManager extends BaseManager {
|
|
|
14
25
|
this.root = ReactDOM.createRoot(this.reactEl);
|
|
15
26
|
}
|
|
16
27
|
|
|
17
|
-
this.root.render(
|
|
28
|
+
this.root.render(
|
|
29
|
+
<DrawingAnnotationsContainer
|
|
30
|
+
referenceEl={this.referenceEl}
|
|
31
|
+
targetType={this.targetType}
|
|
32
|
+
location={this.location}
|
|
33
|
+
popupPortalEl={this.popupPortalEl}
|
|
34
|
+
{...props}
|
|
35
|
+
/>,
|
|
36
|
+
);
|
|
18
37
|
}
|
|
19
38
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
+
import ReactDOM from 'react-dom';
|
|
2
3
|
import HighlightCanvas from './HighlightCanvas';
|
|
3
4
|
import HighlightList from './HighlightList';
|
|
4
5
|
import HighlightSvg from './HighlightSvg';
|
|
@@ -20,6 +21,8 @@ type Props = {
|
|
|
20
21
|
isPromoting: boolean;
|
|
21
22
|
isSelecting: boolean;
|
|
22
23
|
location: number;
|
|
24
|
+
popupPortalEl?: HTMLElement | null;
|
|
25
|
+
rotation: number;
|
|
23
26
|
selection: SelectionItem | null;
|
|
24
27
|
setActiveAnnotationId: (annotationId: string | null) => void;
|
|
25
28
|
setIsPromoting: (isPromoting: boolean) => void;
|
|
@@ -38,6 +41,8 @@ const HighlightAnnotations = (props: Props): JSX.Element => {
|
|
|
38
41
|
isPending = false,
|
|
39
42
|
isPromoting = false,
|
|
40
43
|
isSelecting = false,
|
|
44
|
+
popupPortalEl,
|
|
45
|
+
rotation,
|
|
41
46
|
selection,
|
|
42
47
|
setActiveAnnotationId,
|
|
43
48
|
setIsPromoting,
|
|
@@ -121,22 +126,31 @@ const HighlightAnnotations = (props: Props): JSX.Element => {
|
|
|
121
126
|
)}
|
|
122
127
|
|
|
123
128
|
{/* Layer 3a: Annotations promoter to promote selection to staged */}
|
|
124
|
-
{!isCreating &&
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
129
|
+
{!isCreating &&
|
|
130
|
+
selection &&
|
|
131
|
+
!selection.hasError &&
|
|
132
|
+
(() => {
|
|
133
|
+
const popupShape = selection.popupRect || getBoundingRect(selection.rects);
|
|
134
|
+
const popup = (
|
|
135
|
+
<div className="ba-HighlightAnnotations-popup">
|
|
136
|
+
<PopupHighlight onCancel={handleCancel} onSubmit={handlePromote} shape={popupShape} />
|
|
137
|
+
</div>
|
|
138
|
+
);
|
|
139
|
+
return rotation && popupPortalEl ? ReactDOM.createPortal(popup, popupPortalEl) : popup;
|
|
140
|
+
})()}
|
|
133
141
|
|
|
134
142
|
{/* Layer 3b: Highlight error popup */}
|
|
135
|
-
{selection &&
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
143
|
+
{selection &&
|
|
144
|
+
selection.hasError &&
|
|
145
|
+
(() => {
|
|
146
|
+
const popupShape = selection.popupRect || getBoundingRect(selection.rects);
|
|
147
|
+
const popup = (
|
|
148
|
+
<div className="ba-HighlightAnnotations-popup">
|
|
149
|
+
<PopupHighlightError onCancel={handleCancel} shape={popupShape} />
|
|
150
|
+
</div>
|
|
151
|
+
);
|
|
152
|
+
return rotation && popupPortalEl ? ReactDOM.createPortal(popup, popupPortalEl) : popup;
|
|
153
|
+
})()}
|
|
140
154
|
</>
|
|
141
155
|
);
|
|
142
156
|
};
|
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
getCreatorStatus,
|
|
14
14
|
getIsPromoting,
|
|
15
15
|
getIsSelecting,
|
|
16
|
+
getRotation,
|
|
16
17
|
getSelectionForLocation,
|
|
17
18
|
isCreatorStagedHighlight,
|
|
18
19
|
Mode,
|
|
@@ -33,6 +34,7 @@ export type Props = {
|
|
|
33
34
|
isPending: boolean;
|
|
34
35
|
isPromoting: boolean;
|
|
35
36
|
isSelecting: boolean;
|
|
37
|
+
rotation: number;
|
|
36
38
|
selection: SelectionItem | null;
|
|
37
39
|
staged: CreatorItemHighlight | null;
|
|
38
40
|
};
|
|
@@ -47,6 +49,7 @@ export const mapStateToProps = (state: AppState, { location }: { location: numbe
|
|
|
47
49
|
isPending: getCreatorStatus(state) === CreatorStatus.pending,
|
|
48
50
|
isPromoting: getIsPromoting(state),
|
|
49
51
|
isSelecting: getIsSelecting(state),
|
|
52
|
+
rotation: getRotation(state),
|
|
50
53
|
selection: getSelectionForLocation(state, location),
|
|
51
54
|
staged: isCreatorStagedHighlight(staged) ? staged : null,
|
|
52
55
|
};
|
|
@@ -7,6 +7,13 @@ $text_cursor_32_3x: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAYAA
|
|
|
7
7
|
$offset_x: 10;
|
|
8
8
|
$offset_y: 16;
|
|
9
9
|
|
|
10
|
-
cursor:
|
|
11
|
-
|
|
10
|
+
cursor:
|
|
11
|
+
url($text_cursor_32) $offset_x $offset_y,
|
|
12
|
+
text; /* Legacy */
|
|
13
|
+
|
|
14
|
+
/* stylelint-disable unit-no-unknown */
|
|
15
|
+
cursor:
|
|
16
|
+
image-set(url($text_cursor_32) 1x, url($text_cursor_32_2x) 2x, url($text_cursor_32_3x) 3x) $offset_x $offset_y,
|
|
17
|
+
text; /* Webkit */
|
|
18
|
+
/* stylelint-enable unit-no-unknown */
|
|
12
19
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
AppStore,
|
|
3
3
|
getIsSelecting,
|
|
4
|
+
getRotation,
|
|
4
5
|
SelectionArg as Selection,
|
|
5
6
|
setIsSelectingAction,
|
|
6
7
|
setSelectionAction,
|
|
@@ -41,18 +42,18 @@ export default class HighlightCreatorManager implements Manager {
|
|
|
41
42
|
this.store.dispatch(setSelectionAction(null));
|
|
42
43
|
|
|
43
44
|
this.referenceEl.addEventListener('mousedown', this.handleMouseDown);
|
|
44
|
-
|
|
45
|
+
document.addEventListener('mouseup', this.handleMouseUp);
|
|
45
46
|
}
|
|
46
47
|
|
|
47
|
-
style(
|
|
48
|
-
return
|
|
48
|
+
style(): CSSStyleDeclaration {
|
|
49
|
+
return this.referenceEl.style;
|
|
49
50
|
}
|
|
50
51
|
|
|
51
52
|
destroy(): void {
|
|
52
53
|
clearTimeout(this.selectionChangeTimer);
|
|
53
54
|
|
|
54
55
|
this.referenceEl.removeEventListener('mousedown', this.handleMouseDown);
|
|
55
|
-
|
|
56
|
+
document.removeEventListener('mouseup', this.handleMouseUp);
|
|
56
57
|
}
|
|
57
58
|
|
|
58
59
|
handleMouseDown = ({ buttons }: MouseEvent): void => {
|
|
@@ -72,7 +73,9 @@ export default class HighlightCreatorManager implements Manager {
|
|
|
72
73
|
}
|
|
73
74
|
|
|
74
75
|
this.selectionChangeTimer = window.setTimeout(() => {
|
|
75
|
-
this.
|
|
76
|
+
const selection = this.getSelection();
|
|
77
|
+
const rotation = getRotation(this.store.getState());
|
|
78
|
+
this.store.dispatch(setSelectionAction(selection ? { ...selection, rotation } : null));
|
|
76
79
|
this.store.dispatch(setIsSelectingAction(false));
|
|
77
80
|
}, this.selectionChangeDelay);
|
|
78
81
|
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import debounce from 'lodash/debounce';
|
|
2
|
-
import { AppStore, getIsSelecting, SelectionArg as Selection, setSelectionAction } from '../store';
|
|
2
|
+
import { AppStore, getIsSelecting, getRotation, SelectionArg as Selection, setSelectionAction } from '../store';
|
|
3
3
|
|
|
4
4
|
export type Options = {
|
|
5
5
|
getSelection: () => Selection | null;
|
|
@@ -30,7 +30,9 @@ export default class HighlightListener {
|
|
|
30
30
|
return;
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
this.
|
|
33
|
+
const selection = this.getSelection();
|
|
34
|
+
const rotation = getRotation(this.store.getState());
|
|
35
|
+
this.store.dispatch(setSelectionAction(selection ? { ...selection, rotation } : null));
|
|
34
36
|
};
|
|
35
37
|
|
|
36
38
|
debounceHandleSelectionChange = debounce(this.handleSelectionChange, SELECTION_CHANGE_DEBOUNCE);
|
|
@@ -1,9 +1,20 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import * as ReactDOM from 'react-dom/client';
|
|
3
|
-
import BaseManager, { Props } from '../common/BaseManager';
|
|
3
|
+
import BaseManager, { Options as BaseOptions, Props } from '../common/BaseManager';
|
|
4
4
|
import HighlightContainer from './HighlightContainer';
|
|
5
5
|
|
|
6
|
+
export type Options = BaseOptions & {
|
|
7
|
+
popupPortalEl?: HTMLElement | null;
|
|
8
|
+
};
|
|
9
|
+
|
|
6
10
|
export default class HighlightManager extends BaseManager {
|
|
11
|
+
popupPortalEl?: HTMLElement | null;
|
|
12
|
+
|
|
13
|
+
constructor({ popupPortalEl, ...options }: Options) {
|
|
14
|
+
super(options);
|
|
15
|
+
this.popupPortalEl = popupPortalEl;
|
|
16
|
+
}
|
|
17
|
+
|
|
7
18
|
decorate(): void {
|
|
8
19
|
this.reactEl.classList.add('ba-Layer--highlight');
|
|
9
20
|
this.reactEl.dataset.testid = 'ba-Layer--highlight';
|
|
@@ -14,6 +25,6 @@ export default class HighlightManager extends BaseManager {
|
|
|
14
25
|
this.root = ReactDOM.createRoot(this.reactEl);
|
|
15
26
|
}
|
|
16
27
|
|
|
17
|
-
this.root.render(<HighlightContainer location={this.location} {...props} />);
|
|
28
|
+
this.root.render(<HighlightContainer location={this.location} popupPortalEl={this.popupPortalEl} {...props} />);
|
|
18
29
|
}
|
|
19
30
|
}
|
|
@@ -74,7 +74,7 @@ export default class ImageAnnotator extends BaseAnnotator {
|
|
|
74
74
|
}
|
|
75
75
|
|
|
76
76
|
this.managers.add(new PopupManager({ popupPortalEl: this.popupPortalEl, referenceEl, resinTags }));
|
|
77
|
-
this.managers.add(new DrawingManager({ referenceEl, resinTags }));
|
|
77
|
+
this.managers.add(new DrawingManager({ popupPortalEl: this.popupPortalEl, referenceEl, resinTags }));
|
|
78
78
|
this.managers.add(new RegionManager({ referenceEl, resinTags }));
|
|
79
79
|
this.managers.add(new RegionCreationManager({ referenceEl, resinTags }));
|
|
80
80
|
}
|
|
@@ -124,6 +124,7 @@ export default class ImageAnnotator extends BaseAnnotator {
|
|
|
124
124
|
});
|
|
125
125
|
|
|
126
126
|
manager.render({
|
|
127
|
+
callbacks: { onCopyLink: this.onCopyLink },
|
|
127
128
|
intl: this.intl,
|
|
128
129
|
store: this.store,
|
|
129
130
|
});
|
|
@@ -27,7 +27,6 @@ export default class MediaAnnotator extends BaseAnnotator {
|
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
destroy(): void {
|
|
30
|
-
|
|
31
30
|
// If the store handler is present, unsubscribe from the store.
|
|
32
31
|
if (this.storeHandler) {
|
|
33
32
|
this.storeHandler();
|
|
@@ -44,12 +43,40 @@ export default class MediaAnnotator extends BaseAnnotator {
|
|
|
44
43
|
return this.containerEl?.querySelector(VIDEO_PARENT_SELECTOR);
|
|
45
44
|
}
|
|
46
45
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
46
|
+
addManagers(referenceEl: HTMLVideoElement, resinTags: { fileid: string | null; iscurrent: boolean }): void {
|
|
47
|
+
this.managers.add(
|
|
48
|
+
new PopupManager({
|
|
49
|
+
location: MEDIA_LOCATION_INDEX,
|
|
50
|
+
popupPortalEl: this.popupPortalEl,
|
|
51
|
+
referenceEl,
|
|
52
|
+
resinTags,
|
|
53
|
+
targetType: TARGET_TYPE.FRAME,
|
|
54
|
+
}),
|
|
55
|
+
);
|
|
56
|
+
this.managers.add(
|
|
57
|
+
new DrawingManager({
|
|
58
|
+
location: MEDIA_LOCATION_INDEX,
|
|
59
|
+
referenceEl,
|
|
60
|
+
resinTags,
|
|
61
|
+
targetType: TARGET_TYPE.FRAME,
|
|
62
|
+
}),
|
|
63
|
+
);
|
|
64
|
+
this.managers.add(
|
|
65
|
+
new RegionManager({
|
|
66
|
+
location: MEDIA_LOCATION_INDEX,
|
|
67
|
+
referenceEl,
|
|
68
|
+
resinTags,
|
|
69
|
+
targetType: TARGET_TYPE.FRAME,
|
|
70
|
+
}),
|
|
71
|
+
);
|
|
72
|
+
this.managers.add(
|
|
73
|
+
new RegionCreationManager({
|
|
74
|
+
location: MEDIA_LOCATION_INDEX,
|
|
75
|
+
referenceEl,
|
|
76
|
+
resinTags,
|
|
77
|
+
targetType: TARGET_TYPE.FRAME,
|
|
78
|
+
}),
|
|
79
|
+
);
|
|
53
80
|
}
|
|
54
81
|
|
|
55
82
|
getManagers(parentEl: HTMLElement, referenceEl: HTMLVideoElement): Set<Manager> {
|
|
@@ -70,8 +97,6 @@ export default class MediaAnnotator extends BaseAnnotator {
|
|
|
70
97
|
return this.managers;
|
|
71
98
|
}
|
|
72
99
|
|
|
73
|
-
|
|
74
|
-
|
|
75
100
|
// returns the actual video element
|
|
76
101
|
getReference(): HTMLVideoElement | null | undefined {
|
|
77
102
|
return this.annotatedEl?.querySelector('video');
|
|
@@ -108,6 +133,7 @@ export default class MediaAnnotator extends BaseAnnotator {
|
|
|
108
133
|
width: `${referenceEl.offsetWidth}px`,
|
|
109
134
|
});
|
|
110
135
|
manager.render({
|
|
136
|
+
callbacks: { onCopyLink: this.onCopyLink },
|
|
111
137
|
intl: this.intl,
|
|
112
138
|
store: this.store,
|
|
113
139
|
});
|
|
@@ -116,12 +142,11 @@ export default class MediaAnnotator extends BaseAnnotator {
|
|
|
116
142
|
this.postRender();
|
|
117
143
|
}
|
|
118
144
|
|
|
119
|
-
// This function gets called by the client. We are using the name scrollToAnnotation to match
|
|
145
|
+
// This function gets called by the client. We are using the name scrollToAnnotation to match
|
|
120
146
|
// the other annotators as the client calls this function when it wants to show an annoation on the
|
|
121
|
-
// preview. The only difference is that we are using the video element's currentTime to scroll to the
|
|
147
|
+
// preview. The only difference is that we are using the video element's currentTime to scroll to the
|
|
122
148
|
// annotation instead of the scrollLeft and scrollTop of the parent element.
|
|
123
|
-
scrollToAnnotation(annotationId: string | null | undefined, defaultLocation: number = -1
|
|
124
|
-
|
|
149
|
+
scrollToAnnotation(annotationId: string | null | undefined, defaultLocation: number = -1): void {
|
|
125
150
|
if (!annotationId) {
|
|
126
151
|
return;
|
|
127
152
|
}
|
|
@@ -129,13 +154,11 @@ export default class MediaAnnotator extends BaseAnnotator {
|
|
|
129
154
|
const annotationLocation = annotation?.target?.location?.value ?? defaultLocation;
|
|
130
155
|
const video = this.getReference();
|
|
131
156
|
|
|
132
|
-
if (
|
|
157
|
+
if (!video || !this.annotatedEl || annotationLocation === -1) {
|
|
133
158
|
return;
|
|
134
159
|
}
|
|
135
160
|
|
|
136
161
|
video.pause();
|
|
137
162
|
video.currentTime = annotationLocation / 1000;
|
|
138
|
-
|
|
139
163
|
}
|
|
140
164
|
}
|
|
141
|
-
|
package/src/popup/PopupLayer.tsx
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
+
import * as ReactDOM from 'react-dom';
|
|
2
3
|
import noop from 'lodash/noop';
|
|
3
4
|
import PopupReply from '../components/Popups/PopupReply';
|
|
4
5
|
import PopupV2 from '../components/Popups/PopupV2';
|
|
@@ -44,6 +45,8 @@ const modeStagedMap: { [M in Mode]?: (staged: CreatorItem | null) => boolean } =
|
|
|
44
45
|
[Mode.REGION]: isCreatorStagedRegion,
|
|
45
46
|
};
|
|
46
47
|
|
|
48
|
+
const ACTIVE_TARGET_OBSERVER_TIMEOUT_MS = 10000;
|
|
49
|
+
|
|
47
50
|
const PopupLayer = (props: Props): JSX.Element | null => {
|
|
48
51
|
const {
|
|
49
52
|
activeAnnotationId,
|
|
@@ -97,13 +100,39 @@ const PopupLayer = (props: Props): JSX.Element | null => {
|
|
|
97
100
|
setReference(referenceId ? document.querySelector(`[data-ba-reference-id="${referenceId}"]`) : null);
|
|
98
101
|
}, [referenceId]);
|
|
99
102
|
|
|
103
|
+
// activeAnnotationId can be set (e.g. via deep link) before the target DOM node mounts;
|
|
104
|
+
// observe until it appears, or give up after ACTIVE_TARGET_OBSERVER_TIMEOUT_MS.
|
|
100
105
|
React.useEffect(() => {
|
|
101
|
-
if (activeAnnotationId
|
|
102
|
-
const el = document.querySelector(`[data-ba-annotation-id="${CSS.escape(activeAnnotationId)}"]`);
|
|
103
|
-
setActiveReference(el);
|
|
104
|
-
} else {
|
|
106
|
+
if (!activeAnnotationId || !isThreadedAnnotation) {
|
|
105
107
|
setActiveReference(null);
|
|
108
|
+
return noop;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const selector = `[data-ba-annotation-id="${CSS.escape(activeAnnotationId)}"]`;
|
|
112
|
+
const existing = document.querySelector(selector);
|
|
113
|
+
if (existing) {
|
|
114
|
+
setActiveReference(existing);
|
|
115
|
+
return noop;
|
|
106
116
|
}
|
|
117
|
+
|
|
118
|
+
setActiveReference(null);
|
|
119
|
+
const observer = new MutationObserver(() => {
|
|
120
|
+
const el = document.querySelector(selector);
|
|
121
|
+
if (el) {
|
|
122
|
+
setActiveReference(el);
|
|
123
|
+
observer.disconnect();
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
observer.observe(document.body, { childList: true, subtree: true });
|
|
127
|
+
|
|
128
|
+
const timeoutId = window.setTimeout(() => {
|
|
129
|
+
observer.disconnect();
|
|
130
|
+
}, ACTIVE_TARGET_OBSERVER_TIMEOUT_MS);
|
|
131
|
+
|
|
132
|
+
return () => {
|
|
133
|
+
observer.disconnect();
|
|
134
|
+
window.clearTimeout(timeoutId);
|
|
135
|
+
};
|
|
107
136
|
}, [activeAnnotationId, isThreadedAnnotation]);
|
|
108
137
|
|
|
109
138
|
const showCreator = canCreate && canReply && reference && staged;
|
|
@@ -111,17 +140,14 @@ const PopupLayer = (props: Props): JSX.Element | null => {
|
|
|
111
140
|
if (showCreator && isThreadedAnnotation) {
|
|
112
141
|
return (
|
|
113
142
|
<div className="ba-PopupLayer-popup">
|
|
114
|
-
<PopupV2
|
|
115
|
-
onSubmit={handleSubmit}
|
|
116
|
-
popupPortalEl={popupPortalEl}
|
|
117
|
-
reference={reference}
|
|
118
|
-
/>
|
|
143
|
+
<PopupV2 onSubmit={handleSubmit} popupPortalEl={popupPortalEl} reference={reference} />
|
|
119
144
|
</div>
|
|
120
145
|
);
|
|
121
146
|
}
|
|
122
147
|
|
|
123
148
|
if (showCreator) {
|
|
124
|
-
return
|
|
149
|
+
if (!popupPortalEl) return null;
|
|
150
|
+
return ReactDOM.createPortal(
|
|
125
151
|
<div className="ba-PopupLayer-popup">
|
|
126
152
|
<PopupReply
|
|
127
153
|
isPending={isPending}
|
|
@@ -131,7 +157,8 @@ const PopupLayer = (props: Props): JSX.Element | null => {
|
|
|
131
157
|
reference={reference}
|
|
132
158
|
value={message}
|
|
133
159
|
/>
|
|
134
|
-
</div
|
|
160
|
+
</div>,
|
|
161
|
+
popupPortalEl,
|
|
135
162
|
);
|
|
136
163
|
}
|
|
137
164
|
|
|
@@ -20,16 +20,18 @@ export default class PopupManager extends BaseManager {
|
|
|
20
20
|
this.reactEl.dataset.testid = 'ba-Layer--popup';
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
render(
|
|
23
|
+
render({ callbacks, intl, store }: Props): void {
|
|
24
24
|
if (!this.root) {
|
|
25
25
|
this.root = ReactDOM.createRoot(this.reactEl);
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
this.root.render(
|
|
29
29
|
<PopupContainer
|
|
30
|
+
callbacks={callbacks}
|
|
31
|
+
intl={intl}
|
|
30
32
|
location={this.location}
|
|
31
|
-
{...props}
|
|
32
33
|
popupPortalEl={this.popupPortalEl}
|
|
34
|
+
store={store}
|
|
33
35
|
targetType={this.targetType}
|
|
34
36
|
/>,
|
|
35
37
|
);
|
|
@@ -26,8 +26,8 @@ const RegionAnnotations = (props: Props): JSX.Element => {
|
|
|
26
26
|
setActiveAnnotationId(annotationId);
|
|
27
27
|
};
|
|
28
28
|
|
|
29
|
-
let annotationsToShow: AnnotationRegion[] = []
|
|
30
|
-
|
|
29
|
+
let annotationsToShow: AnnotationRegion[] = [];
|
|
30
|
+
|
|
31
31
|
if (targetType === TARGET_TYPE.FRAME) {
|
|
32
32
|
if (!isVideoSeeking && activeAnnotationId) {
|
|
33
33
|
annotationsToShow = annotations.filter(annotation => annotation.id === activeAnnotationId);
|
|
@@ -35,7 +35,6 @@ const RegionAnnotations = (props: Props): JSX.Element => {
|
|
|
35
35
|
} else {
|
|
36
36
|
annotationsToShow = annotations;
|
|
37
37
|
}
|
|
38
|
-
|
|
39
38
|
|
|
40
39
|
return (
|
|
41
40
|
<RegionList
|
|
@@ -9,9 +9,9 @@ import { getVideoCurrentTimeInMilliseconds } from '../utils/useVideoTiming';
|
|
|
9
9
|
|
|
10
10
|
type Props = {
|
|
11
11
|
isCreating: boolean;
|
|
12
|
-
isRotated: boolean;
|
|
13
12
|
location: number;
|
|
14
13
|
resetCreator: () => void;
|
|
14
|
+
rotation: number;
|
|
15
15
|
setReferenceId: (uuid: string) => void;
|
|
16
16
|
setStaged: (staged: CreatorItemRegion | null) => void;
|
|
17
17
|
setStatus: (status: CreatorStatus) => void;
|
|
@@ -27,13 +27,19 @@ type State = {
|
|
|
27
27
|
export default class RegionCreation extends React.PureComponent<Props, State> {
|
|
28
28
|
static defaultProps = {
|
|
29
29
|
isCreating: false,
|
|
30
|
-
|
|
30
|
+
rotation: 0,
|
|
31
31
|
};
|
|
32
32
|
|
|
33
33
|
state: State = {};
|
|
34
34
|
|
|
35
35
|
handleAbort = (): void => {
|
|
36
|
-
const { resetCreator } = this.props;
|
|
36
|
+
const { resetCreator, staged } = this.props;
|
|
37
|
+
|
|
38
|
+
// Click-away (a click too small to start a new region) must not discard an in-progress comment/annotation
|
|
39
|
+
if (staged) {
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
|
|
37
43
|
resetCreator();
|
|
38
44
|
};
|
|
39
45
|
|
|
@@ -50,18 +56,17 @@ export default class RegionCreation extends React.PureComponent<Props, State> {
|
|
|
50
56
|
|
|
51
57
|
handleStop = (shape: Rect): void => {
|
|
52
58
|
const { location, setStaged, setStatus, targetType, referenceEl } = this.props;
|
|
53
|
-
const annotationLocation =
|
|
59
|
+
const annotationLocation =
|
|
60
|
+
targetType !== TARGET_TYPE.FRAME
|
|
61
|
+
? location
|
|
62
|
+
: getVideoCurrentTimeInMilliseconds(referenceEl as HTMLVideoElement);
|
|
54
63
|
|
|
55
64
|
setStaged({ location: annotationLocation, shape });
|
|
56
65
|
setStatus(CreatorStatus.staged);
|
|
57
66
|
};
|
|
58
67
|
|
|
59
68
|
render(): JSX.Element | null {
|
|
60
|
-
const { isCreating,
|
|
61
|
-
|
|
62
|
-
if (isRotated) {
|
|
63
|
-
return null;
|
|
64
|
-
}
|
|
69
|
+
const { isCreating, rotation, staged } = this.props;
|
|
65
70
|
|
|
66
71
|
return (
|
|
67
72
|
<>
|
|
@@ -71,6 +76,7 @@ export default class RegionCreation extends React.PureComponent<Props, State> {
|
|
|
71
76
|
onAbort={this.handleAbort}
|
|
72
77
|
onStart={this.handleStart}
|
|
73
78
|
onStop={this.handleStop}
|
|
79
|
+
rotation={rotation}
|
|
74
80
|
/>
|
|
75
81
|
)}
|
|
76
82
|
|
|
@@ -19,7 +19,7 @@ import withProviders from '../common/withProviders';
|
|
|
19
19
|
|
|
20
20
|
export type Props = {
|
|
21
21
|
isCreating: boolean;
|
|
22
|
-
|
|
22
|
+
rotation: number;
|
|
23
23
|
staged: CreatorItemRegion | null;
|
|
24
24
|
};
|
|
25
25
|
|
|
@@ -28,7 +28,7 @@ export const mapStateToProps = (state: AppState, { location }: { location: numbe
|
|
|
28
28
|
|
|
29
29
|
return {
|
|
30
30
|
isCreating: getAnnotationMode(state) === Mode.REGION && getCreatorStatus(state) !== CreatorStatus.pending,
|
|
31
|
-
|
|
31
|
+
rotation: getRotation(state),
|
|
32
32
|
staged: isCreatorStagedRegion(staged) ? staged : null,
|
|
33
33
|
};
|
|
34
34
|
};
|
|
@@ -14,6 +14,13 @@ export default class RegionManager extends BaseManager {
|
|
|
14
14
|
this.root = ReactDOM.createRoot(this.reactEl);
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
this.root.render(
|
|
17
|
+
this.root.render(
|
|
18
|
+
<RegionCreationContainer
|
|
19
|
+
targetType={this.targetType}
|
|
20
|
+
referenceEl={this.referenceEl}
|
|
21
|
+
location={this.location}
|
|
22
|
+
{...props}
|
|
23
|
+
/>,
|
|
24
|
+
);
|
|
18
25
|
}
|
|
19
26
|
}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
$region_cursor_32: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAADhlWElmTU0AKgAAAAgAAYdpAAQAAAABAAAAGgAAAAAAAqACAAQAAAABAAAAIKADAAQAAAABAAAAIAAAAACPTkDJAAAA8UlEQVRYCe1Vyw6DIBBcafkPDxjb9P8/pQcTD/4HkZZpe1qeEQyHsgeTXZbZcRiUqEdXoLECQ835LxsxvMEGX7/yQmmuxtELsW6bt16dAKbwYSFS6BV4nBGQG5HCPkzAHveOM7exp4bE1g8TAOh9moLYX25xU2LzKR6InTlnXJ0ANyAfyPOqBHJMxwkUeYCDHcmTCsBMCWAR6slRJHlPAf6YZzLGODy01iSldOpCCHouC+UQcDbzAgiE4qZUaOlT51i+PHkEobewE/ABgoeM7bn4wHNqzU3YCTRXIMcn3h6Y8HcFiv6GXvBe7Ap0Bf5KgTeoYIC/a04wgAAAAABJRU5ErkJggg==';
|
|
2
2
|
$region_cursor_32_2x: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAABGdBTUEAALGPC/xhBQAAADhlWElmTU0AKgAAAAgAAYdpAAQAAAABAAAAGgAAAAAAAqACAAQAAAABAAAAQKADAAQAAAABAAAAQAAAAABlmWCKAAABWUlEQVR4Ae2YOxKDIBCGNaM5R4pYWOT+B0lhYQrPEZ1JGGcoZIy6Lj4IH40DLAt8+8srSUgQgAAEIAABCEAAAnESSM867Y9JmrGlJi1pf1li9M822dknd7/dREN8NY3IHgWIcB1oPBdZqVLsVFCAJRHK113dtbsFCtg78iZib9Nn7vTbmshenbJdsihgF8wjnZRF0ZdWdT1S+7tI+8+7nlGAS+Ss+bX7/Nx8UMAcoaPr506A2vGhAC3Brdq7J76t+oleAQDYSlqh+FW/CHk6meVSP77WiOh/gUUvp1NytpF7lGXSdd2U6aCubds+n+fuxXBgNshkWZY8q6ovQwEDNOsz3hQgHcLa26DtBwVYEsqveheQRsKsGbwIKYPmtXn02yAAvOopQGcoIMCgeR0yCvCKM0Bn0StAfReQBp2ToJQY9hCAAAQgAAEIQAACEIAABCAAAQhAwDOBLxaXQ2IYNsXoAAAAAElFTkSuQmCC';
|
|
3
3
|
$region_cursor_32_3x: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAYAAADimHc4AAAABGdBTUEAALGPC/xhBQAAADhlWElmTU0AKgAAAAgAAYdpAAQAAAABAAAAGgAAAAAAAqACAAQAAAABAAAAYKADAAQAAAABAAAAYAAAAACK+310AAACaUlEQVR4Ae3bwUrDQBDG8VTE+Bg9CD0IBd//IYSCh4KHPobxopuDYQgGOtNvdhvy39O2zc5uf9Odpol2HQ0BBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAgXSBXfoMdzDBT2mZy9iVFo3/EB3IOI0ACdA4hqM8hkeudODLfi9Z+eflIonDDpAwxoOQgLidZOTmSpBV85YRVfmya2AHWI0GfRLQAN1OuekSZCGWfkxl/4hjB9gsNOiTgAbodsrVlKBSCr7Kwnu7+Fl/KGXkefbc3T9kBzROEQlonIDVlCDr9Ho4dMMwdH3fdx/ns30p3M8+21laGDtgSabS8ySgEvTSNKssQUtvxvt8xrUd7xrYAV4x8fEkQAzqDbe5EuS9BO0F9R7PDvCKiY8nAWJQb7hNlKClS81erIzj2QEZqo6YJMCBlXEoCchQdcQkAQ6sjENJQIaqI2b6WVDFy7y9aq6aZ03sAMenNeNQEpCh6ogZ/seCa+ewZeHteOy+y52sW9t4N+yvjXfFbm1PJcb76TSFqVmC0r8DpndVOiO+xbOvRfvqeNF1RMdVTcD4SVM0i67aAYp1RWJULUGRBf43JuOmvJ2nZgniS9jKN+iTgAbodsr07wDVdi5nU/xpos0cfY0AJUjjGI5CAsJ0moEkQOMYjkICwnSagSRA4xiOQgLCdJqBJEDjGI5CAsJ0moEkQOMYjkICwnSagSRA4xiOQgLCdJqBJEDjGI6SfkcsvLLZQC5Hz0B4qBGgBGkciYIAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIITAK/BlNVeN572e8AAAAASUVORK5CYII=';
|
|
4
|
-
|
|
5
4
|
$region_cursor_new: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAAEEfUpiAAAABGdBTUEAALGPC/xhBQAAADhlWElmTU0AKgAAAAgAAYdpAAQAAAABAAAAGgAAAAAAAqACAAQAAAABAAAAIKADAAQAAAABAAAAIAAAAACPTkDJAAAFEUlEQVRYCcVXeUyjVRD/erCl5SjtrpblWHbxADlTD0TDESIak0UJUYyE/zAhGo7gP+oaMDEhIRFNiCRG4A8NmGACwYsAG0lIIBSMCBSCrRDCXbkRiq2bbvv5m9qv2+srn3UTJ5nO++bNmzdv5r2ZKcMEgp6entfAF9Gc2EMglsZOLg1OTk7Gj4+PP6KxP+Tn57O+3CfBkHsyL29sbHzqyWBmZ2eLwfDc1TnvZiwtLanBsRcWFpJ+tzVOKdePDDSqu7v7g8nJyS8wDvec5Ma0MjYrK+tx0Ac5piAqMhgMLwWTJGNZvV7PK+QUIKG5ubmbgTSJDw4OHJi4CtQA3cfkBkSlLS0tWzab7f3s7Oy60tJSLXhuz5FzbAqF4g48OpCamsrrrCgIqvf39xdAJcCAQNtxWwcUCMYU9/b2vpqXl0cueTkURWLXhaQzsAUFBez8/HxJMEXu2+Jr1vb2NtPR0aELDw9/D+PbbW1t5F4/8FMgk8n+hFRGQkKCIikpyYqbpRoaGkpUqVSjeAifYM5vjZ9WF+NKc3PzQUNDwzP4jgBeHx0dvQVK11YQKPr6+t5dX1//rbW19XWEbnl8fHzh8PBwGqsFK/HciR6lCij4CJ6LBY//0yWiXS45HA4LUcFb+ghGTE9Ps6enp1ahSgI6RKlUhp+dnf0hRElABWRVdHS0XIgSXgVClQRUkJKSwqysrMwik+n29vZ+Pjo6+hIKA8rSRp4QgYfD9vf3t4F5HUhVgfIUXSDeBII5NyhGRkbewZemvLxcqdPppjs7Ow2Ey8vLP4Hvd4V9Mw/tEga8u7u7+9XOzk764OBgm91uFyOd1+Non2VmZn6OecoXQUG6ubn5rdFopNwXA1ROTEw0g8YBvTblcwxrsViOV1dXHXDi26DFcrn8xbW1tVookAIvBFKchMVGPN9FPOVfhoeHF0CNjY2NKZjzsoJPG/mCStgDwKsIpUGtVqdj7FVr8S0IyCIKZcCiKUjD/yFEfpKYTKYncPwXMCbn8wUtZPuCKSQDZDMzMwkoyLeRYswodlSjKFcJCqIQq4IZQOtF2FiGwsBQiqqtrf0O36f305CLDPA6BB6T05C6urrvKdXdD0P+lQGcNSiPznxbX1/vNATtA3VdIYVG0KvmNiaKboEpKipys2CEHM3rD8hXFjSz5chZP2LyLvDCfOVWwjMg70RQs0R1LiMjg0WCdAwMDFAyfA6YB3zWhU+DZgOvASOBglI35C7Oa2KxmM3JyXE0NTV9HBsb+zXW/A40azQaBoaVREZGpotEIimqOUOyEonESn8mkpOTpyBnB1LvywvBnhPNUVypr6IM9heQWgYGSfktZPpKtMPX0EKapNJ7kTSbzezY2Nhj1dXVS0jibxYXF89hCRkSUkjICEIKB1FyrXpra+sbavxQchcrKyspST0CvAF8VKvVFiBUehSBhaqqKgoL5W7ey37PdEgFAM5qjjqNYFmWKAPXs/Hx8dS+mIB3gNKampoYq9XqQF8siYmJof6IQsCtx9AbnIq8WUG/yANR7e3tz5eUlHzY1dX1EGJuKysr+zUuLm4ROSoLueESPKQKCwuz486c5ebm2s7Pz2+lpaWNYW3IoeCsIoOpTFKVfxj4VGJiYj6oFphGFPX2jampKf0ioKKi4hUX/zIorfM7sB8DQkKA1nH3gsaciymkSpz8Ck7tAB7i+wxoc8lwcvj8B0I1gFvvS0kfZxzNcfH325hb+Dfx/eE8ndH+AwAAAABJRU5ErkJggg==';
|
|
6
5
|
$region_cursor_new_2x: 'data:image/png;base64,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';
|
|
7
6
|
$region_cursor_new_3x: 'data:image/png;base64,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';
|
|
@@ -10,8 +9,15 @@ $region_cursor_new_3x: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCA
|
|
|
10
9
|
$offset_x: 9;
|
|
11
10
|
$offset_y: 4;
|
|
12
11
|
|
|
13
|
-
cursor:
|
|
14
|
-
|
|
12
|
+
cursor:
|
|
13
|
+
url($region_cursor_new) $offset_x $offset_y,
|
|
14
|
+
auto; /* Legacy */
|
|
15
|
+
|
|
16
|
+
/* stylelint-disable unit-no-unknown */
|
|
17
|
+
cursor:
|
|
18
|
+
image-set(url($region_cursor_new) 1x, url($region_cursor_new_2x) 2x, url($region_cursor_new_3x) 3x) $offset_x $offset_y,
|
|
19
|
+
auto; /* Webkit */
|
|
20
|
+
/* stylelint-enable unit-no-unknown */
|
|
15
21
|
}
|
|
16
22
|
|
|
17
23
|
.ba-RegionCreator-rect {
|