diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/WhiteboardModel.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/WhiteboardModel.scala
index f73d74a4e5..7ada8b233a 100755
--- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/WhiteboardModel.scala
+++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/WhiteboardModel.scala
@@ -105,49 +105,65 @@ class WhiteboardModel extends SystemConfiguration {
//not empty and head id equals annotation id
//println("!usersAnnotations.isEmpty: " + (!usersAnnotations.isEmpty) + ", usersAnnotations.head.id == annotation.id: " + (usersAnnotations.head.id == annotation.id));
- if (!usersAnnotations.isEmpty && usersAnnotations.head.id == annotation.id) {
- var dimensions: List[Int] = List[Int]()
- annotation.annotationInfo.get("dimensions").foreach(d => {
- d match {
- case d2: List[_] => dimensions = convertListNumbersToInt(d2)
- }
- })
- //println("dimensions.size(): " + dimensions.size());
- if (dimensions.length == 2) {
- val oldAnnotation = usersAnnotations.head
- var oldPoints: List[Float] = List[Float]()
- oldAnnotation.annotationInfo.get("points").foreach(a => {
- a match {
- case a2: List[_] => oldPoints = a2.asInstanceOf[List[Float]]
- }
- })
-
- var newPoints: List[Float] = List[Float]()
- annotation.annotationInfo.get("points").foreach(a => {
- a match {
- case a2: List[_] => newPoints = convertListNumbersToFloat(a2)
- }
- }) //newPoints = a.asInstanceOf[ArrayList[Float]])
-
- //println("oldPoints.size(): " + oldPoints.size());
-
- //val oldPointsJava: java.util.List[java.lang.Float] = oldPoints.asJava.asInstanceOf[java.util.List[java.lang.Float]]
- //println("****class = " + oldPointsJava.getClass())
- val pathData = BezierWrapper.lineSimplifyAndCurve((oldPoints ::: newPoints).asJava.asInstanceOf[java.util.List[java.lang.Float]], dimensions(0), dimensions(1))
- //println("Path data: pointssize " + pathData.points.size() + " commandssize " + pathData.commands.size())
-
- val updatedAnnotationData = annotation.annotationInfo + ("points" -> pathData.points.asScala.toList) + ("commands" -> pathData.commands.asScala.toList)
- val updatedAnnotation = annotation.copy(position = oldAnnotation.position, annotationInfo = updatedAnnotationData)
-
- val newAnnotationsMap = wb.annotationsMap + (userId -> (updatedAnnotation :: usersAnnotations.tail))
- //println("Annotation has position [" + usersAnnotations.head.position + "]")
- val newWb = wb.copy(annotationsMap = newAnnotationsMap)
- //println("Updating annotation on page [" + wb.id + "]. After numAnnotations=[" + getAnnotationsByUserId(wb, userId).length + "].")
- saveWhiteboard(newWb)
-
- rtnAnnotation = updatedAnnotation
+ var dimensions: List[Int] = List[Int]()
+ annotation.annotationInfo.get("dimensions").foreach(d => {
+ d match {
+ case d2: List[_] => dimensions = convertListNumbersToInt(d2)
}
+ })
+
+ //println("dimensions.size(): " + dimensions.size());
+ if (dimensions.length == 2) {
+ var oldPoints: List[Float] = List[Float]()
+ val oldAnnotationOption: Option[AnnotationVO] = usersAnnotations.headOption
+ if (!oldAnnotationOption.isEmpty) {
+ val oldAnnotation = oldAnnotationOption.get
+ if (oldAnnotation.id == annotation.id) {
+ oldAnnotation.annotationInfo.get("points").foreach(a => {
+ a match {
+ case a2: List[_] => oldPoints = a2.asInstanceOf[List[Float]]
+ }
+ })
+ }
+ }
+
+ var newPoints: List[Float] = List[Float]()
+ annotation.annotationInfo.get("points").foreach(a => {
+ a match {
+ case a2: List[_] => newPoints = convertListNumbersToFloat(a2)
+ }
+ }) //newPoints = a.asInstanceOf[ArrayList[Float]])
+
+ //println("oldPoints.size(): " + oldPoints.size)
+
+ //val oldPointsJava: java.util.List[java.lang.Float] = oldPoints.asJava.asInstanceOf[java.util.List[java.lang.Float]]
+ //println("****class = " + oldPointsJava.getClass())
+ val pathData = BezierWrapper.lineSimplifyAndCurve((oldPoints ::: newPoints).asJava.asInstanceOf[java.util.List[java.lang.Float]], dimensions(0), dimensions(1))
+ //println("Path data: pointssize " + pathData.points.size() + " commandssize " + pathData.commands.size())
+
+ val updatedAnnotationData = annotation.annotationInfo + ("points" -> pathData.points.asScala.toList) + ("commands" -> pathData.commands.asScala.toList)
+ //println("oldAnnotation value = " + oldAnnotationOption.getOrElse("Empty"))
+
+ var newPosition: Int = oldAnnotationOption match {
+ case Some(annotation) => annotation.position
+ case None => wb.annotationCount
+ }
+
+ val updatedAnnotation = annotation.copy(position = newPosition, annotationInfo = updatedAnnotationData)
+
+ var newUsersAnnotations: List[AnnotationVO] = oldAnnotationOption match {
+ case Some(annotation) => usersAnnotations.tail
+ case None => usersAnnotations
+ }
+
+ val newAnnotationsMap = wb.annotationsMap + (userId -> (updatedAnnotation :: newUsersAnnotations))
+ //println("Annotation has position [" + usersAnnotations.head.position + "]")
+ val newWb = wb.copy(annotationsMap = newAnnotationsMap)
+ //println("Updating annotation on page [" + wb.id + "]. After numAnnotations=[" + getAnnotationsByUserId(wb, userId).length + "].")
+ saveWhiteboard(newWb)
+
+ rtnAnnotation = updatedAnnotation
}
rtnAnnotation
diff --git a/bigbluebutton-html5/imports/ui/components/presentation/component.jsx b/bigbluebutton-html5/imports/ui/components/presentation/component.jsx
index 3bdbaccad5..796da6d291 100755
--- a/bigbluebutton-html5/imports/ui/components/presentation/component.jsx
+++ b/bigbluebutton-html5/imports/ui/components/presentation/component.jsx
@@ -489,6 +489,15 @@ class PresentationArea extends PureComponent {
width,
height,
}}
+ published
+ whiteboardId={currentSlide.id}
+ />
+
Annotations.findOne({
+const getAnnotationById = _id => UnsentAnnotations.findOne({
_id,
});
diff --git a/bigbluebutton-html5/imports/ui/components/whiteboard/annotation-factory/static-annotation/service.js b/bigbluebutton-html5/imports/ui/components/whiteboard/annotation-factory/static-annotation/service.js
index 4550a60159..fb90fb58d5 100755
--- a/bigbluebutton-html5/imports/ui/components/whiteboard/annotation-factory/static-annotation/service.js
+++ b/bigbluebutton-html5/imports/ui/components/whiteboard/annotation-factory/static-annotation/service.js
@@ -1,4 +1,4 @@
-import Annotations from '/imports/ui/components/whiteboard/service';
+import { Annotations } from '/imports/ui/components/whiteboard/service';
const getAnnotationById = _id => Annotations.findOne({
_id,
diff --git a/bigbluebutton-html5/imports/ui/components/whiteboard/annotation-group/container.jsx b/bigbluebutton-html5/imports/ui/components/whiteboard/annotation-group/container.jsx
index 6bdaeb2f37..5f9ca81d05 100755
--- a/bigbluebutton-html5/imports/ui/components/whiteboard/annotation-group/container.jsx
+++ b/bigbluebutton-html5/imports/ui/components/whiteboard/annotation-group/container.jsx
@@ -4,18 +4,27 @@ import { withTracker } from 'meteor/react-meteor-data';
import AnnotationGroupService from './service';
import AnnotationGroup from './component';
-const AnnotationGroupContainer = props => (
+const AnnotationGroupContainer = ({
+ annotationsInfo, width, height, whiteboardId,
+}) => (
);
export default withTracker((params) => {
- const { whiteboardId } = params;
- const annotationsInfo = AnnotationGroupService.getCurrentAnnotationsInfo(whiteboardId);
+ const {
+ whiteboardId,
+ published,
+ } = params;
+
+ const fetchFunc = published
+ ? AnnotationGroupService.getCurrentAnnotationsInfo : AnnotationGroupService.getUnsetAnnotations;
+
+ const annotationsInfo = fetchFunc(whiteboardId);
return {
annotationsInfo,
};
diff --git a/bigbluebutton-html5/imports/ui/components/whiteboard/annotation-group/service.js b/bigbluebutton-html5/imports/ui/components/whiteboard/annotation-group/service.js
index e0428fe9d5..683b8449a7 100755
--- a/bigbluebutton-html5/imports/ui/components/whiteboard/annotation-group/service.js
+++ b/bigbluebutton-html5/imports/ui/components/whiteboard/annotation-group/service.js
@@ -1,4 +1,4 @@
-import Annotations from '/imports/ui/components/whiteboard/service';
+import { Annotations, UnsentAnnotations } from '/imports/ui/components/whiteboard/service';
const getCurrentAnnotationsInfo = (whiteboardId) => {
if (!whiteboardId) {
@@ -8,7 +8,22 @@ const getCurrentAnnotationsInfo = (whiteboardId) => {
return Annotations.find(
{
whiteboardId,
- // annotationType: { $ne: 'pencil_base' },
+ },
+ {
+ sort: { position: 1 },
+ fields: { status: 1, _id: 1, annotationType: 1 },
+ },
+ ).fetch();
+};
+
+const getUnsetAnnotations = (whiteboardId) => {
+ if (!whiteboardId) {
+ return null;
+ }
+
+ return UnsentAnnotations.find(
+ {
+ whiteboardId,
},
{
sort: { position: 1 },
@@ -19,4 +34,5 @@ const getCurrentAnnotationsInfo = (whiteboardId) => {
export default {
getCurrentAnnotationsInfo,
+ getUnsetAnnotations,
};
diff --git a/bigbluebutton-html5/imports/ui/components/whiteboard/annotations/ellipse/component.jsx b/bigbluebutton-html5/imports/ui/components/whiteboard/annotations/ellipse/component.jsx
index 1da0de3b8b..01e9f7a415 100644
--- a/bigbluebutton-html5/imports/ui/components/whiteboard/annotations/ellipse/component.jsx
+++ b/bigbluebutton-html5/imports/ui/components/whiteboard/annotations/ellipse/component.jsx
@@ -1,16 +1,16 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
-import AnnotationHelpers from '../helpers';
+import { getFormattedColor, getStrokeWidth, denormalizeCoord } from '../helpers';
export default class EllipseDrawComponent extends Component {
-
shouldComponentUpdate(nextProps) {
- return this.props.version !== nextProps.version;
+ const { version } = this.props;
+ return version !== nextProps.version;
}
getCoordinates() {
- const { points } = this.props.annotation;
- const { slideWidth, slideHeight } = this.props;
+ const { slideWidth, slideHeight, annotation } = this.props;
+ const { points } = annotation;
// x1 and y1 - coordinates of the ellipse's top left corner
// x2 and y2 - coordinates of the ellipse's bottom right corner
@@ -24,10 +24,10 @@ export default class EllipseDrawComponent extends Component {
// cx and cy - coordinates of the ellipse's center
let rx = (x2 - x1) / 2;
let ry = (y2 - y1) / 2;
- const cx = ((rx + x1) * slideWidth) / 100;
- const cy = ((ry + y1) * slideHeight) / 100;
- rx = Math.abs((rx / 100) * slideWidth);
- ry = Math.abs((ry / 100) * slideHeight);
+ const cx = denormalizeCoord(rx + x1, slideWidth);
+ const cy = denormalizeCoord(ry + y1, slideHeight);
+ rx = denormalizeCoord(Math.abs(rx), slideWidth);
+ ry = denormalizeCoord(Math.abs(ry), slideHeight);
return {
cx,
@@ -40,7 +40,9 @@ export default class EllipseDrawComponent extends Component {
render() {
const results = this.getCoordinates();
const { annotation, slideWidth } = this.props;
- const { cx, cy, rx, ry } = results;
+ const {
+ cx, cy, rx, ry,
+ } = results;
return (
);
diff --git a/bigbluebutton-html5/imports/ui/components/whiteboard/annotations/helpers.js b/bigbluebutton-html5/imports/ui/components/whiteboard/annotations/helpers.js
index 7c4ff2a769..5d67acd6fe 100644
--- a/bigbluebutton-html5/imports/ui/components/whiteboard/annotations/helpers.js
+++ b/bigbluebutton-html5/imports/ui/components/whiteboard/annotations/helpers.js
@@ -20,7 +20,10 @@ const getFormattedColor = (color) => {
const getStrokeWidth = (thickness, slideWidth) => (thickness * slideWidth) / 100;
-export default {
+const denormalizeCoord = (normCoord, sideLength) => ((normCoord / 100) * sideLength).toFixed(2);
+
+export {
getFormattedColor,
getStrokeWidth,
+ denormalizeCoord,
};
diff --git a/bigbluebutton-html5/imports/ui/components/whiteboard/annotations/line/component.jsx b/bigbluebutton-html5/imports/ui/components/whiteboard/annotations/line/component.jsx
index 81e8dacf9d..18725c6d90 100644
--- a/bigbluebutton-html5/imports/ui/components/whiteboard/annotations/line/component.jsx
+++ b/bigbluebutton-html5/imports/ui/components/whiteboard/annotations/line/component.jsx
@@ -1,21 +1,21 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
-import AnnotationHelpers from '../helpers';
+import { getFormattedColor, getStrokeWidth, denormalizeCoord } from '../helpers';
export default class LineDrawComponent extends Component {
-
shouldComponentUpdate(nextProps) {
- return this.props.version !== nextProps.version;
+ const { version } = this.props;
+ return version !== nextProps.version;
}
getCoordinates() {
- const { slideWidth, slideHeight } = this.props;
- const { points } = this.props.annotation;
+ const { slideWidth, slideHeight, annotation } = this.props;
+ const { points } = annotation;
- const x1 = (points[0] / 100) * slideWidth;
- const y1 = (points[1] / 100) * slideHeight;
- const x2 = (points[2] / 100) * slideWidth;
- const y2 = (points[3] / 100) * slideHeight;
+ const x1 = denormalizeCoord(points[0], slideWidth);
+ const y1 = denormalizeCoord(points[1], slideHeight);
+ const x2 = denormalizeCoord(points[2], slideWidth);
+ const y2 = denormalizeCoord(points[3], slideHeight);
return {
x1,
@@ -28,7 +28,9 @@ export default class LineDrawComponent extends Component {
render() {
const results = this.getCoordinates();
const { annotation, slideWidth } = this.props;
- const { x1, y1, x2, y2 } = results;
+ const {
+ x1, y1, x2, y2,
+ } = results;
return (
);
diff --git a/bigbluebutton-html5/imports/ui/components/whiteboard/annotations/pencil/component.jsx b/bigbluebutton-html5/imports/ui/components/whiteboard/annotations/pencil/component.jsx
index e367e04fb8..3a808503ea 100755
--- a/bigbluebutton-html5/imports/ui/components/whiteboard/annotations/pencil/component.jsx
+++ b/bigbluebutton-html5/imports/ui/components/whiteboard/annotations/pencil/component.jsx
@@ -1,6 +1,6 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
-import AnnotationHelpers from '../helpers';
+import { getFormattedColor, getStrokeWidth, denormalizeCoord } from '../helpers';
export default class PencilDrawComponent extends Component {
static getInitialCoordinates(annotation, slideWidth, slideHeight) {
@@ -8,11 +8,11 @@ export default class PencilDrawComponent extends Component {
let i = 2;
let path = '';
if (points && points.length >= 2) {
- path = `M${(points[0] / 100) * slideWidth
- }, ${(points[1] / 100) * slideHeight}`;
+ path = `M${denormalizeCoord(points[0], slideWidth)
+ }, ${denormalizeCoord(points[1], slideHeight)}`;
while (i < points.length) {
- path = `${path} L${(points[i] / 100) * slideWidth
- }, ${(points[i + 1] / 100) * slideHeight}`;
+ path = `${path} L${denormalizeCoord(points[i], slideWidth)
+ }, ${denormalizeCoord(points[i + 1], slideHeight)}`;
i += 2;
}
}
@@ -30,32 +30,32 @@ export default class PencilDrawComponent extends Component {
switch (commands[i]) {
// MOVE_TO - consumes 1 pair of values
case 1:
- path = `${path} M${(points[j] / 100) * slideWidth} ${(points[j + 1] / 100) * slideHeight}`;
+ path = `${path} M${denormalizeCoord(points[j], slideWidth)} ${denormalizeCoord(points[j + 1], slideHeight)}`;
j += 2;
break;
// LINE_TO - consumes 1 pair of values
case 2:
- path = `${path} L${(points[j] / 100) * slideWidth} ${(points[j + 1] / 100) * slideHeight}`;
+ path = `${path} L${denormalizeCoord(points[j], slideWidth)} ${denormalizeCoord(points[j + 1], slideHeight)}`;
j += 2;
break;
// QUADRATIC_CURVE_TO - consumes 2 pairs of values
// 1st pair is a control point, second is a coordinate
case 3:
- path = `${path} Q${(points[j] / 100) * slideWidth}, ${
- (points[j + 1] / 100) * slideHeight}, ${(points[j + 2] / 100) * slideWidth}, ${
- (points[j + 3] / 100) * slideHeight}`;
+ path = `${path} Q${denormalizeCoord(points[j], slideWidth)}, ${
+ denormalizeCoord(points[j + 1], slideHeight)}, ${denormalizeCoord(points[j + 2], slideWidth)}, ${
+ denormalizeCoord(points[j + 3], slideHeight)}`;
j += 4;
break;
// CUBIC_CURVE_TO - consumes 3 pairs of values
// 1st and 2nd are control points, 3rd is an end coordinate
case 4:
- path = `${path} C${(points[j] / 100) * slideWidth}, ${
- (points[j + 1] / 100) * slideHeight}, ${(points[j + 2] / 100) * slideWidth}, ${
- (points[j + 3] / 100) * slideHeight}, ${(points[j + 4] / 100) * slideWidth}, ${
- (points[j + 5] / 100) * slideHeight}`;
+ path = `${path} C${denormalizeCoord(points[j], slideWidth)}, ${
+ denormalizeCoord(points[j + 1], slideHeight)}, ${denormalizeCoord(points[j + 2], slideWidth)}, ${
+ denormalizeCoord(points[j + 3], slideHeight)}, ${denormalizeCoord(points[j + 4], slideWidth)}, ${
+ denormalizeCoord(points[j + 5], slideHeight)}`;
j += 6;
break;
@@ -67,7 +67,7 @@ export default class PencilDrawComponent extends Component {
// If that's just one coordinate at the end (dot) - we want to display it.
// So adding L with the same X and Y values to the path
if (path && points.length === 2) {
- path = `${path} L${(points[0] / 100) * slideWidth} ${(points[1] / 100) * slideHeight}`;
+ path = `${path} L${denormalizeCoord(points[0], slideWidth)} ${denormalizeCoord(points[1], slideHeight)}`;
}
return { path, points };
@@ -85,13 +85,17 @@ export default class PencilDrawComponent extends Component {
}
shouldComponentUpdate(nextProps) {
- return this.props.version !== nextProps.version;
+ const { version } = this.props;
+ return version !== nextProps.version;
}
componentWillUpdate(nextProps) {
- const { annotation, slideWidth, slideHeight } = nextProps;
- if (annotation.points.length !== this.props.annotation.points.length) {
- this.path = this.getCoordinates(annotation, slideWidth, slideHeight);
+ const { annotation: nextAnnotation, slideWidth, slideHeight } = nextProps;
+ const { points: nextPoints } = nextAnnotation;
+ const { annotation } = this.props;
+ const { points } = annotation;
+ if (nextPoints.length !== points.length) {
+ this.path = this.getCoordinates(nextAnnotation, slideWidth, slideHeight);
}
}
@@ -123,14 +127,15 @@ export default class PencilDrawComponent extends Component {
updateCoordinates(annotation, slideWidth, slideHeight) {
const { points } = annotation;
+
let i = this.points.length;
let path = '';
-
while (i < points.length) {
- path = `${path} L${(points[i] / 100) * slideWidth
- }, ${(points[i + 1] / 100) * slideHeight}`;
+ path = `${path} L${denormalizeCoord(points[i], slideWidth)
+ }, ${denormalizeCoord(points[i + 1], slideHeight)}`;
i += 2;
}
+
path = this.path + path;
return { path, points };
@@ -141,9 +146,9 @@ export default class PencilDrawComponent extends Component {
return (
);
diff --git a/bigbluebutton-html5/imports/ui/components/whiteboard/annotations/text/component.jsx b/bigbluebutton-html5/imports/ui/components/whiteboard/annotations/text/component.jsx
index 3cafe4d3fb..7c87acc2b2 100644
--- a/bigbluebutton-html5/imports/ui/components/whiteboard/annotations/text/component.jsx
+++ b/bigbluebutton-html5/imports/ui/components/whiteboard/annotations/text/component.jsx
@@ -1,7 +1,7 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import RenderInBrowser from 'react-render-in-browser';
-import AnnotationHelpers from '../helpers';
+import { getFormattedColor, denormalizeCoord } from '../helpers';
const DRAW_END = Meteor.settings.public.whiteboard.annotations.status.end;
@@ -109,11 +109,11 @@ export default class TextDrawComponent extends Component {
text,
} = annotation;
- const _x = (x / 100) * slideWidth;
- const _y = (y / 100) * slideHeight;
- const _width = (textBoxWidth / 100) * slideWidth;
- const _height = (textBoxHeight / 100) * slideHeight;
- const _fontColor = AnnotationHelpers.getFormattedColor(fontColor);
+ const _x = denormalizeCoord(x, slideWidth);
+ const _y = denormalizeCoord(y, slideHeight);
+ const _width = denormalizeCoord(textBoxWidth, slideWidth);
+ const _height = denormalizeCoord(textBoxHeight, slideHeight);
+ const _fontColor = getFormattedColor(fontColor);
const _fontSize = fontSize;
const _calcedFontSize = (calcedFontSize / 100) * slideHeight;
const _text = text;
diff --git a/bigbluebutton-html5/imports/ui/components/whiteboard/annotations/triangle/component.jsx b/bigbluebutton-html5/imports/ui/components/whiteboard/annotations/triangle/component.jsx
index 06e49c1e86..2a2133def3 100644
--- a/bigbluebutton-html5/imports/ui/components/whiteboard/annotations/triangle/component.jsx
+++ b/bigbluebutton-html5/imports/ui/components/whiteboard/annotations/triangle/component.jsx
@@ -1,16 +1,16 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
-import AnnotationHelpers from '../helpers';
+import { getFormattedColor, getStrokeWidth, denormalizeCoord } from '../helpers';
export default class TriangleDrawComponent extends Component {
-
shouldComponentUpdate(nextProps) {
- return this.props.version !== nextProps.version;
+ const { version } = this.props;
+ return version !== nextProps.version;
}
getCoordinates() {
- const { slideWidth, slideHeight } = this.props;
- const { points } = this.props.annotation;
+ const { slideWidth, slideHeight, annotation } = this.props;
+ const { points } = annotation;
// points[0] and points[1] are x and y coordinates of the top left corner of the annotation
// points[2] and points[3] are x and y coordinates of the bottom right corner of the annotation
@@ -21,13 +21,13 @@ export default class TriangleDrawComponent extends Component {
const xTop = ((xBottomRight - xBottomLeft) / 2) + xBottomLeft;
const yTop = points[1];
- const path = `M${(xTop / 100) * slideWidth
- },${(yTop / 100) * slideHeight
- },${(xBottomLeft / 100) * slideWidth
- },${(yBottomLeft / 100) * slideHeight
- },${(xBottomRight / 100) * slideWidth
- },${(yBottomRight / 100) * slideHeight
- }Z`;
+ const path = `M${denormalizeCoord(xTop, slideWidth)
+ },${denormalizeCoord(yTop, slideHeight)
+ },${denormalizeCoord(xBottomLeft, slideWidth)
+ },${denormalizeCoord(yBottomLeft, slideHeight)
+ },${denormalizeCoord(xBottomRight, slideWidth)
+ },${denormalizeCoord(yBottomRight, slideHeight)
+ }Z`;
return path;
}
@@ -39,9 +39,9 @@ export default class TriangleDrawComponent extends Component {
);
diff --git a/bigbluebutton-html5/imports/ui/components/whiteboard/service.js b/bigbluebutton-html5/imports/ui/components/whiteboard/service.js
index f8712a3e36..4fa4bfe9ed 100755
--- a/bigbluebutton-html5/imports/ui/components/whiteboard/service.js
+++ b/bigbluebutton-html5/imports/ui/components/whiteboard/service.js
@@ -2,25 +2,25 @@ import Users from '/imports/api/users';
import Auth from '/imports/ui/services/auth';
import WhiteboardMultiUser from '/imports/api/whiteboard-multi-user/';
import addAnnotationQuery from '/imports/api/annotations/addAnnotation';
-import logger from '/imports/startup/client/logger';
import { makeCall } from '/imports/ui/services/api';
-import { isEqual } from 'lodash';
const Annotations = new Mongo.Collection(null);
+const UnsentAnnotations = new Mongo.Collection(null);
const ANNOTATION_CONFIG = Meteor.settings.public.whiteboard.annotations;
-const DRAW_START = ANNOTATION_CONFIG.status.start;
+const DRAW_UPDATE = ANNOTATION_CONFIG.status.update;
const DRAW_END = ANNOTATION_CONFIG.status.end;
-const discardedList = [];
+
+const ANNOTATION_TYPE_PENCIL = 'pencil';
let annotationsStreamListener = null;
-export function addAnnotationToDiscardedList(annotation) {
- if (!discardedList.includes(annotation)) discardedList.push(annotation);
-}
+const clearPreview = (annotation) => {
+ UnsentAnnotations.remove({ id: annotation });
+};
function clearFakeAnnotations() {
- Annotations.remove({ id: /-fake/g });
+ UnsentAnnotations.remove({});
}
function handleAddedAnnotation({
@@ -29,55 +29,11 @@ function handleAddedAnnotation({
const isOwn = Auth.meetingID === meetingId && Auth.userID === userId;
const query = addAnnotationQuery(meetingId, whiteboardId, userId, annotation);
- if (!isOwn) {
- Annotations.upsert(query.selector, query.modifier);
- return;
+ Annotations.upsert(query.selector, query.modifier);
+
+ if (isOwn) {
+ UnsentAnnotations.remove({ id: `${annotation.id}` });
}
-
- const fakeAnnotation = Annotations.findOne({ id: `${annotation.id}-fake` });
- let fakePoints;
-
- if (fakeAnnotation) {
- fakePoints = fakeAnnotation.annotationInfo.points;
- const { points: lastPoints } = annotation.annotationInfo;
-
- if (annotation.annotationType !== 'pencil') {
- Annotations.update(fakeAnnotation._id, {
- $set: {
- position: annotation.position,
- 'annotationInfo.color': isEqual(fakePoints, lastPoints) || annotation.status === DRAW_END
- ? annotation.annotationInfo.color : fakeAnnotation.annotationInfo.color,
- },
- $inc: { version: 1 }, // TODO: Remove all this version stuff
- });
- return;
- }
- }
-
- Annotations.upsert(query.selector, query.modifier, (err) => {
- if (err) {
- logger.error({
- logCode: 'whiteboard_annotation_upsert_error',
- extraInfo: { error: err },
- }, 'Error on adding an annotation');
- return;
- }
-
- // Remove fake annotation for pencil on draw end
- if (annotation.status === DRAW_END) {
- Annotations.remove({ id: `${annotation.id}-fake` });
- return;
- }
-
- if (annotation.status === DRAW_START) {
- Annotations.update(fakeAnnotation._id, {
- $set: {
- position: annotation.position - 1,
- },
- $inc: { version: 1 }, // TODO: Remove all this version stuff
- });
- }
- });
}
function handleRemovedAnnotation({
@@ -85,14 +41,12 @@ function handleRemovedAnnotation({
}) {
const query = { meetingId, whiteboardId };
- addAnnotationToDiscardedList(shapeId);
-
if (userId) {
query.userId = userId;
}
if (shapeId) {
- query.id = { $in: [shapeId, `${shapeId}-fake`] };
+ query.id = shapeId;
}
Annotations.remove(query);
@@ -109,7 +63,7 @@ export function initAnnotationsStreamListener() {
const startStreamHandlersPromise = new Promise((resolve) => {
const checkStreamHandlersInterval = setInterval(() => {
const streamHandlersSize = Object.values(Meteor.StreamerCentral.instances[`annotations-${Auth.meetingID}`].handlers)
- .filter(el => el != undefined)
+ .filter(el => el !== undefined)
.length;
if (!streamHandlersSize) {
@@ -122,10 +76,7 @@ export function initAnnotationsStreamListener() {
annotationsStreamListener.on('removed', handleRemovedAnnotation);
annotationsStreamListener.on('added', ({ annotations }) => {
- // Call handleAddedAnnotation when this annotation is not in discardedList
- annotations
- .filter(({ annotation }) => !discardedList.includes(annotation.id))
- .forEach(annotation => handleAddedAnnotation(annotation));
+ annotations.forEach(annotation => handleAddedAnnotation(annotation));
});
});
}
@@ -172,41 +123,52 @@ const proccessAnnotationsQueue = async () => {
const annotations = annotationsQueue.splice(0, queueSize);
// console.log('annotationQueue.length', annotationsQueue, annotationsQueue.length);
- await makeCall('sendBulkAnnotations', annotations.filter(({ id }) => !discardedList.includes(id)));
+ await makeCall('sendBulkAnnotations', annotations);
// ask tiago
const delayPerc = Math.min(annotationsMaxDelayQueueSize, queueSize) / annotationsMaxDelayQueueSize;
const delayDelta = annotationsBufferTimeMax - annotationsBufferTimeMin;
const delayTime = annotationsBufferTimeMin + (delayDelta * delayPerc);
+ // console.log("delayPerc:", delayPerc)
setTimeout(proccessAnnotationsQueue, delayTime);
};
-export function sendAnnotation(annotation) {
+const sendAnnotation = (annotation) => {
// Prevent sending annotations while disconnected
+ // TODO: Change this to add the annotation, but delay the send until we're
+ // reconnected. With this it will miss things
if (!Meteor.status().connected) return;
- annotationsQueue.push(annotation);
- if (!annotationsSenderIsRunning) setTimeout(proccessAnnotationsQueue, annotationsBufferTimeMin);
-
- // skip optimistic for draw end since the smoothing is done in akka
- if (annotation.status === DRAW_END) return;
-
- const { position, ...relevantAnotation } = annotation;
- const queryFake = addAnnotationQuery(
- Auth.meetingID, annotation.wbId, Auth.userID,
- {
- ...relevantAnotation,
- id: `${annotation.id}-fake`,
- position: Number.MAX_SAFE_INTEGER,
- annotationInfo: {
- ...annotation.annotationInfo,
- color: increaseBrightness(annotation.annotationInfo.color, 40),
+ if (annotation.status === DRAW_END) {
+ annotationsQueue.push(annotation);
+ if (!annotationsSenderIsRunning) setTimeout(proccessAnnotationsQueue, annotationsBufferTimeMin);
+ } else {
+ const { position, ...relevantAnotation } = annotation;
+ const queryFake = addAnnotationQuery(
+ Auth.meetingID, annotation.wbId, Auth.userID,
+ {
+ ...relevantAnotation,
+ id: `${annotation.id}`,
+ position: Number.MAX_SAFE_INTEGER,
+ annotationInfo: {
+ ...annotation.annotationInfo,
+ color: increaseBrightness(annotation.annotationInfo.color, 40),
+ },
},
- },
- );
+ );
- Annotations.upsert(queryFake.selector, queryFake.modifier);
-}
+ // This is a really hacky solution, but because of the previous code reuse we need to edit
+ // the pencil draw update modifier so that it sets the whole array instead of pushing to
+ // the end
+ const { status, annotationType } = relevantAnotation;
+ if (status === DRAW_UPDATE && annotationType === ANNOTATION_TYPE_PENCIL) {
+ delete queryFake.modifier.$push;
+ queryFake.modifier.$set['annotationInfo.points'] = annotation.annotationInfo.points;
+ }
+
+ UnsentAnnotations.upsert(queryFake.selector, queryFake.modifier);
+ }
+};
WhiteboardMultiUser.find({ meetingId: Auth.meetingID }).observeChanges({
changed: clearFakeAnnotations,
@@ -218,4 +180,9 @@ Users.find({ userId: Auth.userID }, { fields: { presenter: 1 } }).observeChanges
},
});
-export default Annotations;
+export {
+ Annotations,
+ UnsentAnnotations,
+ sendAnnotation,
+ clearPreview,
+};
diff --git a/bigbluebutton-html5/imports/ui/components/whiteboard/whiteboard-overlay/component.jsx b/bigbluebutton-html5/imports/ui/components/whiteboard/whiteboard-overlay/component.jsx
index 09cce8e832..0ad127fd71 100755
--- a/bigbluebutton-html5/imports/ui/components/whiteboard/whiteboard-overlay/component.jsx
+++ b/bigbluebutton-html5/imports/ui/components/whiteboard/whiteboard-overlay/component.jsx
@@ -201,8 +201,7 @@ export default class WhiteboardOverlay extends Component {
resetTextShapeSession,
setTextShapeActiveId,
contextMenuHandler,
- addAnnotationToDiscardedList,
- undoAnnotation,
+ clearPreview,
updateCursor,
} = this.props;
@@ -218,8 +217,7 @@ export default class WhiteboardOverlay extends Component {
resetTextShapeSession,
setTextShapeActiveId,
contextMenuHandler,
- addAnnotationToDiscardedList,
- undoAnnotation,
+ clearPreview,
};
return (
@@ -257,6 +255,8 @@ WhiteboardOverlay.propTypes = {
viewBoxHeight: PropTypes.number.isRequired,
// Defines a handler to publish an annotation to the server
sendAnnotation: PropTypes.func.isRequired,
+ // Defines a handler to clear a shape preview
+ clearPreview: PropTypes.func.isRequired,
// Defines a current whiteboard id
whiteboardId: PropTypes.string.isRequired,
// Defines an object containing current settings for drawing
diff --git a/bigbluebutton-html5/imports/ui/components/whiteboard/whiteboard-overlay/container.jsx b/bigbluebutton-html5/imports/ui/components/whiteboard/whiteboard-overlay/container.jsx
index 86b1e08959..90eef160d4 100755
--- a/bigbluebutton-html5/imports/ui/components/whiteboard/whiteboard-overlay/container.jsx
+++ b/bigbluebutton-html5/imports/ui/components/whiteboard/whiteboard-overlay/container.jsx
@@ -2,7 +2,6 @@ import React from 'react';
import { withTracker } from 'meteor/react-meteor-data';
import PropTypes from 'prop-types';
import WhiteboardOverlayService from './service';
-import WhiteboardToolbarService from '../whiteboard-toolbar/service';
import WhiteboardOverlay from './component';
const WhiteboardOverlayContainer = (props) => {
@@ -16,10 +15,9 @@ const WhiteboardOverlayContainer = (props) => {
};
export default withTracker(() => ({
- undoAnnotation: WhiteboardToolbarService.undoAnnotation,
+ clearPreview: WhiteboardOverlayService.clearPreview,
contextMenuHandler: WhiteboardOverlayService.contextMenuHandler,
sendAnnotation: WhiteboardOverlayService.sendAnnotation,
- addAnnotationToDiscardedList: WhiteboardOverlayService.addAnnotationToDiscardedList,
setTextShapeActiveId: WhiteboardOverlayService.setTextShapeActiveId,
resetTextShapeSession: WhiteboardOverlayService.resetTextShapeSession,
drawSettings: WhiteboardOverlayService.getWhiteboardToolbarValues(),
diff --git a/bigbluebutton-html5/imports/ui/components/whiteboard/whiteboard-overlay/pencil-draw-listener/component.jsx b/bigbluebutton-html5/imports/ui/components/whiteboard/whiteboard-overlay/pencil-draw-listener/component.jsx
index 4caf3d09f1..68d8092fff 100755
--- a/bigbluebutton-html5/imports/ui/components/whiteboard/whiteboard-overlay/pencil-draw-listener/component.jsx
+++ b/bigbluebutton-html5/imports/ui/components/whiteboard/whiteboard-overlay/pencil-draw-listener/component.jsx
@@ -8,7 +8,7 @@ const DRAW_END = ANNOTATION_CONFIG.status.end;
// maximum value of z-index to prevent other things from overlapping
const MAX_Z_INDEX = (2 ** 31) - 1;
-const POINTS_TO_BUFFER = 5;
+const POINTS_TO_BUFFER = 2;
export default class PencilDrawListener extends Component {
constructor() {
@@ -64,8 +64,8 @@ export default class PencilDrawListener extends Component {
transformedSvgPoint = svgCoordinateToPercentages(transformedSvgPoint);
// sending the first message
- const _points = [transformedSvgPoint.x, transformedSvgPoint.y];
- this.handleDrawPencil(_points, DRAW_START, generateNewShapeId());
+ this.points = [transformedSvgPoint.x, transformedSvgPoint.y];
+ this.handleDrawPencil(this.points, DRAW_START, generateNewShapeId());
}
commonDrawMoveHandler(clientX, clientY) {
@@ -147,7 +147,6 @@ export default class PencilDrawListener extends Component {
// if you switch to a different window using Alt+Tab while mouse is down and release it
// it wont catch mouseUp and will keep tracking the movements. Thus we need this check.
} else if (isRightClick) {
- this.sendLastMessage();
this.discardAnnotation();
}
}
@@ -171,7 +170,6 @@ export default class PencilDrawListener extends Component {
const { getCurrentShapeId } = actions;
this.handleDrawPencil(this.points, DRAW_UPDATE, getCurrentShapeId());
- this.points = [];
}
}
@@ -254,19 +252,16 @@ export default class PencilDrawListener extends Component {
discardAnnotation() {
const {
- whiteboardId,
actions,
} = this.props;
const {
getCurrentShapeId,
- addAnnotationToDiscardedList,
- undoAnnotation,
+ clearPreview,
} = actions;
-
- undoAnnotation(whiteboardId);
- addAnnotationToDiscardedList(getCurrentShapeId());
+ this.resetState();
+ clearPreview(getCurrentShapeId());
}
render() {
diff --git a/bigbluebutton-html5/imports/ui/components/whiteboard/whiteboard-overlay/service.js b/bigbluebutton-html5/imports/ui/components/whiteboard/whiteboard-overlay/service.js
index 95a0eb272a..534ffe471b 100755
--- a/bigbluebutton-html5/imports/ui/components/whiteboard/whiteboard-overlay/service.js
+++ b/bigbluebutton-html5/imports/ui/components/whiteboard/whiteboard-overlay/service.js
@@ -1,6 +1,6 @@
import Storage from '/imports/ui/services/storage/session';
import Auth from '/imports/ui/services/auth';
-import { sendAnnotation, addAnnotationToDiscardedList } from '/imports/ui/components/whiteboard/service';
+import { sendAnnotation, clearPreview } from '/imports/ui/components/whiteboard/service';
import { publishCursorUpdate } from '/imports/ui/components/cursor/service';
const DRAW_SETTINGS = 'drawSettings';
@@ -55,7 +55,6 @@ const updateCursor = (payload) => {
};
export default {
- addAnnotationToDiscardedList,
sendAnnotation,
getWhiteboardToolbarValues,
setTextShapeActiveId,
@@ -63,4 +62,5 @@ export default {
getCurrentUserId,
contextMenuHandler,
updateCursor,
+ clearPreview,
};
diff --git a/bigbluebutton-html5/imports/ui/components/whiteboard/whiteboard-overlay/shape-draw-listener/component.jsx b/bigbluebutton-html5/imports/ui/components/whiteboard/whiteboard-overlay/shape-draw-listener/component.jsx
index 554c2469a8..5b70a3a73b 100755
--- a/bigbluebutton-html5/imports/ui/components/whiteboard/whiteboard-overlay/shape-draw-listener/component.jsx
+++ b/bigbluebutton-html5/imports/ui/components/whiteboard/whiteboard-overlay/shape-draw-listener/component.jsx
@@ -174,8 +174,6 @@ export default class ShapeDrawListener extends Component {
// if you switch to a different window using Alt+Tab while mouse is down and release it
// it wont catch mouseUp and will keep tracking the movements. Thus we need this check.
} else if (isRightClick) {
- // this.isDrawing = false;
- this.sendLastMessage();
this.discardAnnotation();
}
}
@@ -324,18 +322,16 @@ export default class ShapeDrawListener extends Component {
discardAnnotation() {
const {
- whiteboardId,
actions,
} = this.props;
const {
getCurrentShapeId,
- addAnnotationToDiscardedList,
- undoAnnotation,
+ clearPreview,
} = actions;
- undoAnnotation(whiteboardId);
- addAnnotationToDiscardedList(getCurrentShapeId());
+ this.resetState();
+ clearPreview(getCurrentShapeId());
}
render() {
diff --git a/bigbluebutton-html5/imports/ui/components/whiteboard/whiteboard-overlay/text-draw-listener/component.jsx b/bigbluebutton-html5/imports/ui/components/whiteboard/whiteboard-overlay/text-draw-listener/component.jsx
index 518c3aeea8..056d81ce97 100755
--- a/bigbluebutton-html5/imports/ui/components/whiteboard/whiteboard-overlay/text-draw-listener/component.jsx
+++ b/bigbluebutton-html5/imports/ui/components/whiteboard/whiteboard-overlay/text-draw-listener/component.jsx
@@ -215,12 +215,11 @@ export default class TextDrawListener extends Component {
}
// second case is when a user finished writing the text and publishes the final result
+ } else if (isRightClick) {
+ this.discardAnnotation();
} else {
// publishing the final shape and resetting the state
this.sendLastMessage();
- if (isRightClick) {
- this.discardAnnotation();
- }
}
}
@@ -460,18 +459,16 @@ export default class TextDrawListener extends Component {
discardAnnotation() {
const {
- whiteboardId,
actions,
} = this.props;
const {
getCurrentShapeId,
- addAnnotationToDiscardedList,
- undoAnnotation,
+ clearPreview,
} = actions;
- undoAnnotation(whiteboardId);
- addAnnotationToDiscardedList(getCurrentShapeId());
+ this.resetState();
+ clearPreview(getCurrentShapeId());
}
render() {