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