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/browser.js
CHANGED
|
@@ -33402,6 +33402,7 @@ class BaseItem extends Mbr {
|
|
|
33402
33402
|
transformationRenderBlock = undefined;
|
|
33403
33403
|
board;
|
|
33404
33404
|
id;
|
|
33405
|
+
onRemoveCallbacks = [];
|
|
33405
33406
|
shouldUseCustomRender = false;
|
|
33406
33407
|
shouldRenderOutsideViewRect = true;
|
|
33407
33408
|
itemType = "";
|
|
@@ -33479,6 +33480,12 @@ class BaseItem extends Mbr {
|
|
|
33479
33480
|
break;
|
|
33480
33481
|
}
|
|
33481
33482
|
}
|
|
33483
|
+
addOnRemoveCallback(cb) {
|
|
33484
|
+
this.onRemoveCallbacks.push(cb);
|
|
33485
|
+
}
|
|
33486
|
+
onRemove() {
|
|
33487
|
+
this.onRemoveCallbacks.forEach((cb) => cb());
|
|
33488
|
+
}
|
|
33482
33489
|
render(context) {}
|
|
33483
33490
|
renderHTML(documentFactory) {
|
|
33484
33491
|
return documentFactory.createElement("div");
|
|
@@ -38735,6 +38742,9 @@ class VideoItem extends BaseItem {
|
|
|
38735
38742
|
this.loadCallbacks.push(callback);
|
|
38736
38743
|
};
|
|
38737
38744
|
getStorageId() {
|
|
38745
|
+
if (!this.isStorageUrl) {
|
|
38746
|
+
return;
|
|
38747
|
+
}
|
|
38738
38748
|
return this.url.split("/").pop();
|
|
38739
38749
|
}
|
|
38740
38750
|
getIsStorageUrl() {
|
|
@@ -39007,6 +39017,13 @@ class VideoItem extends BaseItem {
|
|
|
39007
39017
|
linkElem.click();
|
|
39008
39018
|
}
|
|
39009
39019
|
}
|
|
39020
|
+
onRemove() {
|
|
39021
|
+
const storageId = this.getStorageId();
|
|
39022
|
+
if (storageId) {
|
|
39023
|
+
deleteMedia([storageId], this.board.getBoardId());
|
|
39024
|
+
}
|
|
39025
|
+
super.onRemove();
|
|
39026
|
+
}
|
|
39010
39027
|
}
|
|
39011
39028
|
// src/Items/Image/calculatePosition.ts
|
|
39012
39029
|
function calculatePosition(boardImage, board) {
|
|
@@ -39437,432 +39454,122 @@ var captureFrame = (frameTime, video) => {
|
|
|
39437
39454
|
return null;
|
|
39438
39455
|
}
|
|
39439
39456
|
};
|
|
39440
|
-
// src/Items/
|
|
39441
|
-
|
|
39457
|
+
// src/Items/Placeholder/Placeholder.ts
|
|
39458
|
+
var PlaceholderImg = `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
39459
|
+
<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"/>
|
|
39460
|
+
</svg>`;
|
|
39461
|
+
|
|
39462
|
+
class Placeholder extends BaseItem {
|
|
39442
39463
|
events;
|
|
39443
|
-
|
|
39444
|
-
|
|
39464
|
+
miroData;
|
|
39465
|
+
backgroundColor;
|
|
39466
|
+
icon;
|
|
39467
|
+
itemType = "Placeholder";
|
|
39468
|
+
shapeType = "Rectangle";
|
|
39445
39469
|
parent = "Board";
|
|
39446
39470
|
transformation;
|
|
39447
|
-
|
|
39471
|
+
path = Shapes[this.shapeType].path.copy();
|
|
39472
|
+
mbr = Shapes[this.shapeType].path.getMbr().copy();
|
|
39448
39473
|
subject = new Subject;
|
|
39449
|
-
loadCallbacks = [];
|
|
39450
|
-
beforeLoadCallbacks = [];
|
|
39451
39474
|
transformationRenderBlock = undefined;
|
|
39452
|
-
|
|
39453
|
-
|
|
39454
|
-
currentTime = 0;
|
|
39455
|
-
isStorageUrl = true;
|
|
39456
|
-
constructor(board, isStorageUrl, url, events, id = "", extension2) {
|
|
39475
|
+
iconImage;
|
|
39476
|
+
constructor(board, events, miroData, id = "", backgroundColor = "#E5E5EA", icon = PlaceholderImg?.toString() || "") {
|
|
39457
39477
|
super(board, id);
|
|
39458
39478
|
this.events = events;
|
|
39459
|
-
this.
|
|
39460
|
-
this.
|
|
39461
|
-
this.
|
|
39462
|
-
this.
|
|
39463
|
-
|
|
39464
|
-
this.
|
|
39465
|
-
}
|
|
39466
|
-
this.transformation = new Transformation(id, events);
|
|
39467
|
-
this.linkTo.subject.subscribe(() => {
|
|
39479
|
+
this.miroData = miroData;
|
|
39480
|
+
this.backgroundColor = backgroundColor;
|
|
39481
|
+
this.icon = icon;
|
|
39482
|
+
this.transformation = new Transformation(this.id, this.events);
|
|
39483
|
+
this.transformation.subject.subscribe((_subject) => {
|
|
39484
|
+
this.transformPath();
|
|
39468
39485
|
this.updateMbr();
|
|
39469
39486
|
this.subject.publish(this);
|
|
39470
39487
|
});
|
|
39471
|
-
this.transformation.subject.subscribe(this.onTransform);
|
|
39472
|
-
this.right = this.left + conf.AUDIO_DIMENSIONS.width;
|
|
39473
|
-
this.bottom = this.top + conf.AUDIO_DIMENSIONS.height;
|
|
39474
|
-
this.shouldUseCustomRender = true;
|
|
39475
|
-
}
|
|
39476
|
-
setCurrentTime(time) {
|
|
39477
|
-
this.currentTime = time;
|
|
39478
|
-
}
|
|
39479
|
-
getCurrentTime() {
|
|
39480
|
-
return this.currentTime;
|
|
39481
|
-
}
|
|
39482
|
-
getIsStorageUrl() {
|
|
39483
|
-
return this.isStorageUrl;
|
|
39484
|
-
}
|
|
39485
|
-
onTransform = () => {
|
|
39486
39488
|
this.updateMbr();
|
|
39487
|
-
this.
|
|
39488
|
-
};
|
|
39489
|
-
doOnceBeforeOnLoad = (callback) => {
|
|
39490
|
-
this.loadCallbacks.push(callback);
|
|
39491
|
-
};
|
|
39492
|
-
doOnceOnLoad = (callback) => {
|
|
39493
|
-
this.loadCallbacks.push(callback);
|
|
39494
|
-
};
|
|
39495
|
-
setIsPlaying(isPlaying) {
|
|
39496
|
-
this.isPlaying = isPlaying;
|
|
39497
|
-
this.shouldRenderOutsideViewRect = isPlaying;
|
|
39498
|
-
this.subject.publish(this);
|
|
39499
|
-
}
|
|
39500
|
-
getIsPlaying() {
|
|
39501
|
-
return this.isPlaying;
|
|
39489
|
+
this.loadIconImage();
|
|
39502
39490
|
}
|
|
39503
|
-
|
|
39504
|
-
if (this.
|
|
39505
|
-
|
|
39506
|
-
|
|
39507
|
-
|
|
39508
|
-
} catch (_) {}
|
|
39491
|
+
emit(operation) {
|
|
39492
|
+
if (this.events) {
|
|
39493
|
+
const command = new PlaceholderCommand([this], operation);
|
|
39494
|
+
command.apply();
|
|
39495
|
+
this.events.emit(operation, command);
|
|
39509
39496
|
} else {
|
|
39510
|
-
this.
|
|
39511
|
-
}
|
|
39512
|
-
}
|
|
39513
|
-
setUrl(url) {
|
|
39514
|
-
this.emit({
|
|
39515
|
-
class: "Audio",
|
|
39516
|
-
method: "setUrl",
|
|
39517
|
-
item: [this.getId()],
|
|
39518
|
-
url
|
|
39519
|
-
});
|
|
39520
|
-
}
|
|
39521
|
-
getStorageId() {
|
|
39522
|
-
return this.url.split("/").pop();
|
|
39523
|
-
}
|
|
39524
|
-
getUrl() {
|
|
39525
|
-
return this.url;
|
|
39526
|
-
}
|
|
39527
|
-
onLoad = async () => {
|
|
39528
|
-
this.shootBeforeLoadCallbacks();
|
|
39529
|
-
this.updateMbr();
|
|
39530
|
-
this.subject.publish(this);
|
|
39531
|
-
this.shootLoadCallbacks();
|
|
39532
|
-
};
|
|
39533
|
-
onError = (_error) => {
|
|
39534
|
-
this.updateMbr();
|
|
39535
|
-
this.subject.publish(this);
|
|
39536
|
-
this.shootLoadCallbacks();
|
|
39537
|
-
};
|
|
39538
|
-
updateMbr() {
|
|
39539
|
-
const { translateX, translateY, scaleX, scaleY } = this.transformation.matrix;
|
|
39540
|
-
this.left = translateX;
|
|
39541
|
-
this.top = translateY;
|
|
39542
|
-
this.right = this.left + conf.AUDIO_DIMENSIONS.width * scaleX;
|
|
39543
|
-
this.bottom = this.top + conf.AUDIO_DIMENSIONS.height * scaleY;
|
|
39544
|
-
}
|
|
39545
|
-
render(context) {
|
|
39546
|
-
if (this.transformationRenderBlock) {
|
|
39547
|
-
return;
|
|
39548
|
-
}
|
|
39549
|
-
const ctx = context.ctx;
|
|
39550
|
-
const radius = 12 * this.transformation.getScale().x;
|
|
39551
|
-
ctx.save();
|
|
39552
|
-
ctx.globalCompositeOperation = "destination-out";
|
|
39553
|
-
ctx.beginPath();
|
|
39554
|
-
ctx.moveTo(this.left + radius, this.top);
|
|
39555
|
-
ctx.lineTo(this.left + this.getWidth() - radius, this.top);
|
|
39556
|
-
ctx.quadraticCurveTo(this.left + this.getWidth(), this.top, this.left + this.getWidth(), this.top + radius);
|
|
39557
|
-
ctx.lineTo(this.left + this.getWidth(), this.top + this.getHeight() - radius);
|
|
39558
|
-
ctx.quadraticCurveTo(this.left + this.getWidth(), this.top + this.getHeight(), this.left + this.getWidth() - radius, this.top + this.getHeight());
|
|
39559
|
-
ctx.lineTo(this.left + radius, this.top + this.getHeight());
|
|
39560
|
-
ctx.quadraticCurveTo(this.left, this.top + this.getHeight(), this.left, this.top + this.getHeight() - radius);
|
|
39561
|
-
ctx.lineTo(this.left, this.top + radius);
|
|
39562
|
-
ctx.quadraticCurveTo(this.left, this.top, this.left + radius, this.top);
|
|
39563
|
-
ctx.closePath();
|
|
39564
|
-
ctx.fill();
|
|
39565
|
-
ctx.restore();
|
|
39566
|
-
}
|
|
39567
|
-
renderHTML(documentFactory) {
|
|
39568
|
-
const div = documentFactory.createElement("audio-item");
|
|
39569
|
-
const { translateX, translateY, scaleX, scaleY } = this.transformation.matrix;
|
|
39570
|
-
const transform = `translate(${translateX}px, ${translateY}px) scale(${scaleX}, ${scaleY})`;
|
|
39571
|
-
div.id = this.getId();
|
|
39572
|
-
div.style.width = `${conf.AUDIO_DIMENSIONS.width}px`;
|
|
39573
|
-
div.style.height = `${conf.AUDIO_DIMENSIONS.height}px`;
|
|
39574
|
-
div.style.transformOrigin = "top left";
|
|
39575
|
-
div.style.transform = transform;
|
|
39576
|
-
div.style.position = "absolute";
|
|
39577
|
-
div.setAttribute("audio-url", this.getUrl());
|
|
39578
|
-
if (this.extension) {
|
|
39579
|
-
div.setAttribute("extension", this.extension);
|
|
39580
|
-
}
|
|
39581
|
-
if (this.isStorageUrl) {
|
|
39582
|
-
div.setAttribute("is-storage-url", "true");
|
|
39497
|
+
this.apply(operation);
|
|
39583
39498
|
}
|
|
39584
|
-
div.setAttribute("data-link-to", "");
|
|
39585
|
-
return div;
|
|
39586
39499
|
}
|
|
39587
39500
|
serialize() {
|
|
39588
39501
|
return {
|
|
39589
|
-
itemType: "
|
|
39590
|
-
|
|
39502
|
+
itemType: "Placeholder",
|
|
39503
|
+
backgroundColor: this.backgroundColor,
|
|
39504
|
+
icon: this.icon,
|
|
39591
39505
|
transformation: this.transformation.serialize(),
|
|
39592
|
-
|
|
39593
|
-
extension: this.extension
|
|
39506
|
+
miroData: this.miroData
|
|
39594
39507
|
};
|
|
39595
39508
|
}
|
|
39596
39509
|
deserialize(data) {
|
|
39597
|
-
|
|
39598
|
-
|
|
39599
|
-
|
|
39510
|
+
this.initPath();
|
|
39511
|
+
this.backgroundColor = data.backgroundColor ?? this.backgroundColor;
|
|
39512
|
+
this.icon = data.icon ?? this.icon;
|
|
39513
|
+
this.miroData = data.miroData;
|
|
39600
39514
|
if (data.transformation) {
|
|
39601
39515
|
this.transformation.deserialize(data.transformation);
|
|
39516
|
+
this.transformPath();
|
|
39602
39517
|
}
|
|
39603
|
-
|
|
39604
|
-
|
|
39605
|
-
|
|
39606
|
-
|
|
39607
|
-
|
|
39608
|
-
|
|
39518
|
+
this.subject.publish(this);
|
|
39519
|
+
return this;
|
|
39520
|
+
}
|
|
39521
|
+
setId(id) {
|
|
39522
|
+
this.id = id;
|
|
39523
|
+
this.transformation.setId(id);
|
|
39609
39524
|
return this;
|
|
39610
39525
|
}
|
|
39526
|
+
getId() {
|
|
39527
|
+
return this.id;
|
|
39528
|
+
}
|
|
39611
39529
|
apply(op) {
|
|
39612
39530
|
switch (op.class) {
|
|
39531
|
+
case "Placeholder":
|
|
39532
|
+
this.applyPlaceholder(op);
|
|
39533
|
+
this.updateMbr();
|
|
39534
|
+
break;
|
|
39613
39535
|
case "Transformation":
|
|
39614
39536
|
this.transformation.apply(op);
|
|
39615
39537
|
break;
|
|
39616
|
-
|
|
39617
|
-
|
|
39538
|
+
default:
|
|
39539
|
+
return;
|
|
39540
|
+
}
|
|
39541
|
+
this.subject.publish(this);
|
|
39542
|
+
}
|
|
39543
|
+
applyPlaceholder(op) {
|
|
39544
|
+
switch (op.method) {
|
|
39545
|
+
case "setBackgroundColor":
|
|
39546
|
+
this.applyBackgroundColor(op.backgroundColor);
|
|
39618
39547
|
break;
|
|
39619
|
-
case "
|
|
39620
|
-
|
|
39621
|
-
|
|
39622
|
-
|
|
39623
|
-
this.
|
|
39548
|
+
case "setIcon":
|
|
39549
|
+
this.applyIcon(op.icon);
|
|
39550
|
+
break;
|
|
39551
|
+
case "setMiroData":
|
|
39552
|
+
this.applyMiroData(op.miroData);
|
|
39624
39553
|
break;
|
|
39625
39554
|
}
|
|
39626
39555
|
}
|
|
39627
|
-
|
|
39628
|
-
|
|
39629
|
-
const command = new AudioCommand([this], operation);
|
|
39630
|
-
command.apply();
|
|
39631
|
-
this.events.emit(operation, command);
|
|
39632
|
-
} else {
|
|
39633
|
-
this.apply(operation);
|
|
39634
|
-
}
|
|
39556
|
+
getBackgroundColor() {
|
|
39557
|
+
return this.backgroundColor;
|
|
39635
39558
|
}
|
|
39636
|
-
|
|
39637
|
-
this.
|
|
39638
|
-
this.
|
|
39639
|
-
return this;
|
|
39559
|
+
applyBackgroundColor(backgroundColor) {
|
|
39560
|
+
this.backgroundColor = backgroundColor;
|
|
39561
|
+
this.path.setBackgroundColor(backgroundColor);
|
|
39640
39562
|
}
|
|
39641
|
-
|
|
39642
|
-
|
|
39563
|
+
setBackgroundColor(backgroundColor) {
|
|
39564
|
+
this.emit({
|
|
39565
|
+
class: "Placeholder",
|
|
39566
|
+
method: "setBackgroundColor",
|
|
39567
|
+
item: [this.getId()],
|
|
39568
|
+
backgroundColor
|
|
39569
|
+
});
|
|
39643
39570
|
}
|
|
39644
|
-
|
|
39645
|
-
|
|
39646
|
-
this.loadCallbacks.shift()(this);
|
|
39647
|
-
}
|
|
39648
|
-
}
|
|
39649
|
-
shootBeforeLoadCallbacks() {
|
|
39650
|
-
while (this.beforeLoadCallbacks.length > 0) {
|
|
39651
|
-
this.beforeLoadCallbacks.shift()(this);
|
|
39652
|
-
}
|
|
39653
|
-
}
|
|
39654
|
-
getPath() {
|
|
39655
|
-
const { left, top, right, bottom } = this.getMbr();
|
|
39656
|
-
const leftTop = new Point(left, top);
|
|
39657
|
-
const rightTop = new Point(right, top);
|
|
39658
|
-
const rightBottom = new Point(right, bottom);
|
|
39659
|
-
const leftBottom = new Point(left, bottom);
|
|
39660
|
-
return new Path([
|
|
39661
|
-
new Line(leftTop, rightTop),
|
|
39662
|
-
new Line(rightTop, rightBottom),
|
|
39663
|
-
new Line(rightBottom, leftBottom),
|
|
39664
|
-
new Line(leftBottom, leftTop)
|
|
39665
|
-
], true);
|
|
39666
|
-
}
|
|
39667
|
-
getSnapAnchorPoints() {
|
|
39668
|
-
const mbr = this.getMbr();
|
|
39669
|
-
const width2 = mbr.getWidth();
|
|
39670
|
-
const height2 = mbr.getHeight();
|
|
39671
|
-
return [
|
|
39672
|
-
new Point(mbr.left + width2 / 2, mbr.top),
|
|
39673
|
-
new Point(mbr.left + width2 / 2, mbr.bottom),
|
|
39674
|
-
new Point(mbr.left, mbr.top + height2 / 2),
|
|
39675
|
-
new Point(mbr.right, mbr.top + height2 / 2)
|
|
39676
|
-
];
|
|
39677
|
-
}
|
|
39678
|
-
isClosed() {
|
|
39679
|
-
return true;
|
|
39680
|
-
}
|
|
39681
|
-
getRichText() {
|
|
39682
|
-
return null;
|
|
39683
|
-
}
|
|
39684
|
-
getLinkTo() {
|
|
39685
|
-
return;
|
|
39686
|
-
}
|
|
39687
|
-
getExtension() {
|
|
39688
|
-
return this.extension;
|
|
39689
|
-
}
|
|
39690
|
-
download() {
|
|
39691
|
-
if (this.extension) {
|
|
39692
|
-
const linkElem = conf.documentFactory.createElement("a");
|
|
39693
|
-
linkElem.href = this.url;
|
|
39694
|
-
linkElem.setAttribute("download", `${this.board.getBoardId()}.${this.extension}`);
|
|
39695
|
-
linkElem.click();
|
|
39696
|
-
}
|
|
39697
|
-
}
|
|
39698
|
-
}
|
|
39699
|
-
// src/Items/Audio/AudioHelpers.ts
|
|
39700
|
-
var uploadAudioToStorage = async (hash, audioBlob, accessToken, boardId) => {
|
|
39701
|
-
return new Promise((resolve2, reject) => {
|
|
39702
|
-
fetch(`${window.location.origin}/api/v1/media/audio/${boardId}`, {
|
|
39703
|
-
method: "POST",
|
|
39704
|
-
headers: {
|
|
39705
|
-
"Content-Type": audioBlob.type,
|
|
39706
|
-
"x-audio-id": hash,
|
|
39707
|
-
Authorization: `Bearer ${accessToken}`
|
|
39708
|
-
},
|
|
39709
|
-
body: audioBlob
|
|
39710
|
-
}).then(async (response) => {
|
|
39711
|
-
if (response.status !== 200) {
|
|
39712
|
-
return catchErrorResponse(response, "audio");
|
|
39713
|
-
}
|
|
39714
|
-
return response.json();
|
|
39715
|
-
}).then((data) => {
|
|
39716
|
-
console.log(data);
|
|
39717
|
-
resolve2(data.src);
|
|
39718
|
-
}).catch((error) => {
|
|
39719
|
-
console.error("Media storage error:", error);
|
|
39720
|
-
reject(error);
|
|
39721
|
-
});
|
|
39722
|
-
});
|
|
39723
|
-
};
|
|
39724
|
-
var prepareAudio = (file, accessToken, boardId) => {
|
|
39725
|
-
return new Promise((resolve2, reject) => {
|
|
39726
|
-
const audio = document.createElement("audio");
|
|
39727
|
-
audio.src = URL.createObjectURL(file);
|
|
39728
|
-
audio.onloadedmetadata = () => {
|
|
39729
|
-
fileTosha256(file).then((hash) => {
|
|
39730
|
-
uploadAudioToStorage(hash, file, accessToken, boardId).then((url) => {
|
|
39731
|
-
resolve2(url);
|
|
39732
|
-
}).catch(reject);
|
|
39733
|
-
}).catch(() => {
|
|
39734
|
-
reject(new Error("Failed to generate hash"));
|
|
39735
|
-
});
|
|
39736
|
-
};
|
|
39737
|
-
audio.onerror = () => {
|
|
39738
|
-
reject(new Error("Failed to load audio"));
|
|
39739
|
-
};
|
|
39740
|
-
});
|
|
39741
|
-
};
|
|
39742
|
-
var calculateAudioPosition = (board, audioItem) => {
|
|
39743
|
-
const cameraMbr = board.camera.getMbr();
|
|
39744
|
-
const cameraWidth = cameraMbr.getWidth();
|
|
39745
|
-
const translateX = cameraMbr.left + cameraWidth * 0.34;
|
|
39746
|
-
const translateY = cameraMbr.getCenter().y - audioItem.getHeight() / 2;
|
|
39747
|
-
const scale = cameraWidth * 0.32 / audioItem.getWidth();
|
|
39748
|
-
return new Matrix2(translateX, translateY, scale, scale);
|
|
39749
|
-
};
|
|
39750
|
-
// src/Items/Placeholder/Placeholder.ts
|
|
39751
|
-
var PlaceholderImg = `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
39752
|
-
<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"/>
|
|
39753
|
-
</svg>`;
|
|
39754
|
-
|
|
39755
|
-
class Placeholder extends BaseItem {
|
|
39756
|
-
events;
|
|
39757
|
-
miroData;
|
|
39758
|
-
backgroundColor;
|
|
39759
|
-
icon;
|
|
39760
|
-
itemType = "Placeholder";
|
|
39761
|
-
shapeType = "Rectangle";
|
|
39762
|
-
parent = "Board";
|
|
39763
|
-
transformation;
|
|
39764
|
-
path = Shapes[this.shapeType].path.copy();
|
|
39765
|
-
mbr = Shapes[this.shapeType].path.getMbr().copy();
|
|
39766
|
-
subject = new Subject;
|
|
39767
|
-
transformationRenderBlock = undefined;
|
|
39768
|
-
iconImage;
|
|
39769
|
-
constructor(board, events, miroData, id = "", backgroundColor = "#E5E5EA", icon = PlaceholderImg?.toString() || "") {
|
|
39770
|
-
super(board, id);
|
|
39771
|
-
this.events = events;
|
|
39772
|
-
this.miroData = miroData;
|
|
39773
|
-
this.backgroundColor = backgroundColor;
|
|
39774
|
-
this.icon = icon;
|
|
39775
|
-
this.transformation = new Transformation(this.id, this.events);
|
|
39776
|
-
this.transformation.subject.subscribe((_subject) => {
|
|
39777
|
-
this.transformPath();
|
|
39778
|
-
this.updateMbr();
|
|
39779
|
-
this.subject.publish(this);
|
|
39780
|
-
});
|
|
39781
|
-
this.updateMbr();
|
|
39782
|
-
this.loadIconImage();
|
|
39783
|
-
}
|
|
39784
|
-
emit(operation) {
|
|
39785
|
-
if (this.events) {
|
|
39786
|
-
const command = new PlaceholderCommand([this], operation);
|
|
39787
|
-
command.apply();
|
|
39788
|
-
this.events.emit(operation, command);
|
|
39789
|
-
} else {
|
|
39790
|
-
this.apply(operation);
|
|
39791
|
-
}
|
|
39792
|
-
}
|
|
39793
|
-
serialize() {
|
|
39794
|
-
return {
|
|
39795
|
-
itemType: "Placeholder",
|
|
39796
|
-
backgroundColor: this.backgroundColor,
|
|
39797
|
-
icon: this.icon,
|
|
39798
|
-
transformation: this.transformation.serialize(),
|
|
39799
|
-
miroData: this.miroData
|
|
39800
|
-
};
|
|
39801
|
-
}
|
|
39802
|
-
deserialize(data) {
|
|
39803
|
-
this.initPath();
|
|
39804
|
-
this.backgroundColor = data.backgroundColor ?? this.backgroundColor;
|
|
39805
|
-
this.icon = data.icon ?? this.icon;
|
|
39806
|
-
this.miroData = data.miroData;
|
|
39807
|
-
if (data.transformation) {
|
|
39808
|
-
this.transformation.deserialize(data.transformation);
|
|
39809
|
-
this.transformPath();
|
|
39810
|
-
}
|
|
39811
|
-
this.subject.publish(this);
|
|
39812
|
-
return this;
|
|
39813
|
-
}
|
|
39814
|
-
setId(id) {
|
|
39815
|
-
this.id = id;
|
|
39816
|
-
this.transformation.setId(id);
|
|
39817
|
-
return this;
|
|
39818
|
-
}
|
|
39819
|
-
getId() {
|
|
39820
|
-
return this.id;
|
|
39821
|
-
}
|
|
39822
|
-
apply(op) {
|
|
39823
|
-
switch (op.class) {
|
|
39824
|
-
case "Placeholder":
|
|
39825
|
-
this.applyPlaceholder(op);
|
|
39826
|
-
this.updateMbr();
|
|
39827
|
-
break;
|
|
39828
|
-
case "Transformation":
|
|
39829
|
-
this.transformation.apply(op);
|
|
39830
|
-
break;
|
|
39831
|
-
default:
|
|
39832
|
-
return;
|
|
39833
|
-
}
|
|
39834
|
-
this.subject.publish(this);
|
|
39835
|
-
}
|
|
39836
|
-
applyPlaceholder(op) {
|
|
39837
|
-
switch (op.method) {
|
|
39838
|
-
case "setBackgroundColor":
|
|
39839
|
-
this.applyBackgroundColor(op.backgroundColor);
|
|
39840
|
-
break;
|
|
39841
|
-
case "setIcon":
|
|
39842
|
-
this.applyIcon(op.icon);
|
|
39843
|
-
break;
|
|
39844
|
-
case "setMiroData":
|
|
39845
|
-
this.applyMiroData(op.miroData);
|
|
39846
|
-
break;
|
|
39847
|
-
}
|
|
39848
|
-
}
|
|
39849
|
-
getBackgroundColor() {
|
|
39850
|
-
return this.backgroundColor;
|
|
39851
|
-
}
|
|
39852
|
-
applyBackgroundColor(backgroundColor) {
|
|
39853
|
-
this.backgroundColor = backgroundColor;
|
|
39854
|
-
this.path.setBackgroundColor(backgroundColor);
|
|
39855
|
-
}
|
|
39856
|
-
setBackgroundColor(backgroundColor) {
|
|
39857
|
-
this.emit({
|
|
39858
|
-
class: "Placeholder",
|
|
39859
|
-
method: "setBackgroundColor",
|
|
39860
|
-
item: [this.getId()],
|
|
39861
|
-
backgroundColor
|
|
39862
|
-
});
|
|
39863
|
-
}
|
|
39864
|
-
getIcon() {
|
|
39865
|
-
return this.icon;
|
|
39571
|
+
getIcon() {
|
|
39572
|
+
return this.icon;
|
|
39866
39573
|
}
|
|
39867
39574
|
applyIcon(icon) {
|
|
39868
39575
|
this.icon = icon;
|
|
@@ -40106,100 +39813,374 @@ class ImageItem extends BaseItem {
|
|
|
40106
39813
|
this.shootLoadCallbacks();
|
|
40107
39814
|
};
|
|
40108
39815
|
onError = (_error) => {
|
|
40109
|
-
this.image = getPlaceholderImage(this.board);
|
|
39816
|
+
this.image = getPlaceholderImage(this.board);
|
|
39817
|
+
this.updateMbr();
|
|
39818
|
+
this.subject.publish(this);
|
|
39819
|
+
this.shootLoadCallbacks();
|
|
39820
|
+
};
|
|
39821
|
+
onTransform = () => {
|
|
39822
|
+
this.updateMbr();
|
|
39823
|
+
this.subject.publish(this);
|
|
39824
|
+
};
|
|
39825
|
+
updateMbr() {
|
|
39826
|
+
const { translateX, translateY, scaleX, scaleY } = this.transformation.matrix;
|
|
39827
|
+
this.left = translateX;
|
|
39828
|
+
this.top = translateY;
|
|
39829
|
+
this.right = this.left + this.image.width * scaleX;
|
|
39830
|
+
this.bottom = this.top + this.image.height * scaleY;
|
|
39831
|
+
}
|
|
39832
|
+
doOnceBeforeOnLoad = (callback) => {
|
|
39833
|
+
this.loadCallbacks.push(callback);
|
|
39834
|
+
};
|
|
39835
|
+
doOnceOnLoad = (callback) => {
|
|
39836
|
+
this.loadCallbacks.push(callback);
|
|
39837
|
+
};
|
|
39838
|
+
setId(id) {
|
|
39839
|
+
this.id = id;
|
|
39840
|
+
this.transformation.setId(id);
|
|
39841
|
+
this.linkTo.setId(id);
|
|
39842
|
+
return this;
|
|
39843
|
+
}
|
|
39844
|
+
getId() {
|
|
39845
|
+
return this.id;
|
|
39846
|
+
}
|
|
39847
|
+
serialize() {
|
|
39848
|
+
return {
|
|
39849
|
+
itemType: "Image",
|
|
39850
|
+
storageLink: this.storageLink,
|
|
39851
|
+
imageDimension: this.imageDimension,
|
|
39852
|
+
transformation: this.transformation.serialize(),
|
|
39853
|
+
linkTo: this.linkTo.serialize()
|
|
39854
|
+
};
|
|
39855
|
+
}
|
|
39856
|
+
setCoordinates() {
|
|
39857
|
+
this.left = this.transformation.matrix.translateX;
|
|
39858
|
+
this.top = this.transformation.matrix.translateY;
|
|
39859
|
+
this.right = this.left + this.image.width * this.transformation.matrix.scaleX;
|
|
39860
|
+
this.bottom = this.top + this.image.height * this.transformation.matrix.scaleY;
|
|
39861
|
+
this.subject.publish(this);
|
|
39862
|
+
}
|
|
39863
|
+
shootBeforeLoadCallbacks() {
|
|
39864
|
+
while (this.beforeLoadCallbacks.length > 0) {
|
|
39865
|
+
this.beforeLoadCallbacks.shift()(this);
|
|
39866
|
+
}
|
|
39867
|
+
}
|
|
39868
|
+
shootLoadCallbacks() {
|
|
39869
|
+
while (this.loadCallbacks.length > 0) {
|
|
39870
|
+
this.loadCallbacks.shift()(this);
|
|
39871
|
+
}
|
|
39872
|
+
}
|
|
39873
|
+
deserialize(data) {
|
|
39874
|
+
if (data.transformation) {
|
|
39875
|
+
this.transformation.deserialize(data.transformation);
|
|
39876
|
+
}
|
|
39877
|
+
this.linkTo.deserialize(data.linkTo);
|
|
39878
|
+
this.image.onload = () => {
|
|
39879
|
+
this.setCoordinates();
|
|
39880
|
+
this.shootLoadCallbacks();
|
|
39881
|
+
};
|
|
39882
|
+
if (data.storageLink) {
|
|
39883
|
+
this.setStorageLink(data.storageLink);
|
|
39884
|
+
}
|
|
39885
|
+
if (this.image.src) {
|
|
39886
|
+
return this;
|
|
39887
|
+
}
|
|
39888
|
+
this.image = getPlaceholderImage(this.board, data.imageDimension);
|
|
39889
|
+
const storageImage = new Image;
|
|
39890
|
+
storageImage.onload = () => {
|
|
39891
|
+
this.image = storageImage;
|
|
39892
|
+
this.onLoad();
|
|
39893
|
+
};
|
|
39894
|
+
storageImage.onerror = this.onError;
|
|
39895
|
+
storageImage.src = this.storageLink;
|
|
39896
|
+
return this;
|
|
39897
|
+
}
|
|
39898
|
+
emit(operation) {
|
|
39899
|
+
if (this.events) {
|
|
39900
|
+
const command = new ImageCommand([this], operation);
|
|
39901
|
+
command.apply();
|
|
39902
|
+
this.events.emit(operation, command);
|
|
39903
|
+
} else {
|
|
39904
|
+
this.apply(operation);
|
|
39905
|
+
}
|
|
39906
|
+
}
|
|
39907
|
+
setDimensions(dim) {
|
|
39908
|
+
this.imageDimension = dim;
|
|
39909
|
+
}
|
|
39910
|
+
apply(op) {
|
|
39911
|
+
switch (op.class) {
|
|
39912
|
+
case "Transformation":
|
|
39913
|
+
this.transformation.apply(op);
|
|
39914
|
+
break;
|
|
39915
|
+
case "LinkTo":
|
|
39916
|
+
this.linkTo.apply(op);
|
|
39917
|
+
break;
|
|
39918
|
+
case "Image":
|
|
39919
|
+
if (op.data.base64) {
|
|
39920
|
+
this.image.src = op.data.base64;
|
|
39921
|
+
}
|
|
39922
|
+
this.setStorageLink(op.data.storageLink);
|
|
39923
|
+
this.setDimensions(op.data.imageDimension);
|
|
39924
|
+
this.subject.publish(this);
|
|
39925
|
+
break;
|
|
39926
|
+
}
|
|
39927
|
+
}
|
|
39928
|
+
render(context) {
|
|
39929
|
+
if (this.transformationRenderBlock) {
|
|
39930
|
+
return;
|
|
39931
|
+
}
|
|
39932
|
+
const ctx = context.ctx;
|
|
39933
|
+
ctx.save();
|
|
39934
|
+
this.transformation.matrix.applyToContext(ctx);
|
|
39935
|
+
ctx.drawImage(this.image, 0, 0);
|
|
39936
|
+
ctx.restore();
|
|
39937
|
+
if (this.getLinkTo()) {
|
|
39938
|
+
const { top, right } = this.getMbr();
|
|
39939
|
+
this.linkTo.render(context, top, right, this.board.camera.getScale());
|
|
39940
|
+
}
|
|
39941
|
+
}
|
|
39942
|
+
renderHTML(documentFactory) {
|
|
39943
|
+
const div = documentFactory.createElement("image-item");
|
|
39944
|
+
const { translateX, translateY, scaleX, scaleY } = this.transformation.matrix;
|
|
39945
|
+
const transform = `translate(${translateX}px, ${translateY}px) scale(${scaleX}, ${scaleY})`;
|
|
39946
|
+
div.style.backgroundImage = `url(${this.storageLink})`;
|
|
39947
|
+
div.id = this.getId();
|
|
39948
|
+
div.style.width = `${this.imageDimension.width}px`;
|
|
39949
|
+
div.style.height = `${this.imageDimension.height}px`;
|
|
39950
|
+
div.style.transformOrigin = "top left";
|
|
39951
|
+
div.style.transform = transform;
|
|
39952
|
+
div.style.position = "absolute";
|
|
39953
|
+
div.style.backgroundSize = "cover";
|
|
39954
|
+
div.setAttribute("data-link-to", this.linkTo.serialize() || "");
|
|
39955
|
+
if (this.getLinkTo()) {
|
|
39956
|
+
const linkElement = this.linkTo.renderHTML(documentFactory);
|
|
39957
|
+
scaleElementBy(linkElement, 1 / scaleX, 1 / scaleY);
|
|
39958
|
+
translateElementBy(linkElement, (this.getMbr().getWidth() - parseInt(linkElement.style.width)) / scaleX, 0);
|
|
39959
|
+
div.appendChild(linkElement);
|
|
39960
|
+
}
|
|
39961
|
+
return div;
|
|
39962
|
+
}
|
|
39963
|
+
getPath() {
|
|
39964
|
+
const { left, top, right, bottom } = this.getMbr();
|
|
39965
|
+
const leftTop = new Point(left, top);
|
|
39966
|
+
const rightTop = new Point(right, top);
|
|
39967
|
+
const rightBottom = new Point(right, bottom);
|
|
39968
|
+
const leftBottom = new Point(left, bottom);
|
|
39969
|
+
return new Path([
|
|
39970
|
+
new Line(leftTop, rightTop),
|
|
39971
|
+
new Line(rightTop, rightBottom),
|
|
39972
|
+
new Line(rightBottom, leftBottom),
|
|
39973
|
+
new Line(leftBottom, leftTop)
|
|
39974
|
+
], true);
|
|
39975
|
+
}
|
|
39976
|
+
getSnapAnchorPoints() {
|
|
39977
|
+
const mbr = this.getMbr();
|
|
39978
|
+
const width2 = mbr.getWidth();
|
|
39979
|
+
const height2 = mbr.getHeight();
|
|
39980
|
+
return [
|
|
39981
|
+
new Point(mbr.left + width2 / 2, mbr.top),
|
|
39982
|
+
new Point(mbr.left + width2 / 2, mbr.bottom),
|
|
39983
|
+
new Point(mbr.left, mbr.top + height2 / 2),
|
|
39984
|
+
new Point(mbr.right, mbr.top + height2 / 2)
|
|
39985
|
+
];
|
|
39986
|
+
}
|
|
39987
|
+
isClosed() {
|
|
39988
|
+
return true;
|
|
39989
|
+
}
|
|
39990
|
+
getRichText() {
|
|
39991
|
+
return null;
|
|
39992
|
+
}
|
|
39993
|
+
getLinkTo() {
|
|
39994
|
+
return this.linkTo.link;
|
|
39995
|
+
}
|
|
39996
|
+
download() {
|
|
39997
|
+
const linkElem = document.createElement("a");
|
|
39998
|
+
linkElem.href = this.storageLink;
|
|
39999
|
+
linkElem.setAttribute("download", "");
|
|
40000
|
+
linkElem.click();
|
|
40001
|
+
}
|
|
40002
|
+
onRemove() {
|
|
40003
|
+
const storageId = this.getStorageId();
|
|
40004
|
+
if (storageId) {
|
|
40005
|
+
deleteMedia([storageId], this.board.getBoardId());
|
|
40006
|
+
}
|
|
40007
|
+
super.onRemove();
|
|
40008
|
+
}
|
|
40009
|
+
}
|
|
40010
|
+
// src/Items/Audio/Audio.ts
|
|
40011
|
+
class AudioItem extends BaseItem {
|
|
40012
|
+
events;
|
|
40013
|
+
extension;
|
|
40014
|
+
itemType = "Audio";
|
|
40015
|
+
parent = "Board";
|
|
40016
|
+
transformation;
|
|
40017
|
+
linkTo;
|
|
40018
|
+
subject = new Subject;
|
|
40019
|
+
loadCallbacks = [];
|
|
40020
|
+
beforeLoadCallbacks = [];
|
|
40021
|
+
transformationRenderBlock = undefined;
|
|
40022
|
+
url = "";
|
|
40023
|
+
isPlaying = false;
|
|
40024
|
+
currentTime = 0;
|
|
40025
|
+
isStorageUrl = true;
|
|
40026
|
+
constructor(board, isStorageUrl, url, events, id = "", extension2) {
|
|
40027
|
+
super(board, id);
|
|
40028
|
+
this.events = events;
|
|
40029
|
+
this.extension = extension2;
|
|
40030
|
+
this.linkTo = new LinkTo(this.id, events);
|
|
40031
|
+
this.board = board;
|
|
40032
|
+
this.isStorageUrl = isStorageUrl;
|
|
40033
|
+
if (url) {
|
|
40034
|
+
this.applyUrl(url);
|
|
40035
|
+
}
|
|
40036
|
+
this.transformation = new Transformation(id, events);
|
|
40037
|
+
this.linkTo.subject.subscribe(() => {
|
|
40038
|
+
this.updateMbr();
|
|
40039
|
+
this.subject.publish(this);
|
|
40040
|
+
});
|
|
40041
|
+
this.transformation.subject.subscribe(this.onTransform);
|
|
40042
|
+
this.right = this.left + conf.AUDIO_DIMENSIONS.width;
|
|
40043
|
+
this.bottom = this.top + conf.AUDIO_DIMENSIONS.height;
|
|
40044
|
+
this.shouldUseCustomRender = true;
|
|
40045
|
+
}
|
|
40046
|
+
setCurrentTime(time) {
|
|
40047
|
+
this.currentTime = time;
|
|
40048
|
+
}
|
|
40049
|
+
getCurrentTime() {
|
|
40050
|
+
return this.currentTime;
|
|
40051
|
+
}
|
|
40052
|
+
getIsStorageUrl() {
|
|
40053
|
+
return this.isStorageUrl;
|
|
40054
|
+
}
|
|
40055
|
+
onTransform = () => {
|
|
40056
|
+
this.updateMbr();
|
|
40057
|
+
this.subject.publish(this);
|
|
40058
|
+
};
|
|
40059
|
+
doOnceBeforeOnLoad = (callback) => {
|
|
40060
|
+
this.loadCallbacks.push(callback);
|
|
40061
|
+
};
|
|
40062
|
+
doOnceOnLoad = (callback) => {
|
|
40063
|
+
this.loadCallbacks.push(callback);
|
|
40064
|
+
};
|
|
40065
|
+
setIsPlaying(isPlaying) {
|
|
40066
|
+
this.isPlaying = isPlaying;
|
|
40067
|
+
this.shouldRenderOutsideViewRect = isPlaying;
|
|
40068
|
+
this.subject.publish(this);
|
|
40069
|
+
}
|
|
40070
|
+
getIsPlaying() {
|
|
40071
|
+
return this.isPlaying;
|
|
40072
|
+
}
|
|
40073
|
+
applyUrl(url) {
|
|
40074
|
+
if (this.isStorageUrl) {
|
|
40075
|
+
try {
|
|
40076
|
+
const newUrl = new URL(url);
|
|
40077
|
+
this.url = `${window.location.origin}${newUrl.pathname}`;
|
|
40078
|
+
} catch (_) {}
|
|
40079
|
+
} else {
|
|
40080
|
+
this.url = url;
|
|
40081
|
+
}
|
|
40082
|
+
}
|
|
40083
|
+
setUrl(url) {
|
|
40084
|
+
this.emit({
|
|
40085
|
+
class: "Audio",
|
|
40086
|
+
method: "setUrl",
|
|
40087
|
+
item: [this.getId()],
|
|
40088
|
+
url
|
|
40089
|
+
});
|
|
40090
|
+
}
|
|
40091
|
+
getStorageId() {
|
|
40092
|
+
if (!this.isStorageUrl) {
|
|
40093
|
+
return;
|
|
40094
|
+
}
|
|
40095
|
+
return this.url.split("/").pop();
|
|
40096
|
+
}
|
|
40097
|
+
getUrl() {
|
|
40098
|
+
return this.url;
|
|
40099
|
+
}
|
|
40100
|
+
onLoad = async () => {
|
|
40101
|
+
this.shootBeforeLoadCallbacks();
|
|
40102
|
+
this.updateMbr();
|
|
40103
|
+
this.subject.publish(this);
|
|
40104
|
+
this.shootLoadCallbacks();
|
|
40105
|
+
};
|
|
40106
|
+
onError = (_error) => {
|
|
40110
40107
|
this.updateMbr();
|
|
40111
40108
|
this.subject.publish(this);
|
|
40112
40109
|
this.shootLoadCallbacks();
|
|
40113
40110
|
};
|
|
40114
|
-
onTransform = () => {
|
|
40115
|
-
this.updateMbr();
|
|
40116
|
-
this.subject.publish(this);
|
|
40117
|
-
};
|
|
40118
40111
|
updateMbr() {
|
|
40119
40112
|
const { translateX, translateY, scaleX, scaleY } = this.transformation.matrix;
|
|
40120
40113
|
this.left = translateX;
|
|
40121
40114
|
this.top = translateY;
|
|
40122
|
-
this.right = this.left +
|
|
40123
|
-
this.bottom = this.top +
|
|
40115
|
+
this.right = this.left + conf.AUDIO_DIMENSIONS.width * scaleX;
|
|
40116
|
+
this.bottom = this.top + conf.AUDIO_DIMENSIONS.height * scaleY;
|
|
40124
40117
|
}
|
|
40125
|
-
|
|
40126
|
-
this.
|
|
40127
|
-
|
|
40128
|
-
|
|
40129
|
-
|
|
40130
|
-
|
|
40131
|
-
|
|
40132
|
-
|
|
40133
|
-
|
|
40134
|
-
this.
|
|
40135
|
-
|
|
40118
|
+
render(context) {
|
|
40119
|
+
if (this.transformationRenderBlock) {
|
|
40120
|
+
return;
|
|
40121
|
+
}
|
|
40122
|
+
const ctx = context.ctx;
|
|
40123
|
+
const radius = 12 * this.transformation.getScale().x;
|
|
40124
|
+
ctx.save();
|
|
40125
|
+
ctx.globalCompositeOperation = "destination-out";
|
|
40126
|
+
ctx.beginPath();
|
|
40127
|
+
ctx.moveTo(this.left + radius, this.top);
|
|
40128
|
+
ctx.lineTo(this.left + this.getWidth() - radius, this.top);
|
|
40129
|
+
ctx.quadraticCurveTo(this.left + this.getWidth(), this.top, this.left + this.getWidth(), this.top + radius);
|
|
40130
|
+
ctx.lineTo(this.left + this.getWidth(), this.top + this.getHeight() - radius);
|
|
40131
|
+
ctx.quadraticCurveTo(this.left + this.getWidth(), this.top + this.getHeight(), this.left + this.getWidth() - radius, this.top + this.getHeight());
|
|
40132
|
+
ctx.lineTo(this.left + radius, this.top + this.getHeight());
|
|
40133
|
+
ctx.quadraticCurveTo(this.left, this.top + this.getHeight(), this.left, this.top + this.getHeight() - radius);
|
|
40134
|
+
ctx.lineTo(this.left, this.top + radius);
|
|
40135
|
+
ctx.quadraticCurveTo(this.left, this.top, this.left + radius, this.top);
|
|
40136
|
+
ctx.closePath();
|
|
40137
|
+
ctx.fill();
|
|
40138
|
+
ctx.restore();
|
|
40136
40139
|
}
|
|
40137
|
-
|
|
40138
|
-
|
|
40140
|
+
renderHTML(documentFactory) {
|
|
40141
|
+
const div = documentFactory.createElement("audio-item");
|
|
40142
|
+
const { translateX, translateY, scaleX, scaleY } = this.transformation.matrix;
|
|
40143
|
+
const transform = `translate(${translateX}px, ${translateY}px) scale(${scaleX}, ${scaleY})`;
|
|
40144
|
+
div.id = this.getId();
|
|
40145
|
+
div.style.width = `${conf.AUDIO_DIMENSIONS.width}px`;
|
|
40146
|
+
div.style.height = `${conf.AUDIO_DIMENSIONS.height}px`;
|
|
40147
|
+
div.style.transformOrigin = "top left";
|
|
40148
|
+
div.style.transform = transform;
|
|
40149
|
+
div.style.position = "absolute";
|
|
40150
|
+
div.setAttribute("audio-url", this.getUrl());
|
|
40151
|
+
if (this.extension) {
|
|
40152
|
+
div.setAttribute("extension", this.extension);
|
|
40153
|
+
}
|
|
40154
|
+
if (this.isStorageUrl) {
|
|
40155
|
+
div.setAttribute("is-storage-url", "true");
|
|
40156
|
+
}
|
|
40157
|
+
div.setAttribute("data-link-to", "");
|
|
40158
|
+
return div;
|
|
40139
40159
|
}
|
|
40140
40160
|
serialize() {
|
|
40141
40161
|
return {
|
|
40142
|
-
itemType: "
|
|
40143
|
-
|
|
40144
|
-
imageDimension: this.imageDimension,
|
|
40162
|
+
itemType: "Audio",
|
|
40163
|
+
url: this.url,
|
|
40145
40164
|
transformation: this.transformation.serialize(),
|
|
40146
|
-
|
|
40165
|
+
isStorageUrl: this.isStorageUrl,
|
|
40166
|
+
extension: this.extension
|
|
40147
40167
|
};
|
|
40148
40168
|
}
|
|
40149
|
-
setCoordinates() {
|
|
40150
|
-
this.left = this.transformation.matrix.translateX;
|
|
40151
|
-
this.top = this.transformation.matrix.translateY;
|
|
40152
|
-
this.right = this.left + this.image.width * this.transformation.matrix.scaleX;
|
|
40153
|
-
this.bottom = this.top + this.image.height * this.transformation.matrix.scaleY;
|
|
40154
|
-
this.subject.publish(this);
|
|
40155
|
-
}
|
|
40156
|
-
shootBeforeLoadCallbacks() {
|
|
40157
|
-
while (this.beforeLoadCallbacks.length > 0) {
|
|
40158
|
-
this.beforeLoadCallbacks.shift()(this);
|
|
40159
|
-
}
|
|
40160
|
-
}
|
|
40161
|
-
shootLoadCallbacks() {
|
|
40162
|
-
while (this.loadCallbacks.length > 0) {
|
|
40163
|
-
this.loadCallbacks.shift()(this);
|
|
40164
|
-
}
|
|
40165
|
-
}
|
|
40166
40169
|
deserialize(data) {
|
|
40170
|
+
if (data.isStorageUrl) {
|
|
40171
|
+
this.isStorageUrl = data.isStorageUrl;
|
|
40172
|
+
}
|
|
40167
40173
|
if (data.transformation) {
|
|
40168
40174
|
this.transformation.deserialize(data.transformation);
|
|
40169
40175
|
}
|
|
40170
|
-
|
|
40171
|
-
|
|
40172
|
-
this.setCoordinates();
|
|
40173
|
-
this.shootLoadCallbacks();
|
|
40174
|
-
};
|
|
40175
|
-
if (data.storageLink) {
|
|
40176
|
-
this.setStorageLink(data.storageLink);
|
|
40176
|
+
if (data.url) {
|
|
40177
|
+
this.setUrl(data.url);
|
|
40177
40178
|
}
|
|
40178
|
-
if (
|
|
40179
|
-
|
|
40179
|
+
if (data.extension) {
|
|
40180
|
+
this.extension = data.extension;
|
|
40180
40181
|
}
|
|
40181
|
-
this.image = getPlaceholderImage(this.board, data.imageDimension);
|
|
40182
|
-
const storageImage = new Image;
|
|
40183
|
-
storageImage.onload = () => {
|
|
40184
|
-
this.image = storageImage;
|
|
40185
|
-
this.onLoad();
|
|
40186
|
-
};
|
|
40187
|
-
storageImage.onerror = this.onError;
|
|
40188
|
-
storageImage.src = this.storageLink;
|
|
40189
40182
|
return this;
|
|
40190
40183
|
}
|
|
40191
|
-
emit(operation) {
|
|
40192
|
-
if (this.events) {
|
|
40193
|
-
const command = new ImageCommand([this], operation);
|
|
40194
|
-
command.apply();
|
|
40195
|
-
this.events.emit(operation, command);
|
|
40196
|
-
} else {
|
|
40197
|
-
this.apply(operation);
|
|
40198
|
-
}
|
|
40199
|
-
}
|
|
40200
|
-
setDimensions(dim) {
|
|
40201
|
-
this.imageDimension = dim;
|
|
40202
|
-
}
|
|
40203
40184
|
apply(op) {
|
|
40204
40185
|
switch (op.class) {
|
|
40205
40186
|
case "Transformation":
|
|
@@ -40208,50 +40189,40 @@ class ImageItem extends BaseItem {
|
|
|
40208
40189
|
case "LinkTo":
|
|
40209
40190
|
this.linkTo.apply(op);
|
|
40210
40191
|
break;
|
|
40211
|
-
case "
|
|
40212
|
-
if (op.
|
|
40213
|
-
this.
|
|
40192
|
+
case "Audio":
|
|
40193
|
+
if (op.method === "setUrl") {
|
|
40194
|
+
this.applyUrl(op.url);
|
|
40214
40195
|
}
|
|
40215
|
-
this.setStorageLink(op.data.storageLink);
|
|
40216
|
-
this.setDimensions(op.data.imageDimension);
|
|
40217
40196
|
this.subject.publish(this);
|
|
40218
40197
|
break;
|
|
40219
40198
|
}
|
|
40220
40199
|
}
|
|
40221
|
-
|
|
40222
|
-
if (this.
|
|
40223
|
-
|
|
40200
|
+
emit(operation) {
|
|
40201
|
+
if (this.events) {
|
|
40202
|
+
const command = new AudioCommand([this], operation);
|
|
40203
|
+
command.apply();
|
|
40204
|
+
this.events.emit(operation, command);
|
|
40205
|
+
} else {
|
|
40206
|
+
this.apply(operation);
|
|
40224
40207
|
}
|
|
40225
|
-
|
|
40226
|
-
|
|
40227
|
-
this.
|
|
40228
|
-
|
|
40229
|
-
|
|
40230
|
-
|
|
40231
|
-
|
|
40232
|
-
|
|
40208
|
+
}
|
|
40209
|
+
setId(id) {
|
|
40210
|
+
this.id = id;
|
|
40211
|
+
this.transformation.setId(id);
|
|
40212
|
+
return this;
|
|
40213
|
+
}
|
|
40214
|
+
getId() {
|
|
40215
|
+
return this.id;
|
|
40216
|
+
}
|
|
40217
|
+
shootLoadCallbacks() {
|
|
40218
|
+
while (this.loadCallbacks.length > 0) {
|
|
40219
|
+
this.loadCallbacks.shift()(this);
|
|
40233
40220
|
}
|
|
40234
40221
|
}
|
|
40235
|
-
|
|
40236
|
-
|
|
40237
|
-
|
|
40238
|
-
const transform = `translate(${translateX}px, ${translateY}px) scale(${scaleX}, ${scaleY})`;
|
|
40239
|
-
div.style.backgroundImage = `url(${this.storageLink})`;
|
|
40240
|
-
div.id = this.getId();
|
|
40241
|
-
div.style.width = `${this.imageDimension.width}px`;
|
|
40242
|
-
div.style.height = `${this.imageDimension.height}px`;
|
|
40243
|
-
div.style.transformOrigin = "top left";
|
|
40244
|
-
div.style.transform = transform;
|
|
40245
|
-
div.style.position = "absolute";
|
|
40246
|
-
div.style.backgroundSize = "cover";
|
|
40247
|
-
div.setAttribute("data-link-to", this.linkTo.serialize() || "");
|
|
40248
|
-
if (this.getLinkTo()) {
|
|
40249
|
-
const linkElement = this.linkTo.renderHTML(documentFactory);
|
|
40250
|
-
scaleElementBy(linkElement, 1 / scaleX, 1 / scaleY);
|
|
40251
|
-
translateElementBy(linkElement, (this.getMbr().getWidth() - parseInt(linkElement.style.width)) / scaleX, 0);
|
|
40252
|
-
div.appendChild(linkElement);
|
|
40222
|
+
shootBeforeLoadCallbacks() {
|
|
40223
|
+
while (this.beforeLoadCallbacks.length > 0) {
|
|
40224
|
+
this.beforeLoadCallbacks.shift()(this);
|
|
40253
40225
|
}
|
|
40254
|
-
return div;
|
|
40255
40226
|
}
|
|
40256
40227
|
getPath() {
|
|
40257
40228
|
const { left, top, right, bottom } = this.getMbr();
|
|
@@ -40284,15 +40255,78 @@ class ImageItem extends BaseItem {
|
|
|
40284
40255
|
return null;
|
|
40285
40256
|
}
|
|
40286
40257
|
getLinkTo() {
|
|
40287
|
-
return
|
|
40258
|
+
return;
|
|
40259
|
+
}
|
|
40260
|
+
getExtension() {
|
|
40261
|
+
return this.extension;
|
|
40288
40262
|
}
|
|
40289
40263
|
download() {
|
|
40290
|
-
|
|
40291
|
-
|
|
40292
|
-
|
|
40293
|
-
|
|
40264
|
+
if (this.extension) {
|
|
40265
|
+
const linkElem = conf.documentFactory.createElement("a");
|
|
40266
|
+
linkElem.href = this.url;
|
|
40267
|
+
linkElem.setAttribute("download", `${this.board.getBoardId()}.${this.extension}`);
|
|
40268
|
+
linkElem.click();
|
|
40269
|
+
}
|
|
40270
|
+
}
|
|
40271
|
+
onRemove() {
|
|
40272
|
+
const storageId = this.getStorageId();
|
|
40273
|
+
if (storageId) {
|
|
40274
|
+
deleteMedia([storageId], this.board.getBoardId());
|
|
40275
|
+
}
|
|
40276
|
+
super.onRemove();
|
|
40294
40277
|
}
|
|
40295
40278
|
}
|
|
40279
|
+
// src/Items/Audio/AudioHelpers.ts
|
|
40280
|
+
var uploadAudioToStorage = async (hash, audioBlob, accessToken, boardId) => {
|
|
40281
|
+
return new Promise((resolve2, reject) => {
|
|
40282
|
+
fetch(`${window.location.origin}/api/v1/media/audio/${boardId}`, {
|
|
40283
|
+
method: "POST",
|
|
40284
|
+
headers: {
|
|
40285
|
+
"Content-Type": audioBlob.type,
|
|
40286
|
+
"x-audio-id": hash,
|
|
40287
|
+
Authorization: `Bearer ${accessToken}`
|
|
40288
|
+
},
|
|
40289
|
+
body: audioBlob
|
|
40290
|
+
}).then(async (response) => {
|
|
40291
|
+
if (response.status !== 200) {
|
|
40292
|
+
return catchErrorResponse(response, "audio");
|
|
40293
|
+
}
|
|
40294
|
+
return response.json();
|
|
40295
|
+
}).then((data) => {
|
|
40296
|
+
console.log(data);
|
|
40297
|
+
resolve2(data.src);
|
|
40298
|
+
}).catch((error) => {
|
|
40299
|
+
console.error("Media storage error:", error);
|
|
40300
|
+
reject(error);
|
|
40301
|
+
});
|
|
40302
|
+
});
|
|
40303
|
+
};
|
|
40304
|
+
var prepareAudio = (file, accessToken, boardId) => {
|
|
40305
|
+
return new Promise((resolve2, reject) => {
|
|
40306
|
+
const audio = document.createElement("audio");
|
|
40307
|
+
audio.src = URL.createObjectURL(file);
|
|
40308
|
+
audio.onloadedmetadata = () => {
|
|
40309
|
+
fileTosha256(file).then((hash) => {
|
|
40310
|
+
uploadAudioToStorage(hash, file, accessToken, boardId).then((url) => {
|
|
40311
|
+
resolve2(url);
|
|
40312
|
+
}).catch(reject);
|
|
40313
|
+
}).catch(() => {
|
|
40314
|
+
reject(new Error("Failed to generate hash"));
|
|
40315
|
+
});
|
|
40316
|
+
};
|
|
40317
|
+
audio.onerror = () => {
|
|
40318
|
+
reject(new Error("Failed to load audio"));
|
|
40319
|
+
};
|
|
40320
|
+
});
|
|
40321
|
+
};
|
|
40322
|
+
var calculateAudioPosition = (board, audioItem) => {
|
|
40323
|
+
const cameraMbr = board.camera.getMbr();
|
|
40324
|
+
const cameraWidth = cameraMbr.getWidth();
|
|
40325
|
+
const translateX = cameraMbr.left + cameraWidth * 0.34;
|
|
40326
|
+
const translateY = cameraMbr.getCenter().y - audioItem.getHeight() / 2;
|
|
40327
|
+
const scale = cameraWidth * 0.32 / audioItem.getWidth();
|
|
40328
|
+
return new Matrix2(translateX, translateY, scale, scale);
|
|
40329
|
+
};
|
|
40296
40330
|
// src/isSafari.ts
|
|
40297
40331
|
function isSafari() {
|
|
40298
40332
|
if (typeof navigator === "undefined") {
|
|
@@ -51990,14 +52024,15 @@ class Board {
|
|
|
51990
52024
|
}
|
|
51991
52025
|
applyAddItems(op) {
|
|
51992
52026
|
if (Array.isArray(op.item)) {
|
|
52027
|
+
const data = op.data;
|
|
51993
52028
|
const items = op.item.map((item2) => {
|
|
51994
|
-
const created = this.createItem(item2,
|
|
52029
|
+
const created = this.createItem(item2, data[item2]);
|
|
51995
52030
|
this.index.insert(created);
|
|
51996
52031
|
return created;
|
|
51997
52032
|
});
|
|
51998
52033
|
items.forEach((item2) => {
|
|
51999
|
-
if (item2
|
|
52000
|
-
const connectorData =
|
|
52034
|
+
if (item2 instanceof Connector2 && data[item2.getId()]) {
|
|
52035
|
+
const connectorData = data[item2.getId()];
|
|
52001
52036
|
item2.applyStartPoint(connectorData.startPoint);
|
|
52002
52037
|
item2.applyEndPoint(connectorData.endPoint);
|
|
52003
52038
|
}
|
|
@@ -52026,7 +52061,7 @@ class Board {
|
|
|
52026
52061
|
this.findItemAndApply(op.item, (item) => {
|
|
52027
52062
|
this.index.remove(item);
|
|
52028
52063
|
this.selection.remove(item);
|
|
52029
|
-
if (item
|
|
52064
|
+
if (item instanceof Connector2) {
|
|
52030
52065
|
item.clearObservedItems();
|
|
52031
52066
|
}
|
|
52032
52067
|
removedItems.push(item);
|
|
@@ -52034,7 +52069,7 @@ class Board {
|
|
|
52034
52069
|
}
|
|
52035
52070
|
applyRemoveLockedGroupOperation(op) {
|
|
52036
52071
|
const item = this.index.getById(op.item[0]);
|
|
52037
|
-
if (!item || item
|
|
52072
|
+
if (!item || !(item instanceof Group)) {
|
|
52038
52073
|
return;
|
|
52039
52074
|
}
|
|
52040
52075
|
item.getChildren().forEach((item2) => {
|
|
@@ -52050,9 +52085,11 @@ class Board {
|
|
|
52050
52085
|
});
|
|
52051
52086
|
}
|
|
52052
52087
|
applyItemOperation(op) {
|
|
52053
|
-
|
|
52054
|
-
|
|
52055
|
-
|
|
52088
|
+
if ("item" in op) {
|
|
52089
|
+
this.findItemAndApply(op.item, (item) => {
|
|
52090
|
+
item.apply(op);
|
|
52091
|
+
});
|
|
52092
|
+
}
|
|
52056
52093
|
}
|
|
52057
52094
|
findItemAndApply(item, apply) {
|
|
52058
52095
|
if (Array.isArray(item)) {
|
|
@@ -52141,9 +52178,8 @@ class Board {
|
|
|
52141
52178
|
if (withConnectors) {
|
|
52142
52179
|
connectors = this.items.getLinkedConnectorsById(item.getId()).map((connector) => connector.getId());
|
|
52143
52180
|
}
|
|
52144
|
-
|
|
52145
|
-
|
|
52146
|
-
deleteMedia([item.getStorageId()], this.boardId);
|
|
52181
|
+
if ("onRemove" in item) {
|
|
52182
|
+
item.onRemove();
|
|
52147
52183
|
}
|
|
52148
52184
|
this.emit({
|
|
52149
52185
|
class: "Board",
|