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/cjs/browser.js
CHANGED
|
@@ -33554,6 +33554,7 @@ class BaseItem extends Mbr {
|
|
|
33554
33554
|
transformationRenderBlock = undefined;
|
|
33555
33555
|
board;
|
|
33556
33556
|
id;
|
|
33557
|
+
onRemoveCallbacks = [];
|
|
33557
33558
|
shouldUseCustomRender = false;
|
|
33558
33559
|
shouldRenderOutsideViewRect = true;
|
|
33559
33560
|
itemType = "";
|
|
@@ -33631,6 +33632,12 @@ class BaseItem extends Mbr {
|
|
|
33631
33632
|
break;
|
|
33632
33633
|
}
|
|
33633
33634
|
}
|
|
33635
|
+
addOnRemoveCallback(cb) {
|
|
33636
|
+
this.onRemoveCallbacks.push(cb);
|
|
33637
|
+
}
|
|
33638
|
+
onRemove() {
|
|
33639
|
+
this.onRemoveCallbacks.forEach((cb) => cb());
|
|
33640
|
+
}
|
|
33634
33641
|
render(context) {}
|
|
33635
33642
|
renderHTML(documentFactory) {
|
|
33636
33643
|
return documentFactory.createElement("div");
|
|
@@ -38887,6 +38894,9 @@ class VideoItem extends BaseItem {
|
|
|
38887
38894
|
this.loadCallbacks.push(callback);
|
|
38888
38895
|
};
|
|
38889
38896
|
getStorageId() {
|
|
38897
|
+
if (!this.isStorageUrl) {
|
|
38898
|
+
return;
|
|
38899
|
+
}
|
|
38890
38900
|
return this.url.split("/").pop();
|
|
38891
38901
|
}
|
|
38892
38902
|
getIsStorageUrl() {
|
|
@@ -39159,6 +39169,13 @@ class VideoItem extends BaseItem {
|
|
|
39159
39169
|
linkElem.click();
|
|
39160
39170
|
}
|
|
39161
39171
|
}
|
|
39172
|
+
onRemove() {
|
|
39173
|
+
const storageId = this.getStorageId();
|
|
39174
|
+
if (storageId) {
|
|
39175
|
+
deleteMedia([storageId], this.board.getBoardId());
|
|
39176
|
+
}
|
|
39177
|
+
super.onRemove();
|
|
39178
|
+
}
|
|
39162
39179
|
}
|
|
39163
39180
|
// src/Items/Image/calculatePosition.ts
|
|
39164
39181
|
function calculatePosition(boardImage, board) {
|
|
@@ -39589,432 +39606,122 @@ var captureFrame = (frameTime, video) => {
|
|
|
39589
39606
|
return null;
|
|
39590
39607
|
}
|
|
39591
39608
|
};
|
|
39592
|
-
// src/Items/
|
|
39593
|
-
|
|
39609
|
+
// src/Items/Placeholder/Placeholder.ts
|
|
39610
|
+
var PlaceholderImg = `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
39611
|
+
<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"/>
|
|
39612
|
+
</svg>`;
|
|
39613
|
+
|
|
39614
|
+
class Placeholder extends BaseItem {
|
|
39594
39615
|
events;
|
|
39595
|
-
|
|
39596
|
-
|
|
39616
|
+
miroData;
|
|
39617
|
+
backgroundColor;
|
|
39618
|
+
icon;
|
|
39619
|
+
itemType = "Placeholder";
|
|
39620
|
+
shapeType = "Rectangle";
|
|
39597
39621
|
parent = "Board";
|
|
39598
39622
|
transformation;
|
|
39599
|
-
|
|
39623
|
+
path = Shapes[this.shapeType].path.copy();
|
|
39624
|
+
mbr = Shapes[this.shapeType].path.getMbr().copy();
|
|
39600
39625
|
subject = new Subject;
|
|
39601
|
-
loadCallbacks = [];
|
|
39602
|
-
beforeLoadCallbacks = [];
|
|
39603
39626
|
transformationRenderBlock = undefined;
|
|
39604
|
-
|
|
39605
|
-
|
|
39606
|
-
currentTime = 0;
|
|
39607
|
-
isStorageUrl = true;
|
|
39608
|
-
constructor(board, isStorageUrl, url, events, id = "", extension2) {
|
|
39627
|
+
iconImage;
|
|
39628
|
+
constructor(board, events, miroData, id = "", backgroundColor = "#E5E5EA", icon = PlaceholderImg?.toString() || "") {
|
|
39609
39629
|
super(board, id);
|
|
39610
39630
|
this.events = events;
|
|
39611
|
-
this.
|
|
39612
|
-
this.
|
|
39613
|
-
this.
|
|
39614
|
-
this.
|
|
39615
|
-
|
|
39616
|
-
this.
|
|
39617
|
-
}
|
|
39618
|
-
this.transformation = new Transformation(id, events);
|
|
39619
|
-
this.linkTo.subject.subscribe(() => {
|
|
39631
|
+
this.miroData = miroData;
|
|
39632
|
+
this.backgroundColor = backgroundColor;
|
|
39633
|
+
this.icon = icon;
|
|
39634
|
+
this.transformation = new Transformation(this.id, this.events);
|
|
39635
|
+
this.transformation.subject.subscribe((_subject) => {
|
|
39636
|
+
this.transformPath();
|
|
39620
39637
|
this.updateMbr();
|
|
39621
39638
|
this.subject.publish(this);
|
|
39622
39639
|
});
|
|
39623
|
-
this.transformation.subject.subscribe(this.onTransform);
|
|
39624
|
-
this.right = this.left + conf.AUDIO_DIMENSIONS.width;
|
|
39625
|
-
this.bottom = this.top + conf.AUDIO_DIMENSIONS.height;
|
|
39626
|
-
this.shouldUseCustomRender = true;
|
|
39627
|
-
}
|
|
39628
|
-
setCurrentTime(time) {
|
|
39629
|
-
this.currentTime = time;
|
|
39630
|
-
}
|
|
39631
|
-
getCurrentTime() {
|
|
39632
|
-
return this.currentTime;
|
|
39633
|
-
}
|
|
39634
|
-
getIsStorageUrl() {
|
|
39635
|
-
return this.isStorageUrl;
|
|
39636
|
-
}
|
|
39637
|
-
onTransform = () => {
|
|
39638
39640
|
this.updateMbr();
|
|
39639
|
-
this.
|
|
39640
|
-
};
|
|
39641
|
-
doOnceBeforeOnLoad = (callback) => {
|
|
39642
|
-
this.loadCallbacks.push(callback);
|
|
39643
|
-
};
|
|
39644
|
-
doOnceOnLoad = (callback) => {
|
|
39645
|
-
this.loadCallbacks.push(callback);
|
|
39646
|
-
};
|
|
39647
|
-
setIsPlaying(isPlaying) {
|
|
39648
|
-
this.isPlaying = isPlaying;
|
|
39649
|
-
this.shouldRenderOutsideViewRect = isPlaying;
|
|
39650
|
-
this.subject.publish(this);
|
|
39651
|
-
}
|
|
39652
|
-
getIsPlaying() {
|
|
39653
|
-
return this.isPlaying;
|
|
39641
|
+
this.loadIconImage();
|
|
39654
39642
|
}
|
|
39655
|
-
|
|
39656
|
-
if (this.
|
|
39657
|
-
|
|
39658
|
-
|
|
39659
|
-
|
|
39660
|
-
} catch (_) {}
|
|
39643
|
+
emit(operation) {
|
|
39644
|
+
if (this.events) {
|
|
39645
|
+
const command = new PlaceholderCommand([this], operation);
|
|
39646
|
+
command.apply();
|
|
39647
|
+
this.events.emit(operation, command);
|
|
39661
39648
|
} else {
|
|
39662
|
-
this.
|
|
39663
|
-
}
|
|
39664
|
-
}
|
|
39665
|
-
setUrl(url) {
|
|
39666
|
-
this.emit({
|
|
39667
|
-
class: "Audio",
|
|
39668
|
-
method: "setUrl",
|
|
39669
|
-
item: [this.getId()],
|
|
39670
|
-
url
|
|
39671
|
-
});
|
|
39672
|
-
}
|
|
39673
|
-
getStorageId() {
|
|
39674
|
-
return this.url.split("/").pop();
|
|
39675
|
-
}
|
|
39676
|
-
getUrl() {
|
|
39677
|
-
return this.url;
|
|
39678
|
-
}
|
|
39679
|
-
onLoad = async () => {
|
|
39680
|
-
this.shootBeforeLoadCallbacks();
|
|
39681
|
-
this.updateMbr();
|
|
39682
|
-
this.subject.publish(this);
|
|
39683
|
-
this.shootLoadCallbacks();
|
|
39684
|
-
};
|
|
39685
|
-
onError = (_error) => {
|
|
39686
|
-
this.updateMbr();
|
|
39687
|
-
this.subject.publish(this);
|
|
39688
|
-
this.shootLoadCallbacks();
|
|
39689
|
-
};
|
|
39690
|
-
updateMbr() {
|
|
39691
|
-
const { translateX, translateY, scaleX, scaleY } = this.transformation.matrix;
|
|
39692
|
-
this.left = translateX;
|
|
39693
|
-
this.top = translateY;
|
|
39694
|
-
this.right = this.left + conf.AUDIO_DIMENSIONS.width * scaleX;
|
|
39695
|
-
this.bottom = this.top + conf.AUDIO_DIMENSIONS.height * scaleY;
|
|
39696
|
-
}
|
|
39697
|
-
render(context) {
|
|
39698
|
-
if (this.transformationRenderBlock) {
|
|
39699
|
-
return;
|
|
39700
|
-
}
|
|
39701
|
-
const ctx = context.ctx;
|
|
39702
|
-
const radius = 12 * this.transformation.getScale().x;
|
|
39703
|
-
ctx.save();
|
|
39704
|
-
ctx.globalCompositeOperation = "destination-out";
|
|
39705
|
-
ctx.beginPath();
|
|
39706
|
-
ctx.moveTo(this.left + radius, this.top);
|
|
39707
|
-
ctx.lineTo(this.left + this.getWidth() - radius, this.top);
|
|
39708
|
-
ctx.quadraticCurveTo(this.left + this.getWidth(), this.top, this.left + this.getWidth(), this.top + radius);
|
|
39709
|
-
ctx.lineTo(this.left + this.getWidth(), this.top + this.getHeight() - radius);
|
|
39710
|
-
ctx.quadraticCurveTo(this.left + this.getWidth(), this.top + this.getHeight(), this.left + this.getWidth() - radius, this.top + this.getHeight());
|
|
39711
|
-
ctx.lineTo(this.left + radius, this.top + this.getHeight());
|
|
39712
|
-
ctx.quadraticCurveTo(this.left, this.top + this.getHeight(), this.left, this.top + this.getHeight() - radius);
|
|
39713
|
-
ctx.lineTo(this.left, this.top + radius);
|
|
39714
|
-
ctx.quadraticCurveTo(this.left, this.top, this.left + radius, this.top);
|
|
39715
|
-
ctx.closePath();
|
|
39716
|
-
ctx.fill();
|
|
39717
|
-
ctx.restore();
|
|
39718
|
-
}
|
|
39719
|
-
renderHTML(documentFactory) {
|
|
39720
|
-
const div = documentFactory.createElement("audio-item");
|
|
39721
|
-
const { translateX, translateY, scaleX, scaleY } = this.transformation.matrix;
|
|
39722
|
-
const transform = `translate(${translateX}px, ${translateY}px) scale(${scaleX}, ${scaleY})`;
|
|
39723
|
-
div.id = this.getId();
|
|
39724
|
-
div.style.width = `${conf.AUDIO_DIMENSIONS.width}px`;
|
|
39725
|
-
div.style.height = `${conf.AUDIO_DIMENSIONS.height}px`;
|
|
39726
|
-
div.style.transformOrigin = "top left";
|
|
39727
|
-
div.style.transform = transform;
|
|
39728
|
-
div.style.position = "absolute";
|
|
39729
|
-
div.setAttribute("audio-url", this.getUrl());
|
|
39730
|
-
if (this.extension) {
|
|
39731
|
-
div.setAttribute("extension", this.extension);
|
|
39732
|
-
}
|
|
39733
|
-
if (this.isStorageUrl) {
|
|
39734
|
-
div.setAttribute("is-storage-url", "true");
|
|
39649
|
+
this.apply(operation);
|
|
39735
39650
|
}
|
|
39736
|
-
div.setAttribute("data-link-to", "");
|
|
39737
|
-
return div;
|
|
39738
39651
|
}
|
|
39739
39652
|
serialize() {
|
|
39740
39653
|
return {
|
|
39741
|
-
itemType: "
|
|
39742
|
-
|
|
39654
|
+
itemType: "Placeholder",
|
|
39655
|
+
backgroundColor: this.backgroundColor,
|
|
39656
|
+
icon: this.icon,
|
|
39743
39657
|
transformation: this.transformation.serialize(),
|
|
39744
|
-
|
|
39745
|
-
extension: this.extension
|
|
39658
|
+
miroData: this.miroData
|
|
39746
39659
|
};
|
|
39747
39660
|
}
|
|
39748
39661
|
deserialize(data) {
|
|
39749
|
-
|
|
39750
|
-
|
|
39751
|
-
|
|
39662
|
+
this.initPath();
|
|
39663
|
+
this.backgroundColor = data.backgroundColor ?? this.backgroundColor;
|
|
39664
|
+
this.icon = data.icon ?? this.icon;
|
|
39665
|
+
this.miroData = data.miroData;
|
|
39752
39666
|
if (data.transformation) {
|
|
39753
39667
|
this.transformation.deserialize(data.transformation);
|
|
39668
|
+
this.transformPath();
|
|
39754
39669
|
}
|
|
39755
|
-
|
|
39756
|
-
|
|
39757
|
-
|
|
39758
|
-
|
|
39759
|
-
|
|
39760
|
-
|
|
39670
|
+
this.subject.publish(this);
|
|
39671
|
+
return this;
|
|
39672
|
+
}
|
|
39673
|
+
setId(id) {
|
|
39674
|
+
this.id = id;
|
|
39675
|
+
this.transformation.setId(id);
|
|
39761
39676
|
return this;
|
|
39762
39677
|
}
|
|
39678
|
+
getId() {
|
|
39679
|
+
return this.id;
|
|
39680
|
+
}
|
|
39763
39681
|
apply(op) {
|
|
39764
39682
|
switch (op.class) {
|
|
39683
|
+
case "Placeholder":
|
|
39684
|
+
this.applyPlaceholder(op);
|
|
39685
|
+
this.updateMbr();
|
|
39686
|
+
break;
|
|
39765
39687
|
case "Transformation":
|
|
39766
39688
|
this.transformation.apply(op);
|
|
39767
39689
|
break;
|
|
39768
|
-
|
|
39769
|
-
|
|
39690
|
+
default:
|
|
39691
|
+
return;
|
|
39692
|
+
}
|
|
39693
|
+
this.subject.publish(this);
|
|
39694
|
+
}
|
|
39695
|
+
applyPlaceholder(op) {
|
|
39696
|
+
switch (op.method) {
|
|
39697
|
+
case "setBackgroundColor":
|
|
39698
|
+
this.applyBackgroundColor(op.backgroundColor);
|
|
39770
39699
|
break;
|
|
39771
|
-
case "
|
|
39772
|
-
|
|
39773
|
-
|
|
39774
|
-
|
|
39775
|
-
this.
|
|
39700
|
+
case "setIcon":
|
|
39701
|
+
this.applyIcon(op.icon);
|
|
39702
|
+
break;
|
|
39703
|
+
case "setMiroData":
|
|
39704
|
+
this.applyMiroData(op.miroData);
|
|
39776
39705
|
break;
|
|
39777
39706
|
}
|
|
39778
39707
|
}
|
|
39779
|
-
|
|
39780
|
-
|
|
39781
|
-
const command = new AudioCommand([this], operation);
|
|
39782
|
-
command.apply();
|
|
39783
|
-
this.events.emit(operation, command);
|
|
39784
|
-
} else {
|
|
39785
|
-
this.apply(operation);
|
|
39786
|
-
}
|
|
39708
|
+
getBackgroundColor() {
|
|
39709
|
+
return this.backgroundColor;
|
|
39787
39710
|
}
|
|
39788
|
-
|
|
39789
|
-
this.
|
|
39790
|
-
this.
|
|
39791
|
-
return this;
|
|
39711
|
+
applyBackgroundColor(backgroundColor) {
|
|
39712
|
+
this.backgroundColor = backgroundColor;
|
|
39713
|
+
this.path.setBackgroundColor(backgroundColor);
|
|
39792
39714
|
}
|
|
39793
|
-
|
|
39794
|
-
|
|
39715
|
+
setBackgroundColor(backgroundColor) {
|
|
39716
|
+
this.emit({
|
|
39717
|
+
class: "Placeholder",
|
|
39718
|
+
method: "setBackgroundColor",
|
|
39719
|
+
item: [this.getId()],
|
|
39720
|
+
backgroundColor
|
|
39721
|
+
});
|
|
39795
39722
|
}
|
|
39796
|
-
|
|
39797
|
-
|
|
39798
|
-
this.loadCallbacks.shift()(this);
|
|
39799
|
-
}
|
|
39800
|
-
}
|
|
39801
|
-
shootBeforeLoadCallbacks() {
|
|
39802
|
-
while (this.beforeLoadCallbacks.length > 0) {
|
|
39803
|
-
this.beforeLoadCallbacks.shift()(this);
|
|
39804
|
-
}
|
|
39805
|
-
}
|
|
39806
|
-
getPath() {
|
|
39807
|
-
const { left, top, right, bottom } = this.getMbr();
|
|
39808
|
-
const leftTop = new Point(left, top);
|
|
39809
|
-
const rightTop = new Point(right, top);
|
|
39810
|
-
const rightBottom = new Point(right, bottom);
|
|
39811
|
-
const leftBottom = new Point(left, bottom);
|
|
39812
|
-
return new Path([
|
|
39813
|
-
new Line(leftTop, rightTop),
|
|
39814
|
-
new Line(rightTop, rightBottom),
|
|
39815
|
-
new Line(rightBottom, leftBottom),
|
|
39816
|
-
new Line(leftBottom, leftTop)
|
|
39817
|
-
], true);
|
|
39818
|
-
}
|
|
39819
|
-
getSnapAnchorPoints() {
|
|
39820
|
-
const mbr = this.getMbr();
|
|
39821
|
-
const width2 = mbr.getWidth();
|
|
39822
|
-
const height2 = mbr.getHeight();
|
|
39823
|
-
return [
|
|
39824
|
-
new Point(mbr.left + width2 / 2, mbr.top),
|
|
39825
|
-
new Point(mbr.left + width2 / 2, mbr.bottom),
|
|
39826
|
-
new Point(mbr.left, mbr.top + height2 / 2),
|
|
39827
|
-
new Point(mbr.right, mbr.top + height2 / 2)
|
|
39828
|
-
];
|
|
39829
|
-
}
|
|
39830
|
-
isClosed() {
|
|
39831
|
-
return true;
|
|
39832
|
-
}
|
|
39833
|
-
getRichText() {
|
|
39834
|
-
return null;
|
|
39835
|
-
}
|
|
39836
|
-
getLinkTo() {
|
|
39837
|
-
return;
|
|
39838
|
-
}
|
|
39839
|
-
getExtension() {
|
|
39840
|
-
return this.extension;
|
|
39841
|
-
}
|
|
39842
|
-
download() {
|
|
39843
|
-
if (this.extension) {
|
|
39844
|
-
const linkElem = conf.documentFactory.createElement("a");
|
|
39845
|
-
linkElem.href = this.url;
|
|
39846
|
-
linkElem.setAttribute("download", `${this.board.getBoardId()}.${this.extension}`);
|
|
39847
|
-
linkElem.click();
|
|
39848
|
-
}
|
|
39849
|
-
}
|
|
39850
|
-
}
|
|
39851
|
-
// src/Items/Audio/AudioHelpers.ts
|
|
39852
|
-
var uploadAudioToStorage = async (hash, audioBlob, accessToken, boardId) => {
|
|
39853
|
-
return new Promise((resolve2, reject) => {
|
|
39854
|
-
fetch(`${window.location.origin}/api/v1/media/audio/${boardId}`, {
|
|
39855
|
-
method: "POST",
|
|
39856
|
-
headers: {
|
|
39857
|
-
"Content-Type": audioBlob.type,
|
|
39858
|
-
"x-audio-id": hash,
|
|
39859
|
-
Authorization: `Bearer ${accessToken}`
|
|
39860
|
-
},
|
|
39861
|
-
body: audioBlob
|
|
39862
|
-
}).then(async (response) => {
|
|
39863
|
-
if (response.status !== 200) {
|
|
39864
|
-
return catchErrorResponse(response, "audio");
|
|
39865
|
-
}
|
|
39866
|
-
return response.json();
|
|
39867
|
-
}).then((data) => {
|
|
39868
|
-
console.log(data);
|
|
39869
|
-
resolve2(data.src);
|
|
39870
|
-
}).catch((error) => {
|
|
39871
|
-
console.error("Media storage error:", error);
|
|
39872
|
-
reject(error);
|
|
39873
|
-
});
|
|
39874
|
-
});
|
|
39875
|
-
};
|
|
39876
|
-
var prepareAudio = (file, accessToken, boardId) => {
|
|
39877
|
-
return new Promise((resolve2, reject) => {
|
|
39878
|
-
const audio = document.createElement("audio");
|
|
39879
|
-
audio.src = URL.createObjectURL(file);
|
|
39880
|
-
audio.onloadedmetadata = () => {
|
|
39881
|
-
fileTosha256(file).then((hash) => {
|
|
39882
|
-
uploadAudioToStorage(hash, file, accessToken, boardId).then((url) => {
|
|
39883
|
-
resolve2(url);
|
|
39884
|
-
}).catch(reject);
|
|
39885
|
-
}).catch(() => {
|
|
39886
|
-
reject(new Error("Failed to generate hash"));
|
|
39887
|
-
});
|
|
39888
|
-
};
|
|
39889
|
-
audio.onerror = () => {
|
|
39890
|
-
reject(new Error("Failed to load audio"));
|
|
39891
|
-
};
|
|
39892
|
-
});
|
|
39893
|
-
};
|
|
39894
|
-
var calculateAudioPosition = (board, audioItem) => {
|
|
39895
|
-
const cameraMbr = board.camera.getMbr();
|
|
39896
|
-
const cameraWidth = cameraMbr.getWidth();
|
|
39897
|
-
const translateX = cameraMbr.left + cameraWidth * 0.34;
|
|
39898
|
-
const translateY = cameraMbr.getCenter().y - audioItem.getHeight() / 2;
|
|
39899
|
-
const scale = cameraWidth * 0.32 / audioItem.getWidth();
|
|
39900
|
-
return new Matrix2(translateX, translateY, scale, scale);
|
|
39901
|
-
};
|
|
39902
|
-
// src/Items/Placeholder/Placeholder.ts
|
|
39903
|
-
var PlaceholderImg = `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
39904
|
-
<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"/>
|
|
39905
|
-
</svg>`;
|
|
39906
|
-
|
|
39907
|
-
class Placeholder extends BaseItem {
|
|
39908
|
-
events;
|
|
39909
|
-
miroData;
|
|
39910
|
-
backgroundColor;
|
|
39911
|
-
icon;
|
|
39912
|
-
itemType = "Placeholder";
|
|
39913
|
-
shapeType = "Rectangle";
|
|
39914
|
-
parent = "Board";
|
|
39915
|
-
transformation;
|
|
39916
|
-
path = Shapes[this.shapeType].path.copy();
|
|
39917
|
-
mbr = Shapes[this.shapeType].path.getMbr().copy();
|
|
39918
|
-
subject = new Subject;
|
|
39919
|
-
transformationRenderBlock = undefined;
|
|
39920
|
-
iconImage;
|
|
39921
|
-
constructor(board, events, miroData, id = "", backgroundColor = "#E5E5EA", icon = PlaceholderImg?.toString() || "") {
|
|
39922
|
-
super(board, id);
|
|
39923
|
-
this.events = events;
|
|
39924
|
-
this.miroData = miroData;
|
|
39925
|
-
this.backgroundColor = backgroundColor;
|
|
39926
|
-
this.icon = icon;
|
|
39927
|
-
this.transformation = new Transformation(this.id, this.events);
|
|
39928
|
-
this.transformation.subject.subscribe((_subject) => {
|
|
39929
|
-
this.transformPath();
|
|
39930
|
-
this.updateMbr();
|
|
39931
|
-
this.subject.publish(this);
|
|
39932
|
-
});
|
|
39933
|
-
this.updateMbr();
|
|
39934
|
-
this.loadIconImage();
|
|
39935
|
-
}
|
|
39936
|
-
emit(operation) {
|
|
39937
|
-
if (this.events) {
|
|
39938
|
-
const command = new PlaceholderCommand([this], operation);
|
|
39939
|
-
command.apply();
|
|
39940
|
-
this.events.emit(operation, command);
|
|
39941
|
-
} else {
|
|
39942
|
-
this.apply(operation);
|
|
39943
|
-
}
|
|
39944
|
-
}
|
|
39945
|
-
serialize() {
|
|
39946
|
-
return {
|
|
39947
|
-
itemType: "Placeholder",
|
|
39948
|
-
backgroundColor: this.backgroundColor,
|
|
39949
|
-
icon: this.icon,
|
|
39950
|
-
transformation: this.transformation.serialize(),
|
|
39951
|
-
miroData: this.miroData
|
|
39952
|
-
};
|
|
39953
|
-
}
|
|
39954
|
-
deserialize(data) {
|
|
39955
|
-
this.initPath();
|
|
39956
|
-
this.backgroundColor = data.backgroundColor ?? this.backgroundColor;
|
|
39957
|
-
this.icon = data.icon ?? this.icon;
|
|
39958
|
-
this.miroData = data.miroData;
|
|
39959
|
-
if (data.transformation) {
|
|
39960
|
-
this.transformation.deserialize(data.transformation);
|
|
39961
|
-
this.transformPath();
|
|
39962
|
-
}
|
|
39963
|
-
this.subject.publish(this);
|
|
39964
|
-
return this;
|
|
39965
|
-
}
|
|
39966
|
-
setId(id) {
|
|
39967
|
-
this.id = id;
|
|
39968
|
-
this.transformation.setId(id);
|
|
39969
|
-
return this;
|
|
39970
|
-
}
|
|
39971
|
-
getId() {
|
|
39972
|
-
return this.id;
|
|
39973
|
-
}
|
|
39974
|
-
apply(op) {
|
|
39975
|
-
switch (op.class) {
|
|
39976
|
-
case "Placeholder":
|
|
39977
|
-
this.applyPlaceholder(op);
|
|
39978
|
-
this.updateMbr();
|
|
39979
|
-
break;
|
|
39980
|
-
case "Transformation":
|
|
39981
|
-
this.transformation.apply(op);
|
|
39982
|
-
break;
|
|
39983
|
-
default:
|
|
39984
|
-
return;
|
|
39985
|
-
}
|
|
39986
|
-
this.subject.publish(this);
|
|
39987
|
-
}
|
|
39988
|
-
applyPlaceholder(op) {
|
|
39989
|
-
switch (op.method) {
|
|
39990
|
-
case "setBackgroundColor":
|
|
39991
|
-
this.applyBackgroundColor(op.backgroundColor);
|
|
39992
|
-
break;
|
|
39993
|
-
case "setIcon":
|
|
39994
|
-
this.applyIcon(op.icon);
|
|
39995
|
-
break;
|
|
39996
|
-
case "setMiroData":
|
|
39997
|
-
this.applyMiroData(op.miroData);
|
|
39998
|
-
break;
|
|
39999
|
-
}
|
|
40000
|
-
}
|
|
40001
|
-
getBackgroundColor() {
|
|
40002
|
-
return this.backgroundColor;
|
|
40003
|
-
}
|
|
40004
|
-
applyBackgroundColor(backgroundColor) {
|
|
40005
|
-
this.backgroundColor = backgroundColor;
|
|
40006
|
-
this.path.setBackgroundColor(backgroundColor);
|
|
40007
|
-
}
|
|
40008
|
-
setBackgroundColor(backgroundColor) {
|
|
40009
|
-
this.emit({
|
|
40010
|
-
class: "Placeholder",
|
|
40011
|
-
method: "setBackgroundColor",
|
|
40012
|
-
item: [this.getId()],
|
|
40013
|
-
backgroundColor
|
|
40014
|
-
});
|
|
40015
|
-
}
|
|
40016
|
-
getIcon() {
|
|
40017
|
-
return this.icon;
|
|
39723
|
+
getIcon() {
|
|
39724
|
+
return this.icon;
|
|
40018
39725
|
}
|
|
40019
39726
|
applyIcon(icon) {
|
|
40020
39727
|
this.icon = icon;
|
|
@@ -40258,100 +39965,374 @@ class ImageItem extends BaseItem {
|
|
|
40258
39965
|
this.shootLoadCallbacks();
|
|
40259
39966
|
};
|
|
40260
39967
|
onError = (_error) => {
|
|
40261
|
-
this.image = getPlaceholderImage(this.board);
|
|
39968
|
+
this.image = getPlaceholderImage(this.board);
|
|
39969
|
+
this.updateMbr();
|
|
39970
|
+
this.subject.publish(this);
|
|
39971
|
+
this.shootLoadCallbacks();
|
|
39972
|
+
};
|
|
39973
|
+
onTransform = () => {
|
|
39974
|
+
this.updateMbr();
|
|
39975
|
+
this.subject.publish(this);
|
|
39976
|
+
};
|
|
39977
|
+
updateMbr() {
|
|
39978
|
+
const { translateX, translateY, scaleX, scaleY } = this.transformation.matrix;
|
|
39979
|
+
this.left = translateX;
|
|
39980
|
+
this.top = translateY;
|
|
39981
|
+
this.right = this.left + this.image.width * scaleX;
|
|
39982
|
+
this.bottom = this.top + this.image.height * scaleY;
|
|
39983
|
+
}
|
|
39984
|
+
doOnceBeforeOnLoad = (callback) => {
|
|
39985
|
+
this.loadCallbacks.push(callback);
|
|
39986
|
+
};
|
|
39987
|
+
doOnceOnLoad = (callback) => {
|
|
39988
|
+
this.loadCallbacks.push(callback);
|
|
39989
|
+
};
|
|
39990
|
+
setId(id) {
|
|
39991
|
+
this.id = id;
|
|
39992
|
+
this.transformation.setId(id);
|
|
39993
|
+
this.linkTo.setId(id);
|
|
39994
|
+
return this;
|
|
39995
|
+
}
|
|
39996
|
+
getId() {
|
|
39997
|
+
return this.id;
|
|
39998
|
+
}
|
|
39999
|
+
serialize() {
|
|
40000
|
+
return {
|
|
40001
|
+
itemType: "Image",
|
|
40002
|
+
storageLink: this.storageLink,
|
|
40003
|
+
imageDimension: this.imageDimension,
|
|
40004
|
+
transformation: this.transformation.serialize(),
|
|
40005
|
+
linkTo: this.linkTo.serialize()
|
|
40006
|
+
};
|
|
40007
|
+
}
|
|
40008
|
+
setCoordinates() {
|
|
40009
|
+
this.left = this.transformation.matrix.translateX;
|
|
40010
|
+
this.top = this.transformation.matrix.translateY;
|
|
40011
|
+
this.right = this.left + this.image.width * this.transformation.matrix.scaleX;
|
|
40012
|
+
this.bottom = this.top + this.image.height * this.transformation.matrix.scaleY;
|
|
40013
|
+
this.subject.publish(this);
|
|
40014
|
+
}
|
|
40015
|
+
shootBeforeLoadCallbacks() {
|
|
40016
|
+
while (this.beforeLoadCallbacks.length > 0) {
|
|
40017
|
+
this.beforeLoadCallbacks.shift()(this);
|
|
40018
|
+
}
|
|
40019
|
+
}
|
|
40020
|
+
shootLoadCallbacks() {
|
|
40021
|
+
while (this.loadCallbacks.length > 0) {
|
|
40022
|
+
this.loadCallbacks.shift()(this);
|
|
40023
|
+
}
|
|
40024
|
+
}
|
|
40025
|
+
deserialize(data) {
|
|
40026
|
+
if (data.transformation) {
|
|
40027
|
+
this.transformation.deserialize(data.transformation);
|
|
40028
|
+
}
|
|
40029
|
+
this.linkTo.deserialize(data.linkTo);
|
|
40030
|
+
this.image.onload = () => {
|
|
40031
|
+
this.setCoordinates();
|
|
40032
|
+
this.shootLoadCallbacks();
|
|
40033
|
+
};
|
|
40034
|
+
if (data.storageLink) {
|
|
40035
|
+
this.setStorageLink(data.storageLink);
|
|
40036
|
+
}
|
|
40037
|
+
if (this.image.src) {
|
|
40038
|
+
return this;
|
|
40039
|
+
}
|
|
40040
|
+
this.image = getPlaceholderImage(this.board, data.imageDimension);
|
|
40041
|
+
const storageImage = new Image;
|
|
40042
|
+
storageImage.onload = () => {
|
|
40043
|
+
this.image = storageImage;
|
|
40044
|
+
this.onLoad();
|
|
40045
|
+
};
|
|
40046
|
+
storageImage.onerror = this.onError;
|
|
40047
|
+
storageImage.src = this.storageLink;
|
|
40048
|
+
return this;
|
|
40049
|
+
}
|
|
40050
|
+
emit(operation) {
|
|
40051
|
+
if (this.events) {
|
|
40052
|
+
const command = new ImageCommand([this], operation);
|
|
40053
|
+
command.apply();
|
|
40054
|
+
this.events.emit(operation, command);
|
|
40055
|
+
} else {
|
|
40056
|
+
this.apply(operation);
|
|
40057
|
+
}
|
|
40058
|
+
}
|
|
40059
|
+
setDimensions(dim) {
|
|
40060
|
+
this.imageDimension = dim;
|
|
40061
|
+
}
|
|
40062
|
+
apply(op) {
|
|
40063
|
+
switch (op.class) {
|
|
40064
|
+
case "Transformation":
|
|
40065
|
+
this.transformation.apply(op);
|
|
40066
|
+
break;
|
|
40067
|
+
case "LinkTo":
|
|
40068
|
+
this.linkTo.apply(op);
|
|
40069
|
+
break;
|
|
40070
|
+
case "Image":
|
|
40071
|
+
if (op.data.base64) {
|
|
40072
|
+
this.image.src = op.data.base64;
|
|
40073
|
+
}
|
|
40074
|
+
this.setStorageLink(op.data.storageLink);
|
|
40075
|
+
this.setDimensions(op.data.imageDimension);
|
|
40076
|
+
this.subject.publish(this);
|
|
40077
|
+
break;
|
|
40078
|
+
}
|
|
40079
|
+
}
|
|
40080
|
+
render(context) {
|
|
40081
|
+
if (this.transformationRenderBlock) {
|
|
40082
|
+
return;
|
|
40083
|
+
}
|
|
40084
|
+
const ctx = context.ctx;
|
|
40085
|
+
ctx.save();
|
|
40086
|
+
this.transformation.matrix.applyToContext(ctx);
|
|
40087
|
+
ctx.drawImage(this.image, 0, 0);
|
|
40088
|
+
ctx.restore();
|
|
40089
|
+
if (this.getLinkTo()) {
|
|
40090
|
+
const { top, right } = this.getMbr();
|
|
40091
|
+
this.linkTo.render(context, top, right, this.board.camera.getScale());
|
|
40092
|
+
}
|
|
40093
|
+
}
|
|
40094
|
+
renderHTML(documentFactory) {
|
|
40095
|
+
const div = documentFactory.createElement("image-item");
|
|
40096
|
+
const { translateX, translateY, scaleX, scaleY } = this.transformation.matrix;
|
|
40097
|
+
const transform = `translate(${translateX}px, ${translateY}px) scale(${scaleX}, ${scaleY})`;
|
|
40098
|
+
div.style.backgroundImage = `url(${this.storageLink})`;
|
|
40099
|
+
div.id = this.getId();
|
|
40100
|
+
div.style.width = `${this.imageDimension.width}px`;
|
|
40101
|
+
div.style.height = `${this.imageDimension.height}px`;
|
|
40102
|
+
div.style.transformOrigin = "top left";
|
|
40103
|
+
div.style.transform = transform;
|
|
40104
|
+
div.style.position = "absolute";
|
|
40105
|
+
div.style.backgroundSize = "cover";
|
|
40106
|
+
div.setAttribute("data-link-to", this.linkTo.serialize() || "");
|
|
40107
|
+
if (this.getLinkTo()) {
|
|
40108
|
+
const linkElement = this.linkTo.renderHTML(documentFactory);
|
|
40109
|
+
scaleElementBy(linkElement, 1 / scaleX, 1 / scaleY);
|
|
40110
|
+
translateElementBy(linkElement, (this.getMbr().getWidth() - parseInt(linkElement.style.width)) / scaleX, 0);
|
|
40111
|
+
div.appendChild(linkElement);
|
|
40112
|
+
}
|
|
40113
|
+
return div;
|
|
40114
|
+
}
|
|
40115
|
+
getPath() {
|
|
40116
|
+
const { left, top, right, bottom } = this.getMbr();
|
|
40117
|
+
const leftTop = new Point(left, top);
|
|
40118
|
+
const rightTop = new Point(right, top);
|
|
40119
|
+
const rightBottom = new Point(right, bottom);
|
|
40120
|
+
const leftBottom = new Point(left, bottom);
|
|
40121
|
+
return new Path([
|
|
40122
|
+
new Line(leftTop, rightTop),
|
|
40123
|
+
new Line(rightTop, rightBottom),
|
|
40124
|
+
new Line(rightBottom, leftBottom),
|
|
40125
|
+
new Line(leftBottom, leftTop)
|
|
40126
|
+
], true);
|
|
40127
|
+
}
|
|
40128
|
+
getSnapAnchorPoints() {
|
|
40129
|
+
const mbr = this.getMbr();
|
|
40130
|
+
const width2 = mbr.getWidth();
|
|
40131
|
+
const height2 = mbr.getHeight();
|
|
40132
|
+
return [
|
|
40133
|
+
new Point(mbr.left + width2 / 2, mbr.top),
|
|
40134
|
+
new Point(mbr.left + width2 / 2, mbr.bottom),
|
|
40135
|
+
new Point(mbr.left, mbr.top + height2 / 2),
|
|
40136
|
+
new Point(mbr.right, mbr.top + height2 / 2)
|
|
40137
|
+
];
|
|
40138
|
+
}
|
|
40139
|
+
isClosed() {
|
|
40140
|
+
return true;
|
|
40141
|
+
}
|
|
40142
|
+
getRichText() {
|
|
40143
|
+
return null;
|
|
40144
|
+
}
|
|
40145
|
+
getLinkTo() {
|
|
40146
|
+
return this.linkTo.link;
|
|
40147
|
+
}
|
|
40148
|
+
download() {
|
|
40149
|
+
const linkElem = document.createElement("a");
|
|
40150
|
+
linkElem.href = this.storageLink;
|
|
40151
|
+
linkElem.setAttribute("download", "");
|
|
40152
|
+
linkElem.click();
|
|
40153
|
+
}
|
|
40154
|
+
onRemove() {
|
|
40155
|
+
const storageId = this.getStorageId();
|
|
40156
|
+
if (storageId) {
|
|
40157
|
+
deleteMedia([storageId], this.board.getBoardId());
|
|
40158
|
+
}
|
|
40159
|
+
super.onRemove();
|
|
40160
|
+
}
|
|
40161
|
+
}
|
|
40162
|
+
// src/Items/Audio/Audio.ts
|
|
40163
|
+
class AudioItem extends BaseItem {
|
|
40164
|
+
events;
|
|
40165
|
+
extension;
|
|
40166
|
+
itemType = "Audio";
|
|
40167
|
+
parent = "Board";
|
|
40168
|
+
transformation;
|
|
40169
|
+
linkTo;
|
|
40170
|
+
subject = new Subject;
|
|
40171
|
+
loadCallbacks = [];
|
|
40172
|
+
beforeLoadCallbacks = [];
|
|
40173
|
+
transformationRenderBlock = undefined;
|
|
40174
|
+
url = "";
|
|
40175
|
+
isPlaying = false;
|
|
40176
|
+
currentTime = 0;
|
|
40177
|
+
isStorageUrl = true;
|
|
40178
|
+
constructor(board, isStorageUrl, url, events, id = "", extension2) {
|
|
40179
|
+
super(board, id);
|
|
40180
|
+
this.events = events;
|
|
40181
|
+
this.extension = extension2;
|
|
40182
|
+
this.linkTo = new LinkTo(this.id, events);
|
|
40183
|
+
this.board = board;
|
|
40184
|
+
this.isStorageUrl = isStorageUrl;
|
|
40185
|
+
if (url) {
|
|
40186
|
+
this.applyUrl(url);
|
|
40187
|
+
}
|
|
40188
|
+
this.transformation = new Transformation(id, events);
|
|
40189
|
+
this.linkTo.subject.subscribe(() => {
|
|
40190
|
+
this.updateMbr();
|
|
40191
|
+
this.subject.publish(this);
|
|
40192
|
+
});
|
|
40193
|
+
this.transformation.subject.subscribe(this.onTransform);
|
|
40194
|
+
this.right = this.left + conf.AUDIO_DIMENSIONS.width;
|
|
40195
|
+
this.bottom = this.top + conf.AUDIO_DIMENSIONS.height;
|
|
40196
|
+
this.shouldUseCustomRender = true;
|
|
40197
|
+
}
|
|
40198
|
+
setCurrentTime(time) {
|
|
40199
|
+
this.currentTime = time;
|
|
40200
|
+
}
|
|
40201
|
+
getCurrentTime() {
|
|
40202
|
+
return this.currentTime;
|
|
40203
|
+
}
|
|
40204
|
+
getIsStorageUrl() {
|
|
40205
|
+
return this.isStorageUrl;
|
|
40206
|
+
}
|
|
40207
|
+
onTransform = () => {
|
|
40208
|
+
this.updateMbr();
|
|
40209
|
+
this.subject.publish(this);
|
|
40210
|
+
};
|
|
40211
|
+
doOnceBeforeOnLoad = (callback) => {
|
|
40212
|
+
this.loadCallbacks.push(callback);
|
|
40213
|
+
};
|
|
40214
|
+
doOnceOnLoad = (callback) => {
|
|
40215
|
+
this.loadCallbacks.push(callback);
|
|
40216
|
+
};
|
|
40217
|
+
setIsPlaying(isPlaying) {
|
|
40218
|
+
this.isPlaying = isPlaying;
|
|
40219
|
+
this.shouldRenderOutsideViewRect = isPlaying;
|
|
40220
|
+
this.subject.publish(this);
|
|
40221
|
+
}
|
|
40222
|
+
getIsPlaying() {
|
|
40223
|
+
return this.isPlaying;
|
|
40224
|
+
}
|
|
40225
|
+
applyUrl(url) {
|
|
40226
|
+
if (this.isStorageUrl) {
|
|
40227
|
+
try {
|
|
40228
|
+
const newUrl = new URL(url);
|
|
40229
|
+
this.url = `${window.location.origin}${newUrl.pathname}`;
|
|
40230
|
+
} catch (_) {}
|
|
40231
|
+
} else {
|
|
40232
|
+
this.url = url;
|
|
40233
|
+
}
|
|
40234
|
+
}
|
|
40235
|
+
setUrl(url) {
|
|
40236
|
+
this.emit({
|
|
40237
|
+
class: "Audio",
|
|
40238
|
+
method: "setUrl",
|
|
40239
|
+
item: [this.getId()],
|
|
40240
|
+
url
|
|
40241
|
+
});
|
|
40242
|
+
}
|
|
40243
|
+
getStorageId() {
|
|
40244
|
+
if (!this.isStorageUrl) {
|
|
40245
|
+
return;
|
|
40246
|
+
}
|
|
40247
|
+
return this.url.split("/").pop();
|
|
40248
|
+
}
|
|
40249
|
+
getUrl() {
|
|
40250
|
+
return this.url;
|
|
40251
|
+
}
|
|
40252
|
+
onLoad = async () => {
|
|
40253
|
+
this.shootBeforeLoadCallbacks();
|
|
40254
|
+
this.updateMbr();
|
|
40255
|
+
this.subject.publish(this);
|
|
40256
|
+
this.shootLoadCallbacks();
|
|
40257
|
+
};
|
|
40258
|
+
onError = (_error) => {
|
|
40262
40259
|
this.updateMbr();
|
|
40263
40260
|
this.subject.publish(this);
|
|
40264
40261
|
this.shootLoadCallbacks();
|
|
40265
40262
|
};
|
|
40266
|
-
onTransform = () => {
|
|
40267
|
-
this.updateMbr();
|
|
40268
|
-
this.subject.publish(this);
|
|
40269
|
-
};
|
|
40270
40263
|
updateMbr() {
|
|
40271
40264
|
const { translateX, translateY, scaleX, scaleY } = this.transformation.matrix;
|
|
40272
40265
|
this.left = translateX;
|
|
40273
40266
|
this.top = translateY;
|
|
40274
|
-
this.right = this.left +
|
|
40275
|
-
this.bottom = this.top +
|
|
40267
|
+
this.right = this.left + conf.AUDIO_DIMENSIONS.width * scaleX;
|
|
40268
|
+
this.bottom = this.top + conf.AUDIO_DIMENSIONS.height * scaleY;
|
|
40276
40269
|
}
|
|
40277
|
-
|
|
40278
|
-
this.
|
|
40279
|
-
|
|
40280
|
-
|
|
40281
|
-
|
|
40282
|
-
|
|
40283
|
-
|
|
40284
|
-
|
|
40285
|
-
|
|
40286
|
-
this.
|
|
40287
|
-
|
|
40270
|
+
render(context) {
|
|
40271
|
+
if (this.transformationRenderBlock) {
|
|
40272
|
+
return;
|
|
40273
|
+
}
|
|
40274
|
+
const ctx = context.ctx;
|
|
40275
|
+
const radius = 12 * this.transformation.getScale().x;
|
|
40276
|
+
ctx.save();
|
|
40277
|
+
ctx.globalCompositeOperation = "destination-out";
|
|
40278
|
+
ctx.beginPath();
|
|
40279
|
+
ctx.moveTo(this.left + radius, this.top);
|
|
40280
|
+
ctx.lineTo(this.left + this.getWidth() - radius, this.top);
|
|
40281
|
+
ctx.quadraticCurveTo(this.left + this.getWidth(), this.top, this.left + this.getWidth(), this.top + radius);
|
|
40282
|
+
ctx.lineTo(this.left + this.getWidth(), this.top + this.getHeight() - radius);
|
|
40283
|
+
ctx.quadraticCurveTo(this.left + this.getWidth(), this.top + this.getHeight(), this.left + this.getWidth() - radius, this.top + this.getHeight());
|
|
40284
|
+
ctx.lineTo(this.left + radius, this.top + this.getHeight());
|
|
40285
|
+
ctx.quadraticCurveTo(this.left, this.top + this.getHeight(), this.left, this.top + this.getHeight() - radius);
|
|
40286
|
+
ctx.lineTo(this.left, this.top + radius);
|
|
40287
|
+
ctx.quadraticCurveTo(this.left, this.top, this.left + radius, this.top);
|
|
40288
|
+
ctx.closePath();
|
|
40289
|
+
ctx.fill();
|
|
40290
|
+
ctx.restore();
|
|
40288
40291
|
}
|
|
40289
|
-
|
|
40290
|
-
|
|
40292
|
+
renderHTML(documentFactory) {
|
|
40293
|
+
const div = documentFactory.createElement("audio-item");
|
|
40294
|
+
const { translateX, translateY, scaleX, scaleY } = this.transformation.matrix;
|
|
40295
|
+
const transform = `translate(${translateX}px, ${translateY}px) scale(${scaleX}, ${scaleY})`;
|
|
40296
|
+
div.id = this.getId();
|
|
40297
|
+
div.style.width = `${conf.AUDIO_DIMENSIONS.width}px`;
|
|
40298
|
+
div.style.height = `${conf.AUDIO_DIMENSIONS.height}px`;
|
|
40299
|
+
div.style.transformOrigin = "top left";
|
|
40300
|
+
div.style.transform = transform;
|
|
40301
|
+
div.style.position = "absolute";
|
|
40302
|
+
div.setAttribute("audio-url", this.getUrl());
|
|
40303
|
+
if (this.extension) {
|
|
40304
|
+
div.setAttribute("extension", this.extension);
|
|
40305
|
+
}
|
|
40306
|
+
if (this.isStorageUrl) {
|
|
40307
|
+
div.setAttribute("is-storage-url", "true");
|
|
40308
|
+
}
|
|
40309
|
+
div.setAttribute("data-link-to", "");
|
|
40310
|
+
return div;
|
|
40291
40311
|
}
|
|
40292
40312
|
serialize() {
|
|
40293
40313
|
return {
|
|
40294
|
-
itemType: "
|
|
40295
|
-
|
|
40296
|
-
imageDimension: this.imageDimension,
|
|
40314
|
+
itemType: "Audio",
|
|
40315
|
+
url: this.url,
|
|
40297
40316
|
transformation: this.transformation.serialize(),
|
|
40298
|
-
|
|
40317
|
+
isStorageUrl: this.isStorageUrl,
|
|
40318
|
+
extension: this.extension
|
|
40299
40319
|
};
|
|
40300
40320
|
}
|
|
40301
|
-
setCoordinates() {
|
|
40302
|
-
this.left = this.transformation.matrix.translateX;
|
|
40303
|
-
this.top = this.transformation.matrix.translateY;
|
|
40304
|
-
this.right = this.left + this.image.width * this.transformation.matrix.scaleX;
|
|
40305
|
-
this.bottom = this.top + this.image.height * this.transformation.matrix.scaleY;
|
|
40306
|
-
this.subject.publish(this);
|
|
40307
|
-
}
|
|
40308
|
-
shootBeforeLoadCallbacks() {
|
|
40309
|
-
while (this.beforeLoadCallbacks.length > 0) {
|
|
40310
|
-
this.beforeLoadCallbacks.shift()(this);
|
|
40311
|
-
}
|
|
40312
|
-
}
|
|
40313
|
-
shootLoadCallbacks() {
|
|
40314
|
-
while (this.loadCallbacks.length > 0) {
|
|
40315
|
-
this.loadCallbacks.shift()(this);
|
|
40316
|
-
}
|
|
40317
|
-
}
|
|
40318
40321
|
deserialize(data) {
|
|
40322
|
+
if (data.isStorageUrl) {
|
|
40323
|
+
this.isStorageUrl = data.isStorageUrl;
|
|
40324
|
+
}
|
|
40319
40325
|
if (data.transformation) {
|
|
40320
40326
|
this.transformation.deserialize(data.transformation);
|
|
40321
40327
|
}
|
|
40322
|
-
|
|
40323
|
-
|
|
40324
|
-
this.setCoordinates();
|
|
40325
|
-
this.shootLoadCallbacks();
|
|
40326
|
-
};
|
|
40327
|
-
if (data.storageLink) {
|
|
40328
|
-
this.setStorageLink(data.storageLink);
|
|
40328
|
+
if (data.url) {
|
|
40329
|
+
this.setUrl(data.url);
|
|
40329
40330
|
}
|
|
40330
|
-
if (
|
|
40331
|
-
|
|
40331
|
+
if (data.extension) {
|
|
40332
|
+
this.extension = data.extension;
|
|
40332
40333
|
}
|
|
40333
|
-
this.image = getPlaceholderImage(this.board, data.imageDimension);
|
|
40334
|
-
const storageImage = new Image;
|
|
40335
|
-
storageImage.onload = () => {
|
|
40336
|
-
this.image = storageImage;
|
|
40337
|
-
this.onLoad();
|
|
40338
|
-
};
|
|
40339
|
-
storageImage.onerror = this.onError;
|
|
40340
|
-
storageImage.src = this.storageLink;
|
|
40341
40334
|
return this;
|
|
40342
40335
|
}
|
|
40343
|
-
emit(operation) {
|
|
40344
|
-
if (this.events) {
|
|
40345
|
-
const command = new ImageCommand([this], operation);
|
|
40346
|
-
command.apply();
|
|
40347
|
-
this.events.emit(operation, command);
|
|
40348
|
-
} else {
|
|
40349
|
-
this.apply(operation);
|
|
40350
|
-
}
|
|
40351
|
-
}
|
|
40352
|
-
setDimensions(dim) {
|
|
40353
|
-
this.imageDimension = dim;
|
|
40354
|
-
}
|
|
40355
40336
|
apply(op) {
|
|
40356
40337
|
switch (op.class) {
|
|
40357
40338
|
case "Transformation":
|
|
@@ -40360,50 +40341,40 @@ class ImageItem extends BaseItem {
|
|
|
40360
40341
|
case "LinkTo":
|
|
40361
40342
|
this.linkTo.apply(op);
|
|
40362
40343
|
break;
|
|
40363
|
-
case "
|
|
40364
|
-
if (op.
|
|
40365
|
-
this.
|
|
40344
|
+
case "Audio":
|
|
40345
|
+
if (op.method === "setUrl") {
|
|
40346
|
+
this.applyUrl(op.url);
|
|
40366
40347
|
}
|
|
40367
|
-
this.setStorageLink(op.data.storageLink);
|
|
40368
|
-
this.setDimensions(op.data.imageDimension);
|
|
40369
40348
|
this.subject.publish(this);
|
|
40370
40349
|
break;
|
|
40371
40350
|
}
|
|
40372
40351
|
}
|
|
40373
|
-
|
|
40374
|
-
if (this.
|
|
40375
|
-
|
|
40352
|
+
emit(operation) {
|
|
40353
|
+
if (this.events) {
|
|
40354
|
+
const command = new AudioCommand([this], operation);
|
|
40355
|
+
command.apply();
|
|
40356
|
+
this.events.emit(operation, command);
|
|
40357
|
+
} else {
|
|
40358
|
+
this.apply(operation);
|
|
40376
40359
|
}
|
|
40377
|
-
|
|
40378
|
-
|
|
40379
|
-
this.
|
|
40380
|
-
|
|
40381
|
-
|
|
40382
|
-
|
|
40383
|
-
|
|
40384
|
-
|
|
40360
|
+
}
|
|
40361
|
+
setId(id) {
|
|
40362
|
+
this.id = id;
|
|
40363
|
+
this.transformation.setId(id);
|
|
40364
|
+
return this;
|
|
40365
|
+
}
|
|
40366
|
+
getId() {
|
|
40367
|
+
return this.id;
|
|
40368
|
+
}
|
|
40369
|
+
shootLoadCallbacks() {
|
|
40370
|
+
while (this.loadCallbacks.length > 0) {
|
|
40371
|
+
this.loadCallbacks.shift()(this);
|
|
40385
40372
|
}
|
|
40386
40373
|
}
|
|
40387
|
-
|
|
40388
|
-
|
|
40389
|
-
|
|
40390
|
-
const transform = `translate(${translateX}px, ${translateY}px) scale(${scaleX}, ${scaleY})`;
|
|
40391
|
-
div.style.backgroundImage = `url(${this.storageLink})`;
|
|
40392
|
-
div.id = this.getId();
|
|
40393
|
-
div.style.width = `${this.imageDimension.width}px`;
|
|
40394
|
-
div.style.height = `${this.imageDimension.height}px`;
|
|
40395
|
-
div.style.transformOrigin = "top left";
|
|
40396
|
-
div.style.transform = transform;
|
|
40397
|
-
div.style.position = "absolute";
|
|
40398
|
-
div.style.backgroundSize = "cover";
|
|
40399
|
-
div.setAttribute("data-link-to", this.linkTo.serialize() || "");
|
|
40400
|
-
if (this.getLinkTo()) {
|
|
40401
|
-
const linkElement = this.linkTo.renderHTML(documentFactory);
|
|
40402
|
-
scaleElementBy(linkElement, 1 / scaleX, 1 / scaleY);
|
|
40403
|
-
translateElementBy(linkElement, (this.getMbr().getWidth() - parseInt(linkElement.style.width)) / scaleX, 0);
|
|
40404
|
-
div.appendChild(linkElement);
|
|
40374
|
+
shootBeforeLoadCallbacks() {
|
|
40375
|
+
while (this.beforeLoadCallbacks.length > 0) {
|
|
40376
|
+
this.beforeLoadCallbacks.shift()(this);
|
|
40405
40377
|
}
|
|
40406
|
-
return div;
|
|
40407
40378
|
}
|
|
40408
40379
|
getPath() {
|
|
40409
40380
|
const { left, top, right, bottom } = this.getMbr();
|
|
@@ -40436,15 +40407,78 @@ class ImageItem extends BaseItem {
|
|
|
40436
40407
|
return null;
|
|
40437
40408
|
}
|
|
40438
40409
|
getLinkTo() {
|
|
40439
|
-
return
|
|
40410
|
+
return;
|
|
40411
|
+
}
|
|
40412
|
+
getExtension() {
|
|
40413
|
+
return this.extension;
|
|
40440
40414
|
}
|
|
40441
40415
|
download() {
|
|
40442
|
-
|
|
40443
|
-
|
|
40444
|
-
|
|
40445
|
-
|
|
40416
|
+
if (this.extension) {
|
|
40417
|
+
const linkElem = conf.documentFactory.createElement("a");
|
|
40418
|
+
linkElem.href = this.url;
|
|
40419
|
+
linkElem.setAttribute("download", `${this.board.getBoardId()}.${this.extension}`);
|
|
40420
|
+
linkElem.click();
|
|
40421
|
+
}
|
|
40422
|
+
}
|
|
40423
|
+
onRemove() {
|
|
40424
|
+
const storageId = this.getStorageId();
|
|
40425
|
+
if (storageId) {
|
|
40426
|
+
deleteMedia([storageId], this.board.getBoardId());
|
|
40427
|
+
}
|
|
40428
|
+
super.onRemove();
|
|
40446
40429
|
}
|
|
40447
40430
|
}
|
|
40431
|
+
// src/Items/Audio/AudioHelpers.ts
|
|
40432
|
+
var uploadAudioToStorage = async (hash, audioBlob, accessToken, boardId) => {
|
|
40433
|
+
return new Promise((resolve2, reject) => {
|
|
40434
|
+
fetch(`${window.location.origin}/api/v1/media/audio/${boardId}`, {
|
|
40435
|
+
method: "POST",
|
|
40436
|
+
headers: {
|
|
40437
|
+
"Content-Type": audioBlob.type,
|
|
40438
|
+
"x-audio-id": hash,
|
|
40439
|
+
Authorization: `Bearer ${accessToken}`
|
|
40440
|
+
},
|
|
40441
|
+
body: audioBlob
|
|
40442
|
+
}).then(async (response) => {
|
|
40443
|
+
if (response.status !== 200) {
|
|
40444
|
+
return catchErrorResponse(response, "audio");
|
|
40445
|
+
}
|
|
40446
|
+
return response.json();
|
|
40447
|
+
}).then((data) => {
|
|
40448
|
+
console.log(data);
|
|
40449
|
+
resolve2(data.src);
|
|
40450
|
+
}).catch((error) => {
|
|
40451
|
+
console.error("Media storage error:", error);
|
|
40452
|
+
reject(error);
|
|
40453
|
+
});
|
|
40454
|
+
});
|
|
40455
|
+
};
|
|
40456
|
+
var prepareAudio = (file, accessToken, boardId) => {
|
|
40457
|
+
return new Promise((resolve2, reject) => {
|
|
40458
|
+
const audio = document.createElement("audio");
|
|
40459
|
+
audio.src = URL.createObjectURL(file);
|
|
40460
|
+
audio.onloadedmetadata = () => {
|
|
40461
|
+
fileTosha256(file).then((hash) => {
|
|
40462
|
+
uploadAudioToStorage(hash, file, accessToken, boardId).then((url) => {
|
|
40463
|
+
resolve2(url);
|
|
40464
|
+
}).catch(reject);
|
|
40465
|
+
}).catch(() => {
|
|
40466
|
+
reject(new Error("Failed to generate hash"));
|
|
40467
|
+
});
|
|
40468
|
+
};
|
|
40469
|
+
audio.onerror = () => {
|
|
40470
|
+
reject(new Error("Failed to load audio"));
|
|
40471
|
+
};
|
|
40472
|
+
});
|
|
40473
|
+
};
|
|
40474
|
+
var calculateAudioPosition = (board, audioItem) => {
|
|
40475
|
+
const cameraMbr = board.camera.getMbr();
|
|
40476
|
+
const cameraWidth = cameraMbr.getWidth();
|
|
40477
|
+
const translateX = cameraMbr.left + cameraWidth * 0.34;
|
|
40478
|
+
const translateY = cameraMbr.getCenter().y - audioItem.getHeight() / 2;
|
|
40479
|
+
const scale = cameraWidth * 0.32 / audioItem.getWidth();
|
|
40480
|
+
return new Matrix2(translateX, translateY, scale, scale);
|
|
40481
|
+
};
|
|
40448
40482
|
// src/isSafari.ts
|
|
40449
40483
|
function isSafari() {
|
|
40450
40484
|
if (typeof navigator === "undefined") {
|
|
@@ -52142,14 +52176,15 @@ class Board {
|
|
|
52142
52176
|
}
|
|
52143
52177
|
applyAddItems(op) {
|
|
52144
52178
|
if (Array.isArray(op.item)) {
|
|
52179
|
+
const data = op.data;
|
|
52145
52180
|
const items = op.item.map((item2) => {
|
|
52146
|
-
const created = this.createItem(item2,
|
|
52181
|
+
const created = this.createItem(item2, data[item2]);
|
|
52147
52182
|
this.index.insert(created);
|
|
52148
52183
|
return created;
|
|
52149
52184
|
});
|
|
52150
52185
|
items.forEach((item2) => {
|
|
52151
|
-
if (item2
|
|
52152
|
-
const connectorData =
|
|
52186
|
+
if (item2 instanceof Connector2 && data[item2.getId()]) {
|
|
52187
|
+
const connectorData = data[item2.getId()];
|
|
52153
52188
|
item2.applyStartPoint(connectorData.startPoint);
|
|
52154
52189
|
item2.applyEndPoint(connectorData.endPoint);
|
|
52155
52190
|
}
|
|
@@ -52178,7 +52213,7 @@ class Board {
|
|
|
52178
52213
|
this.findItemAndApply(op.item, (item) => {
|
|
52179
52214
|
this.index.remove(item);
|
|
52180
52215
|
this.selection.remove(item);
|
|
52181
|
-
if (item
|
|
52216
|
+
if (item instanceof Connector2) {
|
|
52182
52217
|
item.clearObservedItems();
|
|
52183
52218
|
}
|
|
52184
52219
|
removedItems.push(item);
|
|
@@ -52186,7 +52221,7 @@ class Board {
|
|
|
52186
52221
|
}
|
|
52187
52222
|
applyRemoveLockedGroupOperation(op) {
|
|
52188
52223
|
const item = this.index.getById(op.item[0]);
|
|
52189
|
-
if (!item || item
|
|
52224
|
+
if (!item || !(item instanceof Group)) {
|
|
52190
52225
|
return;
|
|
52191
52226
|
}
|
|
52192
52227
|
item.getChildren().forEach((item2) => {
|
|
@@ -52202,9 +52237,11 @@ class Board {
|
|
|
52202
52237
|
});
|
|
52203
52238
|
}
|
|
52204
52239
|
applyItemOperation(op) {
|
|
52205
|
-
|
|
52206
|
-
|
|
52207
|
-
|
|
52240
|
+
if ("item" in op) {
|
|
52241
|
+
this.findItemAndApply(op.item, (item) => {
|
|
52242
|
+
item.apply(op);
|
|
52243
|
+
});
|
|
52244
|
+
}
|
|
52208
52245
|
}
|
|
52209
52246
|
findItemAndApply(item, apply) {
|
|
52210
52247
|
if (Array.isArray(item)) {
|
|
@@ -52293,9 +52330,8 @@ class Board {
|
|
|
52293
52330
|
if (withConnectors) {
|
|
52294
52331
|
connectors = this.items.getLinkedConnectorsById(item.getId()).map((connector) => connector.getId());
|
|
52295
52332
|
}
|
|
52296
|
-
|
|
52297
|
-
|
|
52298
|
-
deleteMedia([item.getStorageId()], this.boardId);
|
|
52333
|
+
if ("onRemove" in item) {
|
|
52334
|
+
item.onRemove();
|
|
52299
52335
|
}
|
|
52300
52336
|
this.emit({
|
|
52301
52337
|
class: "Board",
|