microboard-temp 0.2.4 → 0.3.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/cjs/browser.js +545 -509
- package/dist/cjs/index.js +545 -509
- package/dist/cjs/node.js +545 -509
- package/dist/esm/browser.js +545 -509
- package/dist/esm/index.js +545 -509
- package/dist/esm/node.js +545 -509
- package/dist/types/BoardOperations.d.ts +1 -1
- package/dist/types/Items/Audio/Audio.d.ts +1 -0
- package/dist/types/Items/BaseItem/BaseItem.d.ts +4 -1
- package/dist/types/Items/Image/Image.d.ts +1 -0
- package/dist/types/Items/Video/Video.d.ts +1 -0
- package/package.json +1 -1
package/dist/esm/node.js
CHANGED
|
@@ -35930,6 +35930,7 @@ class BaseItem extends Mbr {
|
|
|
35930
35930
|
transformationRenderBlock = undefined;
|
|
35931
35931
|
board;
|
|
35932
35932
|
id;
|
|
35933
|
+
onRemoveCallbacks = [];
|
|
35933
35934
|
shouldUseCustomRender = false;
|
|
35934
35935
|
shouldRenderOutsideViewRect = true;
|
|
35935
35936
|
itemType = "";
|
|
@@ -36007,6 +36008,12 @@ class BaseItem extends Mbr {
|
|
|
36007
36008
|
break;
|
|
36008
36009
|
}
|
|
36009
36010
|
}
|
|
36011
|
+
addOnRemoveCallback(cb) {
|
|
36012
|
+
this.onRemoveCallbacks.push(cb);
|
|
36013
|
+
}
|
|
36014
|
+
onRemove() {
|
|
36015
|
+
this.onRemoveCallbacks.forEach((cb) => cb());
|
|
36016
|
+
}
|
|
36010
36017
|
render(context) {}
|
|
36011
36018
|
renderHTML(documentFactory) {
|
|
36012
36019
|
return documentFactory.createElement("div");
|
|
@@ -41263,6 +41270,9 @@ class VideoItem extends BaseItem {
|
|
|
41263
41270
|
this.loadCallbacks.push(callback);
|
|
41264
41271
|
};
|
|
41265
41272
|
getStorageId() {
|
|
41273
|
+
if (!this.isStorageUrl) {
|
|
41274
|
+
return;
|
|
41275
|
+
}
|
|
41266
41276
|
return this.url.split("/").pop();
|
|
41267
41277
|
}
|
|
41268
41278
|
getIsStorageUrl() {
|
|
@@ -41535,6 +41545,13 @@ class VideoItem extends BaseItem {
|
|
|
41535
41545
|
linkElem.click();
|
|
41536
41546
|
}
|
|
41537
41547
|
}
|
|
41548
|
+
onRemove() {
|
|
41549
|
+
const storageId = this.getStorageId();
|
|
41550
|
+
if (storageId) {
|
|
41551
|
+
deleteMedia([storageId], this.board.getBoardId());
|
|
41552
|
+
}
|
|
41553
|
+
super.onRemove();
|
|
41554
|
+
}
|
|
41538
41555
|
}
|
|
41539
41556
|
// src/Items/Image/calculatePosition.ts
|
|
41540
41557
|
function calculatePosition(boardImage, board) {
|
|
@@ -41965,432 +41982,122 @@ var captureFrame = (frameTime, video) => {
|
|
|
41965
41982
|
return null;
|
|
41966
41983
|
}
|
|
41967
41984
|
};
|
|
41968
|
-
// src/Items/
|
|
41969
|
-
|
|
41985
|
+
// src/Items/Placeholder/Placeholder.ts
|
|
41986
|
+
var PlaceholderImg = `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
41987
|
+
<path d="M5 11.1L7 9.1L12.5 14.6L16 11.1L19 14.1V5H5V11.1ZM4 3H20C20.2652 3 20.5196 3.10536 20.7071 3.29289C20.8946 3.48043 21 3.73478 21 4V20C21 20.2652 20.8946 20.5196 20.7071 20.7071C20.5196 20.8946 20.2652 21 20 21H4C3.73478 21 3.48043 20.8946 3.29289 20.7071C3.10536 20.5196 3 20.2652 3 20V4C3 3.73478 3.10536 3.48043 3.29289 3.29289C3.48043 3.10536 3.73478 3 4 3ZM15.5 10C15.1022 10 14.7206 9.84196 14.4393 9.56066C14.158 9.27936 14 8.89782 14 8.5C14 8.10218 14.158 7.72064 14.4393 7.43934C14.7206 7.15804 15.1022 7 15.5 7C15.8978 7 16.2794 7.15804 16.5607 7.43934C16.842 7.72064 17 8.10218 17 8.5C17 8.89782 16.842 9.27936 16.5607 9.56066C16.2794 9.84196 15.8978 10 15.5 10Z" fill="white" fill-opacity="0.6"/>
|
|
41988
|
+
</svg>`;
|
|
41989
|
+
|
|
41990
|
+
class Placeholder extends BaseItem {
|
|
41970
41991
|
events;
|
|
41971
|
-
|
|
41972
|
-
|
|
41992
|
+
miroData;
|
|
41993
|
+
backgroundColor;
|
|
41994
|
+
icon;
|
|
41995
|
+
itemType = "Placeholder";
|
|
41996
|
+
shapeType = "Rectangle";
|
|
41973
41997
|
parent = "Board";
|
|
41974
41998
|
transformation;
|
|
41975
|
-
|
|
41999
|
+
path = Shapes[this.shapeType].path.copy();
|
|
42000
|
+
mbr = Shapes[this.shapeType].path.getMbr().copy();
|
|
41976
42001
|
subject = new Subject;
|
|
41977
|
-
loadCallbacks = [];
|
|
41978
|
-
beforeLoadCallbacks = [];
|
|
41979
42002
|
transformationRenderBlock = undefined;
|
|
41980
|
-
|
|
41981
|
-
|
|
41982
|
-
currentTime = 0;
|
|
41983
|
-
isStorageUrl = true;
|
|
41984
|
-
constructor(board, isStorageUrl, url, events, id = "", extension2) {
|
|
42003
|
+
iconImage;
|
|
42004
|
+
constructor(board, events, miroData, id = "", backgroundColor = "#E5E5EA", icon = PlaceholderImg?.toString() || "") {
|
|
41985
42005
|
super(board, id);
|
|
41986
42006
|
this.events = events;
|
|
41987
|
-
this.
|
|
41988
|
-
this.
|
|
41989
|
-
this.
|
|
41990
|
-
this.
|
|
41991
|
-
|
|
41992
|
-
this.
|
|
41993
|
-
}
|
|
41994
|
-
this.transformation = new Transformation(id, events);
|
|
41995
|
-
this.linkTo.subject.subscribe(() => {
|
|
42007
|
+
this.miroData = miroData;
|
|
42008
|
+
this.backgroundColor = backgroundColor;
|
|
42009
|
+
this.icon = icon;
|
|
42010
|
+
this.transformation = new Transformation(this.id, this.events);
|
|
42011
|
+
this.transformation.subject.subscribe((_subject) => {
|
|
42012
|
+
this.transformPath();
|
|
41996
42013
|
this.updateMbr();
|
|
41997
42014
|
this.subject.publish(this);
|
|
41998
42015
|
});
|
|
41999
|
-
this.transformation.subject.subscribe(this.onTransform);
|
|
42000
|
-
this.right = this.left + conf.AUDIO_DIMENSIONS.width;
|
|
42001
|
-
this.bottom = this.top + conf.AUDIO_DIMENSIONS.height;
|
|
42002
|
-
this.shouldUseCustomRender = true;
|
|
42003
|
-
}
|
|
42004
|
-
setCurrentTime(time) {
|
|
42005
|
-
this.currentTime = time;
|
|
42006
|
-
}
|
|
42007
|
-
getCurrentTime() {
|
|
42008
|
-
return this.currentTime;
|
|
42009
|
-
}
|
|
42010
|
-
getIsStorageUrl() {
|
|
42011
|
-
return this.isStorageUrl;
|
|
42012
|
-
}
|
|
42013
|
-
onTransform = () => {
|
|
42014
42016
|
this.updateMbr();
|
|
42015
|
-
this.
|
|
42016
|
-
};
|
|
42017
|
-
doOnceBeforeOnLoad = (callback) => {
|
|
42018
|
-
this.loadCallbacks.push(callback);
|
|
42019
|
-
};
|
|
42020
|
-
doOnceOnLoad = (callback) => {
|
|
42021
|
-
this.loadCallbacks.push(callback);
|
|
42022
|
-
};
|
|
42023
|
-
setIsPlaying(isPlaying) {
|
|
42024
|
-
this.isPlaying = isPlaying;
|
|
42025
|
-
this.shouldRenderOutsideViewRect = isPlaying;
|
|
42026
|
-
this.subject.publish(this);
|
|
42027
|
-
}
|
|
42028
|
-
getIsPlaying() {
|
|
42029
|
-
return this.isPlaying;
|
|
42017
|
+
this.loadIconImage();
|
|
42030
42018
|
}
|
|
42031
|
-
|
|
42032
|
-
if (this.
|
|
42033
|
-
|
|
42034
|
-
|
|
42035
|
-
|
|
42036
|
-
} catch (_) {}
|
|
42019
|
+
emit(operation) {
|
|
42020
|
+
if (this.events) {
|
|
42021
|
+
const command = new PlaceholderCommand([this], operation);
|
|
42022
|
+
command.apply();
|
|
42023
|
+
this.events.emit(operation, command);
|
|
42037
42024
|
} else {
|
|
42038
|
-
this.
|
|
42039
|
-
}
|
|
42040
|
-
}
|
|
42041
|
-
setUrl(url) {
|
|
42042
|
-
this.emit({
|
|
42043
|
-
class: "Audio",
|
|
42044
|
-
method: "setUrl",
|
|
42045
|
-
item: [this.getId()],
|
|
42046
|
-
url
|
|
42047
|
-
});
|
|
42048
|
-
}
|
|
42049
|
-
getStorageId() {
|
|
42050
|
-
return this.url.split("/").pop();
|
|
42051
|
-
}
|
|
42052
|
-
getUrl() {
|
|
42053
|
-
return this.url;
|
|
42054
|
-
}
|
|
42055
|
-
onLoad = async () => {
|
|
42056
|
-
this.shootBeforeLoadCallbacks();
|
|
42057
|
-
this.updateMbr();
|
|
42058
|
-
this.subject.publish(this);
|
|
42059
|
-
this.shootLoadCallbacks();
|
|
42060
|
-
};
|
|
42061
|
-
onError = (_error) => {
|
|
42062
|
-
this.updateMbr();
|
|
42063
|
-
this.subject.publish(this);
|
|
42064
|
-
this.shootLoadCallbacks();
|
|
42065
|
-
};
|
|
42066
|
-
updateMbr() {
|
|
42067
|
-
const { translateX, translateY, scaleX, scaleY } = this.transformation.matrix;
|
|
42068
|
-
this.left = translateX;
|
|
42069
|
-
this.top = translateY;
|
|
42070
|
-
this.right = this.left + conf.AUDIO_DIMENSIONS.width * scaleX;
|
|
42071
|
-
this.bottom = this.top + conf.AUDIO_DIMENSIONS.height * scaleY;
|
|
42072
|
-
}
|
|
42073
|
-
render(context) {
|
|
42074
|
-
if (this.transformationRenderBlock) {
|
|
42075
|
-
return;
|
|
42076
|
-
}
|
|
42077
|
-
const ctx = context.ctx;
|
|
42078
|
-
const radius = 12 * this.transformation.getScale().x;
|
|
42079
|
-
ctx.save();
|
|
42080
|
-
ctx.globalCompositeOperation = "destination-out";
|
|
42081
|
-
ctx.beginPath();
|
|
42082
|
-
ctx.moveTo(this.left + radius, this.top);
|
|
42083
|
-
ctx.lineTo(this.left + this.getWidth() - radius, this.top);
|
|
42084
|
-
ctx.quadraticCurveTo(this.left + this.getWidth(), this.top, this.left + this.getWidth(), this.top + radius);
|
|
42085
|
-
ctx.lineTo(this.left + this.getWidth(), this.top + this.getHeight() - radius);
|
|
42086
|
-
ctx.quadraticCurveTo(this.left + this.getWidth(), this.top + this.getHeight(), this.left + this.getWidth() - radius, this.top + this.getHeight());
|
|
42087
|
-
ctx.lineTo(this.left + radius, this.top + this.getHeight());
|
|
42088
|
-
ctx.quadraticCurveTo(this.left, this.top + this.getHeight(), this.left, this.top + this.getHeight() - radius);
|
|
42089
|
-
ctx.lineTo(this.left, this.top + radius);
|
|
42090
|
-
ctx.quadraticCurveTo(this.left, this.top, this.left + radius, this.top);
|
|
42091
|
-
ctx.closePath();
|
|
42092
|
-
ctx.fill();
|
|
42093
|
-
ctx.restore();
|
|
42094
|
-
}
|
|
42095
|
-
renderHTML(documentFactory) {
|
|
42096
|
-
const div = documentFactory.createElement("audio-item");
|
|
42097
|
-
const { translateX, translateY, scaleX, scaleY } = this.transformation.matrix;
|
|
42098
|
-
const transform = `translate(${translateX}px, ${translateY}px) scale(${scaleX}, ${scaleY})`;
|
|
42099
|
-
div.id = this.getId();
|
|
42100
|
-
div.style.width = `${conf.AUDIO_DIMENSIONS.width}px`;
|
|
42101
|
-
div.style.height = `${conf.AUDIO_DIMENSIONS.height}px`;
|
|
42102
|
-
div.style.transformOrigin = "top left";
|
|
42103
|
-
div.style.transform = transform;
|
|
42104
|
-
div.style.position = "absolute";
|
|
42105
|
-
div.setAttribute("audio-url", this.getUrl());
|
|
42106
|
-
if (this.extension) {
|
|
42107
|
-
div.setAttribute("extension", this.extension);
|
|
42108
|
-
}
|
|
42109
|
-
if (this.isStorageUrl) {
|
|
42110
|
-
div.setAttribute("is-storage-url", "true");
|
|
42025
|
+
this.apply(operation);
|
|
42111
42026
|
}
|
|
42112
|
-
div.setAttribute("data-link-to", "");
|
|
42113
|
-
return div;
|
|
42114
42027
|
}
|
|
42115
42028
|
serialize() {
|
|
42116
42029
|
return {
|
|
42117
|
-
itemType: "
|
|
42118
|
-
|
|
42030
|
+
itemType: "Placeholder",
|
|
42031
|
+
backgroundColor: this.backgroundColor,
|
|
42032
|
+
icon: this.icon,
|
|
42119
42033
|
transformation: this.transformation.serialize(),
|
|
42120
|
-
|
|
42121
|
-
extension: this.extension
|
|
42034
|
+
miroData: this.miroData
|
|
42122
42035
|
};
|
|
42123
42036
|
}
|
|
42124
42037
|
deserialize(data) {
|
|
42125
|
-
|
|
42126
|
-
|
|
42127
|
-
|
|
42038
|
+
this.initPath();
|
|
42039
|
+
this.backgroundColor = data.backgroundColor ?? this.backgroundColor;
|
|
42040
|
+
this.icon = data.icon ?? this.icon;
|
|
42041
|
+
this.miroData = data.miroData;
|
|
42128
42042
|
if (data.transformation) {
|
|
42129
42043
|
this.transformation.deserialize(data.transformation);
|
|
42044
|
+
this.transformPath();
|
|
42130
42045
|
}
|
|
42131
|
-
|
|
42132
|
-
|
|
42133
|
-
|
|
42134
|
-
|
|
42135
|
-
|
|
42136
|
-
|
|
42046
|
+
this.subject.publish(this);
|
|
42047
|
+
return this;
|
|
42048
|
+
}
|
|
42049
|
+
setId(id) {
|
|
42050
|
+
this.id = id;
|
|
42051
|
+
this.transformation.setId(id);
|
|
42137
42052
|
return this;
|
|
42138
42053
|
}
|
|
42054
|
+
getId() {
|
|
42055
|
+
return this.id;
|
|
42056
|
+
}
|
|
42139
42057
|
apply(op) {
|
|
42140
42058
|
switch (op.class) {
|
|
42059
|
+
case "Placeholder":
|
|
42060
|
+
this.applyPlaceholder(op);
|
|
42061
|
+
this.updateMbr();
|
|
42062
|
+
break;
|
|
42141
42063
|
case "Transformation":
|
|
42142
42064
|
this.transformation.apply(op);
|
|
42143
42065
|
break;
|
|
42144
|
-
|
|
42145
|
-
|
|
42066
|
+
default:
|
|
42067
|
+
return;
|
|
42068
|
+
}
|
|
42069
|
+
this.subject.publish(this);
|
|
42070
|
+
}
|
|
42071
|
+
applyPlaceholder(op) {
|
|
42072
|
+
switch (op.method) {
|
|
42073
|
+
case "setBackgroundColor":
|
|
42074
|
+
this.applyBackgroundColor(op.backgroundColor);
|
|
42146
42075
|
break;
|
|
42147
|
-
case "
|
|
42148
|
-
|
|
42149
|
-
|
|
42150
|
-
|
|
42151
|
-
this.
|
|
42076
|
+
case "setIcon":
|
|
42077
|
+
this.applyIcon(op.icon);
|
|
42078
|
+
break;
|
|
42079
|
+
case "setMiroData":
|
|
42080
|
+
this.applyMiroData(op.miroData);
|
|
42152
42081
|
break;
|
|
42153
42082
|
}
|
|
42154
42083
|
}
|
|
42155
|
-
|
|
42156
|
-
|
|
42157
|
-
const command = new AudioCommand([this], operation);
|
|
42158
|
-
command.apply();
|
|
42159
|
-
this.events.emit(operation, command);
|
|
42160
|
-
} else {
|
|
42161
|
-
this.apply(operation);
|
|
42162
|
-
}
|
|
42084
|
+
getBackgroundColor() {
|
|
42085
|
+
return this.backgroundColor;
|
|
42163
42086
|
}
|
|
42164
|
-
|
|
42165
|
-
this.
|
|
42166
|
-
this.
|
|
42167
|
-
return this;
|
|
42087
|
+
applyBackgroundColor(backgroundColor) {
|
|
42088
|
+
this.backgroundColor = backgroundColor;
|
|
42089
|
+
this.path.setBackgroundColor(backgroundColor);
|
|
42168
42090
|
}
|
|
42169
|
-
|
|
42170
|
-
|
|
42091
|
+
setBackgroundColor(backgroundColor) {
|
|
42092
|
+
this.emit({
|
|
42093
|
+
class: "Placeholder",
|
|
42094
|
+
method: "setBackgroundColor",
|
|
42095
|
+
item: [this.getId()],
|
|
42096
|
+
backgroundColor
|
|
42097
|
+
});
|
|
42171
42098
|
}
|
|
42172
|
-
|
|
42173
|
-
|
|
42174
|
-
this.loadCallbacks.shift()(this);
|
|
42175
|
-
}
|
|
42176
|
-
}
|
|
42177
|
-
shootBeforeLoadCallbacks() {
|
|
42178
|
-
while (this.beforeLoadCallbacks.length > 0) {
|
|
42179
|
-
this.beforeLoadCallbacks.shift()(this);
|
|
42180
|
-
}
|
|
42181
|
-
}
|
|
42182
|
-
getPath() {
|
|
42183
|
-
const { left, top, right, bottom } = this.getMbr();
|
|
42184
|
-
const leftTop = new Point(left, top);
|
|
42185
|
-
const rightTop = new Point(right, top);
|
|
42186
|
-
const rightBottom = new Point(right, bottom);
|
|
42187
|
-
const leftBottom = new Point(left, bottom);
|
|
42188
|
-
return new Path([
|
|
42189
|
-
new Line(leftTop, rightTop),
|
|
42190
|
-
new Line(rightTop, rightBottom),
|
|
42191
|
-
new Line(rightBottom, leftBottom),
|
|
42192
|
-
new Line(leftBottom, leftTop)
|
|
42193
|
-
], true);
|
|
42194
|
-
}
|
|
42195
|
-
getSnapAnchorPoints() {
|
|
42196
|
-
const mbr = this.getMbr();
|
|
42197
|
-
const width2 = mbr.getWidth();
|
|
42198
|
-
const height2 = mbr.getHeight();
|
|
42199
|
-
return [
|
|
42200
|
-
new Point(mbr.left + width2 / 2, mbr.top),
|
|
42201
|
-
new Point(mbr.left + width2 / 2, mbr.bottom),
|
|
42202
|
-
new Point(mbr.left, mbr.top + height2 / 2),
|
|
42203
|
-
new Point(mbr.right, mbr.top + height2 / 2)
|
|
42204
|
-
];
|
|
42205
|
-
}
|
|
42206
|
-
isClosed() {
|
|
42207
|
-
return true;
|
|
42208
|
-
}
|
|
42209
|
-
getRichText() {
|
|
42210
|
-
return null;
|
|
42211
|
-
}
|
|
42212
|
-
getLinkTo() {
|
|
42213
|
-
return;
|
|
42214
|
-
}
|
|
42215
|
-
getExtension() {
|
|
42216
|
-
return this.extension;
|
|
42217
|
-
}
|
|
42218
|
-
download() {
|
|
42219
|
-
if (this.extension) {
|
|
42220
|
-
const linkElem = conf.documentFactory.createElement("a");
|
|
42221
|
-
linkElem.href = this.url;
|
|
42222
|
-
linkElem.setAttribute("download", `${this.board.getBoardId()}.${this.extension}`);
|
|
42223
|
-
linkElem.click();
|
|
42224
|
-
}
|
|
42225
|
-
}
|
|
42226
|
-
}
|
|
42227
|
-
// src/Items/Audio/AudioHelpers.ts
|
|
42228
|
-
var uploadAudioToStorage = async (hash, audioBlob, accessToken, boardId) => {
|
|
42229
|
-
return new Promise((resolve2, reject) => {
|
|
42230
|
-
fetch(`${window.location.origin}/api/v1/media/audio/${boardId}`, {
|
|
42231
|
-
method: "POST",
|
|
42232
|
-
headers: {
|
|
42233
|
-
"Content-Type": audioBlob.type,
|
|
42234
|
-
"x-audio-id": hash,
|
|
42235
|
-
Authorization: `Bearer ${accessToken}`
|
|
42236
|
-
},
|
|
42237
|
-
body: audioBlob
|
|
42238
|
-
}).then(async (response) => {
|
|
42239
|
-
if (response.status !== 200) {
|
|
42240
|
-
return catchErrorResponse(response, "audio");
|
|
42241
|
-
}
|
|
42242
|
-
return response.json();
|
|
42243
|
-
}).then((data) => {
|
|
42244
|
-
console.log(data);
|
|
42245
|
-
resolve2(data.src);
|
|
42246
|
-
}).catch((error) => {
|
|
42247
|
-
console.error("Media storage error:", error);
|
|
42248
|
-
reject(error);
|
|
42249
|
-
});
|
|
42250
|
-
});
|
|
42251
|
-
};
|
|
42252
|
-
var prepareAudio = (file, accessToken, boardId) => {
|
|
42253
|
-
return new Promise((resolve2, reject) => {
|
|
42254
|
-
const audio = document.createElement("audio");
|
|
42255
|
-
audio.src = URL.createObjectURL(file);
|
|
42256
|
-
audio.onloadedmetadata = () => {
|
|
42257
|
-
fileTosha256(file).then((hash) => {
|
|
42258
|
-
uploadAudioToStorage(hash, file, accessToken, boardId).then((url) => {
|
|
42259
|
-
resolve2(url);
|
|
42260
|
-
}).catch(reject);
|
|
42261
|
-
}).catch(() => {
|
|
42262
|
-
reject(new Error("Failed to generate hash"));
|
|
42263
|
-
});
|
|
42264
|
-
};
|
|
42265
|
-
audio.onerror = () => {
|
|
42266
|
-
reject(new Error("Failed to load audio"));
|
|
42267
|
-
};
|
|
42268
|
-
});
|
|
42269
|
-
};
|
|
42270
|
-
var calculateAudioPosition = (board, audioItem) => {
|
|
42271
|
-
const cameraMbr = board.camera.getMbr();
|
|
42272
|
-
const cameraWidth = cameraMbr.getWidth();
|
|
42273
|
-
const translateX = cameraMbr.left + cameraWidth * 0.34;
|
|
42274
|
-
const translateY = cameraMbr.getCenter().y - audioItem.getHeight() / 2;
|
|
42275
|
-
const scale = cameraWidth * 0.32 / audioItem.getWidth();
|
|
42276
|
-
return new Matrix2(translateX, translateY, scale, scale);
|
|
42277
|
-
};
|
|
42278
|
-
// src/Items/Placeholder/Placeholder.ts
|
|
42279
|
-
var PlaceholderImg = `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
42280
|
-
<path d="M5 11.1L7 9.1L12.5 14.6L16 11.1L19 14.1V5H5V11.1ZM4 3H20C20.2652 3 20.5196 3.10536 20.7071 3.29289C20.8946 3.48043 21 3.73478 21 4V20C21 20.2652 20.8946 20.5196 20.7071 20.7071C20.5196 20.8946 20.2652 21 20 21H4C3.73478 21 3.48043 20.8946 3.29289 20.7071C3.10536 20.5196 3 20.2652 3 20V4C3 3.73478 3.10536 3.48043 3.29289 3.29289C3.48043 3.10536 3.73478 3 4 3ZM15.5 10C15.1022 10 14.7206 9.84196 14.4393 9.56066C14.158 9.27936 14 8.89782 14 8.5C14 8.10218 14.158 7.72064 14.4393 7.43934C14.7206 7.15804 15.1022 7 15.5 7C15.8978 7 16.2794 7.15804 16.5607 7.43934C16.842 7.72064 17 8.10218 17 8.5C17 8.89782 16.842 9.27936 16.5607 9.56066C16.2794 9.84196 15.8978 10 15.5 10Z" fill="white" fill-opacity="0.6"/>
|
|
42281
|
-
</svg>`;
|
|
42282
|
-
|
|
42283
|
-
class Placeholder extends BaseItem {
|
|
42284
|
-
events;
|
|
42285
|
-
miroData;
|
|
42286
|
-
backgroundColor;
|
|
42287
|
-
icon;
|
|
42288
|
-
itemType = "Placeholder";
|
|
42289
|
-
shapeType = "Rectangle";
|
|
42290
|
-
parent = "Board";
|
|
42291
|
-
transformation;
|
|
42292
|
-
path = Shapes[this.shapeType].path.copy();
|
|
42293
|
-
mbr = Shapes[this.shapeType].path.getMbr().copy();
|
|
42294
|
-
subject = new Subject;
|
|
42295
|
-
transformationRenderBlock = undefined;
|
|
42296
|
-
iconImage;
|
|
42297
|
-
constructor(board, events, miroData, id = "", backgroundColor = "#E5E5EA", icon = PlaceholderImg?.toString() || "") {
|
|
42298
|
-
super(board, id);
|
|
42299
|
-
this.events = events;
|
|
42300
|
-
this.miroData = miroData;
|
|
42301
|
-
this.backgroundColor = backgroundColor;
|
|
42302
|
-
this.icon = icon;
|
|
42303
|
-
this.transformation = new Transformation(this.id, this.events);
|
|
42304
|
-
this.transformation.subject.subscribe((_subject) => {
|
|
42305
|
-
this.transformPath();
|
|
42306
|
-
this.updateMbr();
|
|
42307
|
-
this.subject.publish(this);
|
|
42308
|
-
});
|
|
42309
|
-
this.updateMbr();
|
|
42310
|
-
this.loadIconImage();
|
|
42311
|
-
}
|
|
42312
|
-
emit(operation) {
|
|
42313
|
-
if (this.events) {
|
|
42314
|
-
const command = new PlaceholderCommand([this], operation);
|
|
42315
|
-
command.apply();
|
|
42316
|
-
this.events.emit(operation, command);
|
|
42317
|
-
} else {
|
|
42318
|
-
this.apply(operation);
|
|
42319
|
-
}
|
|
42320
|
-
}
|
|
42321
|
-
serialize() {
|
|
42322
|
-
return {
|
|
42323
|
-
itemType: "Placeholder",
|
|
42324
|
-
backgroundColor: this.backgroundColor,
|
|
42325
|
-
icon: this.icon,
|
|
42326
|
-
transformation: this.transformation.serialize(),
|
|
42327
|
-
miroData: this.miroData
|
|
42328
|
-
};
|
|
42329
|
-
}
|
|
42330
|
-
deserialize(data) {
|
|
42331
|
-
this.initPath();
|
|
42332
|
-
this.backgroundColor = data.backgroundColor ?? this.backgroundColor;
|
|
42333
|
-
this.icon = data.icon ?? this.icon;
|
|
42334
|
-
this.miroData = data.miroData;
|
|
42335
|
-
if (data.transformation) {
|
|
42336
|
-
this.transformation.deserialize(data.transformation);
|
|
42337
|
-
this.transformPath();
|
|
42338
|
-
}
|
|
42339
|
-
this.subject.publish(this);
|
|
42340
|
-
return this;
|
|
42341
|
-
}
|
|
42342
|
-
setId(id) {
|
|
42343
|
-
this.id = id;
|
|
42344
|
-
this.transformation.setId(id);
|
|
42345
|
-
return this;
|
|
42346
|
-
}
|
|
42347
|
-
getId() {
|
|
42348
|
-
return this.id;
|
|
42349
|
-
}
|
|
42350
|
-
apply(op) {
|
|
42351
|
-
switch (op.class) {
|
|
42352
|
-
case "Placeholder":
|
|
42353
|
-
this.applyPlaceholder(op);
|
|
42354
|
-
this.updateMbr();
|
|
42355
|
-
break;
|
|
42356
|
-
case "Transformation":
|
|
42357
|
-
this.transformation.apply(op);
|
|
42358
|
-
break;
|
|
42359
|
-
default:
|
|
42360
|
-
return;
|
|
42361
|
-
}
|
|
42362
|
-
this.subject.publish(this);
|
|
42363
|
-
}
|
|
42364
|
-
applyPlaceholder(op) {
|
|
42365
|
-
switch (op.method) {
|
|
42366
|
-
case "setBackgroundColor":
|
|
42367
|
-
this.applyBackgroundColor(op.backgroundColor);
|
|
42368
|
-
break;
|
|
42369
|
-
case "setIcon":
|
|
42370
|
-
this.applyIcon(op.icon);
|
|
42371
|
-
break;
|
|
42372
|
-
case "setMiroData":
|
|
42373
|
-
this.applyMiroData(op.miroData);
|
|
42374
|
-
break;
|
|
42375
|
-
}
|
|
42376
|
-
}
|
|
42377
|
-
getBackgroundColor() {
|
|
42378
|
-
return this.backgroundColor;
|
|
42379
|
-
}
|
|
42380
|
-
applyBackgroundColor(backgroundColor) {
|
|
42381
|
-
this.backgroundColor = backgroundColor;
|
|
42382
|
-
this.path.setBackgroundColor(backgroundColor);
|
|
42383
|
-
}
|
|
42384
|
-
setBackgroundColor(backgroundColor) {
|
|
42385
|
-
this.emit({
|
|
42386
|
-
class: "Placeholder",
|
|
42387
|
-
method: "setBackgroundColor",
|
|
42388
|
-
item: [this.getId()],
|
|
42389
|
-
backgroundColor
|
|
42390
|
-
});
|
|
42391
|
-
}
|
|
42392
|
-
getIcon() {
|
|
42393
|
-
return this.icon;
|
|
42099
|
+
getIcon() {
|
|
42100
|
+
return this.icon;
|
|
42394
42101
|
}
|
|
42395
42102
|
applyIcon(icon) {
|
|
42396
42103
|
this.icon = icon;
|
|
@@ -42634,100 +42341,374 @@ class ImageItem extends BaseItem {
|
|
|
42634
42341
|
this.shootLoadCallbacks();
|
|
42635
42342
|
};
|
|
42636
42343
|
onError = (_error) => {
|
|
42637
|
-
this.image = getPlaceholderImage(this.board);
|
|
42344
|
+
this.image = getPlaceholderImage(this.board);
|
|
42345
|
+
this.updateMbr();
|
|
42346
|
+
this.subject.publish(this);
|
|
42347
|
+
this.shootLoadCallbacks();
|
|
42348
|
+
};
|
|
42349
|
+
onTransform = () => {
|
|
42350
|
+
this.updateMbr();
|
|
42351
|
+
this.subject.publish(this);
|
|
42352
|
+
};
|
|
42353
|
+
updateMbr() {
|
|
42354
|
+
const { translateX, translateY, scaleX, scaleY } = this.transformation.matrix;
|
|
42355
|
+
this.left = translateX;
|
|
42356
|
+
this.top = translateY;
|
|
42357
|
+
this.right = this.left + this.image.width * scaleX;
|
|
42358
|
+
this.bottom = this.top + this.image.height * scaleY;
|
|
42359
|
+
}
|
|
42360
|
+
doOnceBeforeOnLoad = (callback) => {
|
|
42361
|
+
this.loadCallbacks.push(callback);
|
|
42362
|
+
};
|
|
42363
|
+
doOnceOnLoad = (callback) => {
|
|
42364
|
+
this.loadCallbacks.push(callback);
|
|
42365
|
+
};
|
|
42366
|
+
setId(id) {
|
|
42367
|
+
this.id = id;
|
|
42368
|
+
this.transformation.setId(id);
|
|
42369
|
+
this.linkTo.setId(id);
|
|
42370
|
+
return this;
|
|
42371
|
+
}
|
|
42372
|
+
getId() {
|
|
42373
|
+
return this.id;
|
|
42374
|
+
}
|
|
42375
|
+
serialize() {
|
|
42376
|
+
return {
|
|
42377
|
+
itemType: "Image",
|
|
42378
|
+
storageLink: this.storageLink,
|
|
42379
|
+
imageDimension: this.imageDimension,
|
|
42380
|
+
transformation: this.transformation.serialize(),
|
|
42381
|
+
linkTo: this.linkTo.serialize()
|
|
42382
|
+
};
|
|
42383
|
+
}
|
|
42384
|
+
setCoordinates() {
|
|
42385
|
+
this.left = this.transformation.matrix.translateX;
|
|
42386
|
+
this.top = this.transformation.matrix.translateY;
|
|
42387
|
+
this.right = this.left + this.image.width * this.transformation.matrix.scaleX;
|
|
42388
|
+
this.bottom = this.top + this.image.height * this.transformation.matrix.scaleY;
|
|
42389
|
+
this.subject.publish(this);
|
|
42390
|
+
}
|
|
42391
|
+
shootBeforeLoadCallbacks() {
|
|
42392
|
+
while (this.beforeLoadCallbacks.length > 0) {
|
|
42393
|
+
this.beforeLoadCallbacks.shift()(this);
|
|
42394
|
+
}
|
|
42395
|
+
}
|
|
42396
|
+
shootLoadCallbacks() {
|
|
42397
|
+
while (this.loadCallbacks.length > 0) {
|
|
42398
|
+
this.loadCallbacks.shift()(this);
|
|
42399
|
+
}
|
|
42400
|
+
}
|
|
42401
|
+
deserialize(data) {
|
|
42402
|
+
if (data.transformation) {
|
|
42403
|
+
this.transformation.deserialize(data.transformation);
|
|
42404
|
+
}
|
|
42405
|
+
this.linkTo.deserialize(data.linkTo);
|
|
42406
|
+
this.image.onload = () => {
|
|
42407
|
+
this.setCoordinates();
|
|
42408
|
+
this.shootLoadCallbacks();
|
|
42409
|
+
};
|
|
42410
|
+
if (data.storageLink) {
|
|
42411
|
+
this.setStorageLink(data.storageLink);
|
|
42412
|
+
}
|
|
42413
|
+
if (this.image.src) {
|
|
42414
|
+
return this;
|
|
42415
|
+
}
|
|
42416
|
+
this.image = getPlaceholderImage(this.board, data.imageDimension);
|
|
42417
|
+
const storageImage = new Image;
|
|
42418
|
+
storageImage.onload = () => {
|
|
42419
|
+
this.image = storageImage;
|
|
42420
|
+
this.onLoad();
|
|
42421
|
+
};
|
|
42422
|
+
storageImage.onerror = this.onError;
|
|
42423
|
+
storageImage.src = this.storageLink;
|
|
42424
|
+
return this;
|
|
42425
|
+
}
|
|
42426
|
+
emit(operation) {
|
|
42427
|
+
if (this.events) {
|
|
42428
|
+
const command = new ImageCommand([this], operation);
|
|
42429
|
+
command.apply();
|
|
42430
|
+
this.events.emit(operation, command);
|
|
42431
|
+
} else {
|
|
42432
|
+
this.apply(operation);
|
|
42433
|
+
}
|
|
42434
|
+
}
|
|
42435
|
+
setDimensions(dim) {
|
|
42436
|
+
this.imageDimension = dim;
|
|
42437
|
+
}
|
|
42438
|
+
apply(op) {
|
|
42439
|
+
switch (op.class) {
|
|
42440
|
+
case "Transformation":
|
|
42441
|
+
this.transformation.apply(op);
|
|
42442
|
+
break;
|
|
42443
|
+
case "LinkTo":
|
|
42444
|
+
this.linkTo.apply(op);
|
|
42445
|
+
break;
|
|
42446
|
+
case "Image":
|
|
42447
|
+
if (op.data.base64) {
|
|
42448
|
+
this.image.src = op.data.base64;
|
|
42449
|
+
}
|
|
42450
|
+
this.setStorageLink(op.data.storageLink);
|
|
42451
|
+
this.setDimensions(op.data.imageDimension);
|
|
42452
|
+
this.subject.publish(this);
|
|
42453
|
+
break;
|
|
42454
|
+
}
|
|
42455
|
+
}
|
|
42456
|
+
render(context) {
|
|
42457
|
+
if (this.transformationRenderBlock) {
|
|
42458
|
+
return;
|
|
42459
|
+
}
|
|
42460
|
+
const ctx = context.ctx;
|
|
42461
|
+
ctx.save();
|
|
42462
|
+
this.transformation.matrix.applyToContext(ctx);
|
|
42463
|
+
ctx.drawImage(this.image, 0, 0);
|
|
42464
|
+
ctx.restore();
|
|
42465
|
+
if (this.getLinkTo()) {
|
|
42466
|
+
const { top, right } = this.getMbr();
|
|
42467
|
+
this.linkTo.render(context, top, right, this.board.camera.getScale());
|
|
42468
|
+
}
|
|
42469
|
+
}
|
|
42470
|
+
renderHTML(documentFactory) {
|
|
42471
|
+
const div = documentFactory.createElement("image-item");
|
|
42472
|
+
const { translateX, translateY, scaleX, scaleY } = this.transformation.matrix;
|
|
42473
|
+
const transform = `translate(${translateX}px, ${translateY}px) scale(${scaleX}, ${scaleY})`;
|
|
42474
|
+
div.style.backgroundImage = `url(${this.storageLink})`;
|
|
42475
|
+
div.id = this.getId();
|
|
42476
|
+
div.style.width = `${this.imageDimension.width}px`;
|
|
42477
|
+
div.style.height = `${this.imageDimension.height}px`;
|
|
42478
|
+
div.style.transformOrigin = "top left";
|
|
42479
|
+
div.style.transform = transform;
|
|
42480
|
+
div.style.position = "absolute";
|
|
42481
|
+
div.style.backgroundSize = "cover";
|
|
42482
|
+
div.setAttribute("data-link-to", this.linkTo.serialize() || "");
|
|
42483
|
+
if (this.getLinkTo()) {
|
|
42484
|
+
const linkElement = this.linkTo.renderHTML(documentFactory);
|
|
42485
|
+
scaleElementBy(linkElement, 1 / scaleX, 1 / scaleY);
|
|
42486
|
+
translateElementBy(linkElement, (this.getMbr().getWidth() - parseInt(linkElement.style.width)) / scaleX, 0);
|
|
42487
|
+
div.appendChild(linkElement);
|
|
42488
|
+
}
|
|
42489
|
+
return div;
|
|
42490
|
+
}
|
|
42491
|
+
getPath() {
|
|
42492
|
+
const { left, top, right, bottom } = this.getMbr();
|
|
42493
|
+
const leftTop = new Point(left, top);
|
|
42494
|
+
const rightTop = new Point(right, top);
|
|
42495
|
+
const rightBottom = new Point(right, bottom);
|
|
42496
|
+
const leftBottom = new Point(left, bottom);
|
|
42497
|
+
return new Path([
|
|
42498
|
+
new Line(leftTop, rightTop),
|
|
42499
|
+
new Line(rightTop, rightBottom),
|
|
42500
|
+
new Line(rightBottom, leftBottom),
|
|
42501
|
+
new Line(leftBottom, leftTop)
|
|
42502
|
+
], true);
|
|
42503
|
+
}
|
|
42504
|
+
getSnapAnchorPoints() {
|
|
42505
|
+
const mbr = this.getMbr();
|
|
42506
|
+
const width2 = mbr.getWidth();
|
|
42507
|
+
const height2 = mbr.getHeight();
|
|
42508
|
+
return [
|
|
42509
|
+
new Point(mbr.left + width2 / 2, mbr.top),
|
|
42510
|
+
new Point(mbr.left + width2 / 2, mbr.bottom),
|
|
42511
|
+
new Point(mbr.left, mbr.top + height2 / 2),
|
|
42512
|
+
new Point(mbr.right, mbr.top + height2 / 2)
|
|
42513
|
+
];
|
|
42514
|
+
}
|
|
42515
|
+
isClosed() {
|
|
42516
|
+
return true;
|
|
42517
|
+
}
|
|
42518
|
+
getRichText() {
|
|
42519
|
+
return null;
|
|
42520
|
+
}
|
|
42521
|
+
getLinkTo() {
|
|
42522
|
+
return this.linkTo.link;
|
|
42523
|
+
}
|
|
42524
|
+
download() {
|
|
42525
|
+
const linkElem = document.createElement("a");
|
|
42526
|
+
linkElem.href = this.storageLink;
|
|
42527
|
+
linkElem.setAttribute("download", "");
|
|
42528
|
+
linkElem.click();
|
|
42529
|
+
}
|
|
42530
|
+
onRemove() {
|
|
42531
|
+
const storageId = this.getStorageId();
|
|
42532
|
+
if (storageId) {
|
|
42533
|
+
deleteMedia([storageId], this.board.getBoardId());
|
|
42534
|
+
}
|
|
42535
|
+
super.onRemove();
|
|
42536
|
+
}
|
|
42537
|
+
}
|
|
42538
|
+
// src/Items/Audio/Audio.ts
|
|
42539
|
+
class AudioItem extends BaseItem {
|
|
42540
|
+
events;
|
|
42541
|
+
extension;
|
|
42542
|
+
itemType = "Audio";
|
|
42543
|
+
parent = "Board";
|
|
42544
|
+
transformation;
|
|
42545
|
+
linkTo;
|
|
42546
|
+
subject = new Subject;
|
|
42547
|
+
loadCallbacks = [];
|
|
42548
|
+
beforeLoadCallbacks = [];
|
|
42549
|
+
transformationRenderBlock = undefined;
|
|
42550
|
+
url = "";
|
|
42551
|
+
isPlaying = false;
|
|
42552
|
+
currentTime = 0;
|
|
42553
|
+
isStorageUrl = true;
|
|
42554
|
+
constructor(board, isStorageUrl, url, events, id = "", extension2) {
|
|
42555
|
+
super(board, id);
|
|
42556
|
+
this.events = events;
|
|
42557
|
+
this.extension = extension2;
|
|
42558
|
+
this.linkTo = new LinkTo(this.id, events);
|
|
42559
|
+
this.board = board;
|
|
42560
|
+
this.isStorageUrl = isStorageUrl;
|
|
42561
|
+
if (url) {
|
|
42562
|
+
this.applyUrl(url);
|
|
42563
|
+
}
|
|
42564
|
+
this.transformation = new Transformation(id, events);
|
|
42565
|
+
this.linkTo.subject.subscribe(() => {
|
|
42566
|
+
this.updateMbr();
|
|
42567
|
+
this.subject.publish(this);
|
|
42568
|
+
});
|
|
42569
|
+
this.transformation.subject.subscribe(this.onTransform);
|
|
42570
|
+
this.right = this.left + conf.AUDIO_DIMENSIONS.width;
|
|
42571
|
+
this.bottom = this.top + conf.AUDIO_DIMENSIONS.height;
|
|
42572
|
+
this.shouldUseCustomRender = true;
|
|
42573
|
+
}
|
|
42574
|
+
setCurrentTime(time) {
|
|
42575
|
+
this.currentTime = time;
|
|
42576
|
+
}
|
|
42577
|
+
getCurrentTime() {
|
|
42578
|
+
return this.currentTime;
|
|
42579
|
+
}
|
|
42580
|
+
getIsStorageUrl() {
|
|
42581
|
+
return this.isStorageUrl;
|
|
42582
|
+
}
|
|
42583
|
+
onTransform = () => {
|
|
42584
|
+
this.updateMbr();
|
|
42585
|
+
this.subject.publish(this);
|
|
42586
|
+
};
|
|
42587
|
+
doOnceBeforeOnLoad = (callback) => {
|
|
42588
|
+
this.loadCallbacks.push(callback);
|
|
42589
|
+
};
|
|
42590
|
+
doOnceOnLoad = (callback) => {
|
|
42591
|
+
this.loadCallbacks.push(callback);
|
|
42592
|
+
};
|
|
42593
|
+
setIsPlaying(isPlaying) {
|
|
42594
|
+
this.isPlaying = isPlaying;
|
|
42595
|
+
this.shouldRenderOutsideViewRect = isPlaying;
|
|
42596
|
+
this.subject.publish(this);
|
|
42597
|
+
}
|
|
42598
|
+
getIsPlaying() {
|
|
42599
|
+
return this.isPlaying;
|
|
42600
|
+
}
|
|
42601
|
+
applyUrl(url) {
|
|
42602
|
+
if (this.isStorageUrl) {
|
|
42603
|
+
try {
|
|
42604
|
+
const newUrl = new URL(url);
|
|
42605
|
+
this.url = `${window.location.origin}${newUrl.pathname}`;
|
|
42606
|
+
} catch (_) {}
|
|
42607
|
+
} else {
|
|
42608
|
+
this.url = url;
|
|
42609
|
+
}
|
|
42610
|
+
}
|
|
42611
|
+
setUrl(url) {
|
|
42612
|
+
this.emit({
|
|
42613
|
+
class: "Audio",
|
|
42614
|
+
method: "setUrl",
|
|
42615
|
+
item: [this.getId()],
|
|
42616
|
+
url
|
|
42617
|
+
});
|
|
42618
|
+
}
|
|
42619
|
+
getStorageId() {
|
|
42620
|
+
if (!this.isStorageUrl) {
|
|
42621
|
+
return;
|
|
42622
|
+
}
|
|
42623
|
+
return this.url.split("/").pop();
|
|
42624
|
+
}
|
|
42625
|
+
getUrl() {
|
|
42626
|
+
return this.url;
|
|
42627
|
+
}
|
|
42628
|
+
onLoad = async () => {
|
|
42629
|
+
this.shootBeforeLoadCallbacks();
|
|
42630
|
+
this.updateMbr();
|
|
42631
|
+
this.subject.publish(this);
|
|
42632
|
+
this.shootLoadCallbacks();
|
|
42633
|
+
};
|
|
42634
|
+
onError = (_error) => {
|
|
42638
42635
|
this.updateMbr();
|
|
42639
42636
|
this.subject.publish(this);
|
|
42640
42637
|
this.shootLoadCallbacks();
|
|
42641
42638
|
};
|
|
42642
|
-
onTransform = () => {
|
|
42643
|
-
this.updateMbr();
|
|
42644
|
-
this.subject.publish(this);
|
|
42645
|
-
};
|
|
42646
42639
|
updateMbr() {
|
|
42647
42640
|
const { translateX, translateY, scaleX, scaleY } = this.transformation.matrix;
|
|
42648
42641
|
this.left = translateX;
|
|
42649
42642
|
this.top = translateY;
|
|
42650
|
-
this.right = this.left +
|
|
42651
|
-
this.bottom = this.top +
|
|
42643
|
+
this.right = this.left + conf.AUDIO_DIMENSIONS.width * scaleX;
|
|
42644
|
+
this.bottom = this.top + conf.AUDIO_DIMENSIONS.height * scaleY;
|
|
42652
42645
|
}
|
|
42653
|
-
|
|
42654
|
-
this.
|
|
42655
|
-
|
|
42656
|
-
|
|
42657
|
-
|
|
42658
|
-
|
|
42659
|
-
|
|
42660
|
-
|
|
42661
|
-
|
|
42662
|
-
this.
|
|
42663
|
-
|
|
42646
|
+
render(context) {
|
|
42647
|
+
if (this.transformationRenderBlock) {
|
|
42648
|
+
return;
|
|
42649
|
+
}
|
|
42650
|
+
const ctx = context.ctx;
|
|
42651
|
+
const radius = 12 * this.transformation.getScale().x;
|
|
42652
|
+
ctx.save();
|
|
42653
|
+
ctx.globalCompositeOperation = "destination-out";
|
|
42654
|
+
ctx.beginPath();
|
|
42655
|
+
ctx.moveTo(this.left + radius, this.top);
|
|
42656
|
+
ctx.lineTo(this.left + this.getWidth() - radius, this.top);
|
|
42657
|
+
ctx.quadraticCurveTo(this.left + this.getWidth(), this.top, this.left + this.getWidth(), this.top + radius);
|
|
42658
|
+
ctx.lineTo(this.left + this.getWidth(), this.top + this.getHeight() - radius);
|
|
42659
|
+
ctx.quadraticCurveTo(this.left + this.getWidth(), this.top + this.getHeight(), this.left + this.getWidth() - radius, this.top + this.getHeight());
|
|
42660
|
+
ctx.lineTo(this.left + radius, this.top + this.getHeight());
|
|
42661
|
+
ctx.quadraticCurveTo(this.left, this.top + this.getHeight(), this.left, this.top + this.getHeight() - radius);
|
|
42662
|
+
ctx.lineTo(this.left, this.top + radius);
|
|
42663
|
+
ctx.quadraticCurveTo(this.left, this.top, this.left + radius, this.top);
|
|
42664
|
+
ctx.closePath();
|
|
42665
|
+
ctx.fill();
|
|
42666
|
+
ctx.restore();
|
|
42664
42667
|
}
|
|
42665
|
-
|
|
42666
|
-
|
|
42668
|
+
renderHTML(documentFactory) {
|
|
42669
|
+
const div = documentFactory.createElement("audio-item");
|
|
42670
|
+
const { translateX, translateY, scaleX, scaleY } = this.transformation.matrix;
|
|
42671
|
+
const transform = `translate(${translateX}px, ${translateY}px) scale(${scaleX}, ${scaleY})`;
|
|
42672
|
+
div.id = this.getId();
|
|
42673
|
+
div.style.width = `${conf.AUDIO_DIMENSIONS.width}px`;
|
|
42674
|
+
div.style.height = `${conf.AUDIO_DIMENSIONS.height}px`;
|
|
42675
|
+
div.style.transformOrigin = "top left";
|
|
42676
|
+
div.style.transform = transform;
|
|
42677
|
+
div.style.position = "absolute";
|
|
42678
|
+
div.setAttribute("audio-url", this.getUrl());
|
|
42679
|
+
if (this.extension) {
|
|
42680
|
+
div.setAttribute("extension", this.extension);
|
|
42681
|
+
}
|
|
42682
|
+
if (this.isStorageUrl) {
|
|
42683
|
+
div.setAttribute("is-storage-url", "true");
|
|
42684
|
+
}
|
|
42685
|
+
div.setAttribute("data-link-to", "");
|
|
42686
|
+
return div;
|
|
42667
42687
|
}
|
|
42668
42688
|
serialize() {
|
|
42669
42689
|
return {
|
|
42670
|
-
itemType: "
|
|
42671
|
-
|
|
42672
|
-
imageDimension: this.imageDimension,
|
|
42690
|
+
itemType: "Audio",
|
|
42691
|
+
url: this.url,
|
|
42673
42692
|
transformation: this.transformation.serialize(),
|
|
42674
|
-
|
|
42693
|
+
isStorageUrl: this.isStorageUrl,
|
|
42694
|
+
extension: this.extension
|
|
42675
42695
|
};
|
|
42676
42696
|
}
|
|
42677
|
-
setCoordinates() {
|
|
42678
|
-
this.left = this.transformation.matrix.translateX;
|
|
42679
|
-
this.top = this.transformation.matrix.translateY;
|
|
42680
|
-
this.right = this.left + this.image.width * this.transformation.matrix.scaleX;
|
|
42681
|
-
this.bottom = this.top + this.image.height * this.transformation.matrix.scaleY;
|
|
42682
|
-
this.subject.publish(this);
|
|
42683
|
-
}
|
|
42684
|
-
shootBeforeLoadCallbacks() {
|
|
42685
|
-
while (this.beforeLoadCallbacks.length > 0) {
|
|
42686
|
-
this.beforeLoadCallbacks.shift()(this);
|
|
42687
|
-
}
|
|
42688
|
-
}
|
|
42689
|
-
shootLoadCallbacks() {
|
|
42690
|
-
while (this.loadCallbacks.length > 0) {
|
|
42691
|
-
this.loadCallbacks.shift()(this);
|
|
42692
|
-
}
|
|
42693
|
-
}
|
|
42694
42697
|
deserialize(data) {
|
|
42698
|
+
if (data.isStorageUrl) {
|
|
42699
|
+
this.isStorageUrl = data.isStorageUrl;
|
|
42700
|
+
}
|
|
42695
42701
|
if (data.transformation) {
|
|
42696
42702
|
this.transformation.deserialize(data.transformation);
|
|
42697
42703
|
}
|
|
42698
|
-
|
|
42699
|
-
|
|
42700
|
-
this.setCoordinates();
|
|
42701
|
-
this.shootLoadCallbacks();
|
|
42702
|
-
};
|
|
42703
|
-
if (data.storageLink) {
|
|
42704
|
-
this.setStorageLink(data.storageLink);
|
|
42704
|
+
if (data.url) {
|
|
42705
|
+
this.setUrl(data.url);
|
|
42705
42706
|
}
|
|
42706
|
-
if (
|
|
42707
|
-
|
|
42707
|
+
if (data.extension) {
|
|
42708
|
+
this.extension = data.extension;
|
|
42708
42709
|
}
|
|
42709
|
-
this.image = getPlaceholderImage(this.board, data.imageDimension);
|
|
42710
|
-
const storageImage = new Image;
|
|
42711
|
-
storageImage.onload = () => {
|
|
42712
|
-
this.image = storageImage;
|
|
42713
|
-
this.onLoad();
|
|
42714
|
-
};
|
|
42715
|
-
storageImage.onerror = this.onError;
|
|
42716
|
-
storageImage.src = this.storageLink;
|
|
42717
42710
|
return this;
|
|
42718
42711
|
}
|
|
42719
|
-
emit(operation) {
|
|
42720
|
-
if (this.events) {
|
|
42721
|
-
const command = new ImageCommand([this], operation);
|
|
42722
|
-
command.apply();
|
|
42723
|
-
this.events.emit(operation, command);
|
|
42724
|
-
} else {
|
|
42725
|
-
this.apply(operation);
|
|
42726
|
-
}
|
|
42727
|
-
}
|
|
42728
|
-
setDimensions(dim) {
|
|
42729
|
-
this.imageDimension = dim;
|
|
42730
|
-
}
|
|
42731
42712
|
apply(op) {
|
|
42732
42713
|
switch (op.class) {
|
|
42733
42714
|
case "Transformation":
|
|
@@ -42736,50 +42717,40 @@ class ImageItem extends BaseItem {
|
|
|
42736
42717
|
case "LinkTo":
|
|
42737
42718
|
this.linkTo.apply(op);
|
|
42738
42719
|
break;
|
|
42739
|
-
case "
|
|
42740
|
-
if (op.
|
|
42741
|
-
this.
|
|
42720
|
+
case "Audio":
|
|
42721
|
+
if (op.method === "setUrl") {
|
|
42722
|
+
this.applyUrl(op.url);
|
|
42742
42723
|
}
|
|
42743
|
-
this.setStorageLink(op.data.storageLink);
|
|
42744
|
-
this.setDimensions(op.data.imageDimension);
|
|
42745
42724
|
this.subject.publish(this);
|
|
42746
42725
|
break;
|
|
42747
42726
|
}
|
|
42748
42727
|
}
|
|
42749
|
-
|
|
42750
|
-
if (this.
|
|
42751
|
-
|
|
42728
|
+
emit(operation) {
|
|
42729
|
+
if (this.events) {
|
|
42730
|
+
const command = new AudioCommand([this], operation);
|
|
42731
|
+
command.apply();
|
|
42732
|
+
this.events.emit(operation, command);
|
|
42733
|
+
} else {
|
|
42734
|
+
this.apply(operation);
|
|
42752
42735
|
}
|
|
42753
|
-
|
|
42754
|
-
|
|
42755
|
-
this.
|
|
42756
|
-
|
|
42757
|
-
|
|
42758
|
-
|
|
42759
|
-
|
|
42760
|
-
|
|
42736
|
+
}
|
|
42737
|
+
setId(id) {
|
|
42738
|
+
this.id = id;
|
|
42739
|
+
this.transformation.setId(id);
|
|
42740
|
+
return this;
|
|
42741
|
+
}
|
|
42742
|
+
getId() {
|
|
42743
|
+
return this.id;
|
|
42744
|
+
}
|
|
42745
|
+
shootLoadCallbacks() {
|
|
42746
|
+
while (this.loadCallbacks.length > 0) {
|
|
42747
|
+
this.loadCallbacks.shift()(this);
|
|
42761
42748
|
}
|
|
42762
42749
|
}
|
|
42763
|
-
|
|
42764
|
-
|
|
42765
|
-
|
|
42766
|
-
const transform = `translate(${translateX}px, ${translateY}px) scale(${scaleX}, ${scaleY})`;
|
|
42767
|
-
div.style.backgroundImage = `url(${this.storageLink})`;
|
|
42768
|
-
div.id = this.getId();
|
|
42769
|
-
div.style.width = `${this.imageDimension.width}px`;
|
|
42770
|
-
div.style.height = `${this.imageDimension.height}px`;
|
|
42771
|
-
div.style.transformOrigin = "top left";
|
|
42772
|
-
div.style.transform = transform;
|
|
42773
|
-
div.style.position = "absolute";
|
|
42774
|
-
div.style.backgroundSize = "cover";
|
|
42775
|
-
div.setAttribute("data-link-to", this.linkTo.serialize() || "");
|
|
42776
|
-
if (this.getLinkTo()) {
|
|
42777
|
-
const linkElement = this.linkTo.renderHTML(documentFactory);
|
|
42778
|
-
scaleElementBy(linkElement, 1 / scaleX, 1 / scaleY);
|
|
42779
|
-
translateElementBy(linkElement, (this.getMbr().getWidth() - parseInt(linkElement.style.width)) / scaleX, 0);
|
|
42780
|
-
div.appendChild(linkElement);
|
|
42750
|
+
shootBeforeLoadCallbacks() {
|
|
42751
|
+
while (this.beforeLoadCallbacks.length > 0) {
|
|
42752
|
+
this.beforeLoadCallbacks.shift()(this);
|
|
42781
42753
|
}
|
|
42782
|
-
return div;
|
|
42783
42754
|
}
|
|
42784
42755
|
getPath() {
|
|
42785
42756
|
const { left, top, right, bottom } = this.getMbr();
|
|
@@ -42812,15 +42783,78 @@ class ImageItem extends BaseItem {
|
|
|
42812
42783
|
return null;
|
|
42813
42784
|
}
|
|
42814
42785
|
getLinkTo() {
|
|
42815
|
-
return
|
|
42786
|
+
return;
|
|
42787
|
+
}
|
|
42788
|
+
getExtension() {
|
|
42789
|
+
return this.extension;
|
|
42816
42790
|
}
|
|
42817
42791
|
download() {
|
|
42818
|
-
|
|
42819
|
-
|
|
42820
|
-
|
|
42821
|
-
|
|
42792
|
+
if (this.extension) {
|
|
42793
|
+
const linkElem = conf.documentFactory.createElement("a");
|
|
42794
|
+
linkElem.href = this.url;
|
|
42795
|
+
linkElem.setAttribute("download", `${this.board.getBoardId()}.${this.extension}`);
|
|
42796
|
+
linkElem.click();
|
|
42797
|
+
}
|
|
42798
|
+
}
|
|
42799
|
+
onRemove() {
|
|
42800
|
+
const storageId = this.getStorageId();
|
|
42801
|
+
if (storageId) {
|
|
42802
|
+
deleteMedia([storageId], this.board.getBoardId());
|
|
42803
|
+
}
|
|
42804
|
+
super.onRemove();
|
|
42822
42805
|
}
|
|
42823
42806
|
}
|
|
42807
|
+
// src/Items/Audio/AudioHelpers.ts
|
|
42808
|
+
var uploadAudioToStorage = async (hash, audioBlob, accessToken, boardId) => {
|
|
42809
|
+
return new Promise((resolve2, reject) => {
|
|
42810
|
+
fetch(`${window.location.origin}/api/v1/media/audio/${boardId}`, {
|
|
42811
|
+
method: "POST",
|
|
42812
|
+
headers: {
|
|
42813
|
+
"Content-Type": audioBlob.type,
|
|
42814
|
+
"x-audio-id": hash,
|
|
42815
|
+
Authorization: `Bearer ${accessToken}`
|
|
42816
|
+
},
|
|
42817
|
+
body: audioBlob
|
|
42818
|
+
}).then(async (response) => {
|
|
42819
|
+
if (response.status !== 200) {
|
|
42820
|
+
return catchErrorResponse(response, "audio");
|
|
42821
|
+
}
|
|
42822
|
+
return response.json();
|
|
42823
|
+
}).then((data) => {
|
|
42824
|
+
console.log(data);
|
|
42825
|
+
resolve2(data.src);
|
|
42826
|
+
}).catch((error) => {
|
|
42827
|
+
console.error("Media storage error:", error);
|
|
42828
|
+
reject(error);
|
|
42829
|
+
});
|
|
42830
|
+
});
|
|
42831
|
+
};
|
|
42832
|
+
var prepareAudio = (file, accessToken, boardId) => {
|
|
42833
|
+
return new Promise((resolve2, reject) => {
|
|
42834
|
+
const audio = document.createElement("audio");
|
|
42835
|
+
audio.src = URL.createObjectURL(file);
|
|
42836
|
+
audio.onloadedmetadata = () => {
|
|
42837
|
+
fileTosha256(file).then((hash) => {
|
|
42838
|
+
uploadAudioToStorage(hash, file, accessToken, boardId).then((url) => {
|
|
42839
|
+
resolve2(url);
|
|
42840
|
+
}).catch(reject);
|
|
42841
|
+
}).catch(() => {
|
|
42842
|
+
reject(new Error("Failed to generate hash"));
|
|
42843
|
+
});
|
|
42844
|
+
};
|
|
42845
|
+
audio.onerror = () => {
|
|
42846
|
+
reject(new Error("Failed to load audio"));
|
|
42847
|
+
};
|
|
42848
|
+
});
|
|
42849
|
+
};
|
|
42850
|
+
var calculateAudioPosition = (board, audioItem) => {
|
|
42851
|
+
const cameraMbr = board.camera.getMbr();
|
|
42852
|
+
const cameraWidth = cameraMbr.getWidth();
|
|
42853
|
+
const translateX = cameraMbr.left + cameraWidth * 0.34;
|
|
42854
|
+
const translateY = cameraMbr.getCenter().y - audioItem.getHeight() / 2;
|
|
42855
|
+
const scale = cameraWidth * 0.32 / audioItem.getWidth();
|
|
42856
|
+
return new Matrix2(translateX, translateY, scale, scale);
|
|
42857
|
+
};
|
|
42824
42858
|
// src/isSafari.ts
|
|
42825
42859
|
function isSafari() {
|
|
42826
42860
|
if (typeof navigator === "undefined") {
|
|
@@ -54451,14 +54485,15 @@ class Board {
|
|
|
54451
54485
|
}
|
|
54452
54486
|
applyAddItems(op) {
|
|
54453
54487
|
if (Array.isArray(op.item)) {
|
|
54488
|
+
const data = op.data;
|
|
54454
54489
|
const items = op.item.map((item2) => {
|
|
54455
|
-
const created = this.createItem(item2,
|
|
54490
|
+
const created = this.createItem(item2, data[item2]);
|
|
54456
54491
|
this.index.insert(created);
|
|
54457
54492
|
return created;
|
|
54458
54493
|
});
|
|
54459
54494
|
items.forEach((item2) => {
|
|
54460
|
-
if (item2
|
|
54461
|
-
const connectorData =
|
|
54495
|
+
if (item2 instanceof Connector2 && data[item2.getId()]) {
|
|
54496
|
+
const connectorData = data[item2.getId()];
|
|
54462
54497
|
item2.applyStartPoint(connectorData.startPoint);
|
|
54463
54498
|
item2.applyEndPoint(connectorData.endPoint);
|
|
54464
54499
|
}
|
|
@@ -54487,7 +54522,7 @@ class Board {
|
|
|
54487
54522
|
this.findItemAndApply(op.item, (item) => {
|
|
54488
54523
|
this.index.remove(item);
|
|
54489
54524
|
this.selection.remove(item);
|
|
54490
|
-
if (item
|
|
54525
|
+
if (item instanceof Connector2) {
|
|
54491
54526
|
item.clearObservedItems();
|
|
54492
54527
|
}
|
|
54493
54528
|
removedItems.push(item);
|
|
@@ -54495,7 +54530,7 @@ class Board {
|
|
|
54495
54530
|
}
|
|
54496
54531
|
applyRemoveLockedGroupOperation(op) {
|
|
54497
54532
|
const item = this.index.getById(op.item[0]);
|
|
54498
|
-
if (!item || item
|
|
54533
|
+
if (!item || !(item instanceof Group)) {
|
|
54499
54534
|
return;
|
|
54500
54535
|
}
|
|
54501
54536
|
item.getChildren().forEach((item2) => {
|
|
@@ -54511,9 +54546,11 @@ class Board {
|
|
|
54511
54546
|
});
|
|
54512
54547
|
}
|
|
54513
54548
|
applyItemOperation(op) {
|
|
54514
|
-
|
|
54515
|
-
|
|
54516
|
-
|
|
54549
|
+
if ("item" in op) {
|
|
54550
|
+
this.findItemAndApply(op.item, (item) => {
|
|
54551
|
+
item.apply(op);
|
|
54552
|
+
});
|
|
54553
|
+
}
|
|
54517
54554
|
}
|
|
54518
54555
|
findItemAndApply(item, apply) {
|
|
54519
54556
|
if (Array.isArray(item)) {
|
|
@@ -54602,9 +54639,8 @@ class Board {
|
|
|
54602
54639
|
if (withConnectors) {
|
|
54603
54640
|
connectors = this.items.getLinkedConnectorsById(item.getId()).map((connector) => connector.getId());
|
|
54604
54641
|
}
|
|
54605
|
-
|
|
54606
|
-
|
|
54607
|
-
deleteMedia([item.getStorageId()], this.boardId);
|
|
54642
|
+
if ("onRemove" in item) {
|
|
54643
|
+
item.onRemove();
|
|
54608
54644
|
}
|
|
54609
54645
|
this.emit({
|
|
54610
54646
|
class: "Board",
|