microboard-temp 0.1.5 → 0.1.7

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.
@@ -141320,18 +141320,23 @@ var require_css_escape = __commonJS((exports2, module2) => {
141320
141320
  });
141321
141321
  });
141322
141322
 
141323
- // src/node-entry.ts
141324
- var exports_node_entry = {};
141325
- __export(exports_node_entry, {
141323
+ // src/node.ts
141324
+ var exports_node = {};
141325
+ __export(exports_node, {
141326
141326
  validateRichTextData: () => validateRichTextData,
141327
141327
  validateItemsMap: () => validateItemsMap,
141328
+ uploadVideoToStorage: () => uploadVideoToStorage,
141329
+ uploadVideo: () => uploadVideo,
141328
141330
  translateElementBy: () => translateElementBy,
141329
141331
  toFiniteNumber: () => toFiniteNumber,
141330
141332
  tempStorage: () => tempStorage2,
141331
141333
  tagByType: () => tagByType,
141332
141334
  sha256: () => sha256,
141333
141335
  scaleElementBy: () => scaleElementBy,
141336
+ rgbToRgba: () => rgbToRgba,
141334
141337
  resetElementScale: () => resetElementScale,
141338
+ quickAddItem: () => quickAddItem,
141339
+ prepareVideo: () => prepareVideo,
141335
141340
  positionRelatively: () => positionRelatively,
141336
141341
  positionAbsolutely: () => positionAbsolutely,
141337
141342
  parsersHTML: () => parsersHTML,
@@ -141345,17 +141350,26 @@ __export(exports_node_entry, {
141345
141350
  isHotkeyPushed: () => isHotkeyPushed,
141346
141351
  isFiniteNumber: () => isFiniteNumber,
141347
141352
  isControlCharacter: () => isControlCharacter,
141353
+ getYouTubeVideoPreview: () => getYouTubeVideoPreview,
141354
+ getYouTubeThumbnail: () => getYouTubeThumbnail,
141355
+ getVideoMetadata: () => getVideoMetadata,
141348
141356
  getTranslationFromHTML: () => getTranslationFromHTML,
141349
141357
  getScaleFromHTML: () => getScaleFromHTML,
141350
141358
  getRandomNumber: () => getRandomNumber,
141359
+ getQuickAddButtons: () => getQuickAddButtons,
141351
141360
  getHotkeyLabel: () => getHotkeyLabel,
141361
+ getControlPointData: () => getControlPointData,
141352
141362
  forceNumberIntoInterval: () => forceNumberIntoInterval,
141353
141363
  fileTosha256: () => fileTosha256,
141354
141364
  decodeHtml: () => decodeHtml,
141355
141365
  cursors: () => defaultCursors,
141366
+ createVideoItem: () => createVideoItem,
141356
141367
  createEvents: () => createEvents,
141357
141368
  conf: () => conf,
141358
141369
  checkHotkeys: () => checkHotkeys,
141370
+ catmullRomInterpolate: () => catmullRomInterpolate,
141371
+ captureFrame: () => captureFrame,
141372
+ VideoItem: () => VideoItem,
141359
141373
  Transformation: () => Transformation,
141360
141374
  Tools: () => Tools,
141361
141375
  SubjectOperation: () => SubjectOperation,
@@ -141381,7 +141395,8 @@ __export(exports_node_entry, {
141381
141395
  Items: () => Items,
141382
141396
  Frame: () => Frame,
141383
141397
  ExportQuality: () => ExportQuality,
141384
- Events: () => Events,
141398
+ Events: () => Events2,
141399
+ DefaultTransformationData: () => DefaultTransformationData,
141385
141400
  CubicBezier: () => CubicBezier,
141386
141401
  ConnectorData: () => ConnectorData2,
141387
141402
  Connector: () => Connector,
@@ -141393,7 +141408,7 @@ __export(exports_node_entry, {
141393
141408
  Board: () => Board,
141394
141409
  Arc: () => Arc
141395
141410
  });
141396
- module.exports = __toCommonJS(exports_node_entry);
141411
+ module.exports = __toCommonJS(exports_node);
141397
141412
 
141398
141413
  // src/BoardCommand.ts
141399
141414
  class BoardCommand {
@@ -162857,6 +162872,791 @@ class Frame {
162857
162872
  return this.text;
162858
162873
  }
162859
162874
  }
162875
+ // src/Items/Video/VideoCommand.ts
162876
+ class VideoCommand {
162877
+ videos;
162878
+ operation;
162879
+ constructor(videos, operation) {
162880
+ this.videos = videos;
162881
+ this.operation = operation;
162882
+ }
162883
+ apply() {
162884
+ for (const video of this.videos) {
162885
+ video.apply(this.operation);
162886
+ }
162887
+ }
162888
+ revert() {}
162889
+ }
162890
+
162891
+ // src/Items/Video/Video.ts
162892
+ var VIDEO_ICON_SRC = "data:image/svg+xml;charset=utf-8,%3Csvg viewBox='0 0 22 16' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M15 0C15.2652 0 15.5196 0.105357 15.7071 0.292893C15.8946 0.48043 16 0.734784 16 1V5.2L21.213 1.55C21.288 1.49746 21.3759 1.4665 21.4672 1.4605C21.5586 1.4545 21.6498 1.4737 21.731 1.51599C21.8122 1.55829 21.8802 1.62206 21.9276 1.70035C21.9751 1.77865 22.0001 1.86846 22 1.96V14.04C22.0001 14.1315 21.9751 14.2214 21.9276 14.2996C21.8802 14.3779 21.8122 14.4417 21.731 14.484C21.6498 14.5263 21.5586 14.5455 21.4672 14.5395C21.3759 14.5335 21.288 14.5025 21.213 14.45L16 10.8V15C16 15.2652 15.8946 15.5196 15.7071 15.7071C15.5196 15.8946 15.2652 16 15 16H1C0.734784 16 0.48043 15.8946 0.292893 15.7071C0.105357 15.5196 0 15.2652 0 15V1C0 0.734784 0.105357 0.48043 0.292893 0.292893C0.48043 0.105357 0.734784 0 1 0H15ZM14 2H2V14H14V2ZM6.4 4.829C6.47611 4.82879 6.55069 4.8503 6.615 4.891L10.97 7.663C11.0266 7.69917 11.0731 7.749 11.1054 7.80789C11.1376 7.86679 11.1545 7.93285 11.1545 8C11.1545 8.06715 11.1376 8.13321 11.1054 8.19211C11.0731 8.251 11.0266 8.30083 10.97 8.337L6.615 11.11C6.55434 11.1487 6.48438 11.1703 6.41248 11.1725C6.34059 11.1748 6.26941 11.1576 6.20646 11.1228C6.14351 11.088 6.0911 11.0368 6.05477 10.9747C6.01844 10.9127 5.99951 10.8419 6 10.77V5.23C6 5.009 6.18 4.83 6.4 4.83V4.829ZM20 4.84L16 7.64V8.358L20 11.158V4.84Z' fill='%23FFFFFF'/%3E%3C/svg%3E";
162893
+ var videoIcon = conf.documentFactory.createElement("img");
162894
+ videoIcon.src = VIDEO_ICON_SRC;
162895
+ var createPlaceholderImage = (width, height) => {
162896
+ const canvas = conf.documentFactory.createElement("canvas");
162897
+ canvas.width = width;
162898
+ canvas.height = height;
162899
+ const ctx = canvas.getContext("2d");
162900
+ if (ctx) {
162901
+ ctx.fillStyle = "rgba(229, 229, 234, 1)";
162902
+ ctx.fillRect(0, 0, width, height);
162903
+ const iconSize = Math.min(width, height) * 0.3;
162904
+ const iconX = (width - iconSize) / 2;
162905
+ const iconY = (height - iconSize) / 2;
162906
+ ctx.drawImage(videoIcon, iconX, iconY, iconSize * 1.375, iconSize);
162907
+ }
162908
+ const image = new Image;
162909
+ image.src = canvas.toDataURL();
162910
+ return image;
162911
+ };
162912
+
162913
+ class VideoItem extends Mbr {
162914
+ events;
162915
+ id;
162916
+ extension;
162917
+ itemType = "Video";
162918
+ parent = "Board";
162919
+ preview;
162920
+ transformation;
162921
+ linkTo;
162922
+ subject = new Subject;
162923
+ loadCallbacks = [];
162924
+ beforeLoadCallbacks = [];
162925
+ transformationRenderBlock = undefined;
162926
+ url = "";
162927
+ previewUrl = "";
162928
+ isStorageUrl = false;
162929
+ videoDimension;
162930
+ board;
162931
+ isPlaying = false;
162932
+ shouldShowControls = false;
162933
+ playBtnMbr = new Mbr;
162934
+ currentTime = 0;
162935
+ constructor({ url, videoDimension, previewUrl }, board, events, id = "", extension2 = "mp4") {
162936
+ super();
162937
+ this.events = events;
162938
+ this.id = id;
162939
+ this.extension = extension2;
162940
+ this.isStorageUrl = !conf.getYouTubeId(url);
162941
+ this.preview = createPlaceholderImage(videoDimension.width, videoDimension.height);
162942
+ this.linkTo = new LinkTo(this.id, events);
162943
+ this.board = board;
162944
+ if (previewUrl) {
162945
+ this.previewUrl = previewUrl;
162946
+ this.setPreview(this.preview, previewUrl);
162947
+ }
162948
+ this.preview.onload = this.onLoad;
162949
+ this.preview.onerror = this.onError;
162950
+ if (url) {
162951
+ this.setUrl(url);
162952
+ }
162953
+ this.videoDimension = videoDimension;
162954
+ this.transformation = new Transformation(id, events);
162955
+ this.linkTo.subject.subscribe(() => {
162956
+ this.updateMbr();
162957
+ this.subject.publish(this);
162958
+ });
162959
+ this.transformation.subject.subscribe(this.onTransform);
162960
+ }
162961
+ setCurrentTime(time) {
162962
+ this.currentTime = time;
162963
+ }
162964
+ getCurrentTime() {
162965
+ return this.currentTime;
162966
+ }
162967
+ onTransform = () => {
162968
+ this.updateMbr();
162969
+ this.subject.publish(this);
162970
+ };
162971
+ doOnceBeforeOnLoad = (callback) => {
162972
+ this.loadCallbacks.push(callback);
162973
+ };
162974
+ doOnceOnLoad = (callback) => {
162975
+ this.loadCallbacks.push(callback);
162976
+ };
162977
+ getStorageId() {
162978
+ return this.url.split("/").pop();
162979
+ }
162980
+ getIsStorageUrl() {
162981
+ return this.isStorageUrl;
162982
+ }
162983
+ setVideoData({ previewUrl, url }) {
162984
+ this.emit({
162985
+ class: "Video",
162986
+ item: [this.id],
162987
+ method: "updateVideoData",
162988
+ data: { previewUrl, url, videoDimension: this.videoDimension }
162989
+ });
162990
+ }
162991
+ applyVideoData({ previewUrl = "", url = "" }) {
162992
+ this.previewUrl = previewUrl;
162993
+ this.setPreview(this.preview, previewUrl);
162994
+ this.setUrl(url);
162995
+ }
162996
+ setIsPlaying(isPlaying) {
162997
+ this.isPlaying = isPlaying;
162998
+ this.subject.publish(this);
162999
+ }
163000
+ getIsPlaying() {
163001
+ return this.isPlaying;
163002
+ }
163003
+ setShouldShowControls(shouldShowControls) {
163004
+ this.shouldShowControls = shouldShowControls;
163005
+ this.subject.publish(this);
163006
+ }
163007
+ getShouldShowControls() {
163008
+ return this.shouldShowControls;
163009
+ }
163010
+ getPlayBtnMbr() {
163011
+ return this.playBtnMbr;
163012
+ }
163013
+ setUrl(url) {
163014
+ if (this.isStorageUrl) {
163015
+ try {
163016
+ const newUrl = new URL(url);
163017
+ this.url = `${window.location.origin}${newUrl.pathname}`;
163018
+ } catch (_) {}
163019
+ } else {
163020
+ this.url = url;
163021
+ }
163022
+ }
163023
+ setPreview(image, previewUrl) {
163024
+ if (this.isStorageUrl) {
163025
+ try {
163026
+ const newUrl = new URL(previewUrl);
163027
+ image.src = `${window.location.origin}${newUrl.pathname}`;
163028
+ } catch (_) {}
163029
+ } else {
163030
+ image.src = previewUrl;
163031
+ }
163032
+ image.onload = () => {
163033
+ this.preview = image;
163034
+ };
163035
+ }
163036
+ setPreviewImage(image) {
163037
+ this.preview = image;
163038
+ this.preview.onload = this.onLoad;
163039
+ this.preview.onerror = () => {
163040
+ const defaultPreview = new Image;
163041
+ defaultPreview.src = this.getPreviewUrl();
163042
+ this.preview = defaultPreview;
163043
+ this.preview.onload = this.onLoad;
163044
+ this.preview.onerror = this.onError;
163045
+ this.subject.publish(this);
163046
+ };
163047
+ this.subject.publish(this);
163048
+ }
163049
+ getPreviewUrl() {
163050
+ return this.previewUrl;
163051
+ }
163052
+ getUrl() {
163053
+ return this.url;
163054
+ }
163055
+ onLoad = async () => {
163056
+ this.shootBeforeLoadCallbacks();
163057
+ this.updateMbr();
163058
+ this.subject.publish(this);
163059
+ this.shootLoadCallbacks();
163060
+ };
163061
+ onError = (_error) => {
163062
+ this.preview = createPlaceholderImage(this.videoDimension.width, this.videoDimension.height);
163063
+ this.updateMbr();
163064
+ this.subject.publish(this);
163065
+ this.shootLoadCallbacks();
163066
+ };
163067
+ updateMbr() {
163068
+ const { translateX, translateY, scaleX, scaleY } = this.transformation.matrix;
163069
+ this.left = translateX;
163070
+ this.top = translateY;
163071
+ this.right = this.left + this.videoDimension.width * scaleX;
163072
+ this.bottom = this.top + this.videoDimension.height * scaleY;
163073
+ const playBtnSize = 50;
163074
+ const scaledPlayBtn = playBtnSize * this.transformation.matrix.scaleX;
163075
+ this.playBtnMbr = new Mbr(this.left + this.getWidth() / 2 - scaledPlayBtn / 2, this.top + this.getHeight() / 2 - scaledPlayBtn / 2, this.right - this.getWidth() / 2 + scaledPlayBtn / 2, this.bottom - this.getHeight() / 2 + scaledPlayBtn / 2);
163076
+ }
163077
+ render(context) {
163078
+ if (this.transformationRenderBlock || !this.preview.complete) {
163079
+ return;
163080
+ }
163081
+ const ctx = context.ctx;
163082
+ if (this.isPlaying) {
163083
+ ctx.save();
163084
+ ctx.globalCompositeOperation = "destination-out";
163085
+ ctx.fillRect(this.left, this.top, this.getWidth(), this.getHeight());
163086
+ ctx.restore();
163087
+ return;
163088
+ }
163089
+ ctx.save();
163090
+ this.transformation.matrix.applyToContext(ctx);
163091
+ ctx.drawImage(this.preview, 0, 0);
163092
+ if (this.shouldShowControls && this.previewUrl) {
163093
+ ctx.restore();
163094
+ ctx.fillStyle = "rgba(0, 0, 0, 0.5)";
163095
+ ctx.fillRect(this.left, this.top, this.getWidth(), this.getHeight());
163096
+ const playBtnSize = this.playBtnMbr.getWidth();
163097
+ const left = this.playBtnMbr.left;
163098
+ const top = this.playBtnMbr.top;
163099
+ ctx.fillStyle = "white";
163100
+ ctx.beginPath();
163101
+ ctx.moveTo(left, top);
163102
+ ctx.lineTo(left + playBtnSize, top + playBtnSize / 2);
163103
+ ctx.lineTo(left, top + playBtnSize);
163104
+ ctx.closePath();
163105
+ ctx.fill();
163106
+ }
163107
+ ctx.restore();
163108
+ }
163109
+ renderHTML(documentFactory) {
163110
+ const div = documentFactory.createElement("video-item");
163111
+ const { translateX, translateY, scaleX, scaleY } = this.transformation.matrix;
163112
+ const transform = `translate(${translateX}px, ${translateY}px) scale(${scaleX}, ${scaleY})`;
163113
+ div.style.backgroundImage = this.previewUrl ? `url(${this.previewUrl})` : `url(${createPlaceholderImage(this.videoDimension.width, this.videoDimension.height).src})`;
163114
+ div.id = this.getId();
163115
+ div.style.width = `${this.videoDimension.width}px`;
163116
+ div.style.height = `${this.videoDimension.height}px`;
163117
+ div.style.transformOrigin = "top left";
163118
+ div.style.transform = transform;
163119
+ div.style.position = "absolute";
163120
+ div.style.backgroundSize = "cover";
163121
+ div.setAttribute("video-url", this.getUrl());
163122
+ div.setAttribute("preview-url", this.getPreviewUrl());
163123
+ div.setAttribute("extension", this.extension);
163124
+ div.setAttribute("is-storage-url", this.isStorageUrl ? "1" : "");
163125
+ div.setAttribute("data-link-to", "");
163126
+ return div;
163127
+ }
163128
+ serialize() {
163129
+ return {
163130
+ itemType: "Video",
163131
+ url: this.url,
163132
+ videoDimension: this.videoDimension,
163133
+ transformation: this.transformation.serialize(),
163134
+ isStorageUrl: this.isStorageUrl,
163135
+ previewUrl: this.previewUrl,
163136
+ extension: this.extension
163137
+ };
163138
+ }
163139
+ deserialize(data) {
163140
+ if (data.transformation) {
163141
+ this.transformation.deserialize(data.transformation);
163142
+ }
163143
+ if (data.isStorageUrl) {
163144
+ this.isStorageUrl = data.isStorageUrl;
163145
+ }
163146
+ if (data.url) {
163147
+ this.setUrl(data.url);
163148
+ }
163149
+ if (data.extension) {
163150
+ this.extension = data.extension;
163151
+ }
163152
+ this.preview = createPlaceholderImage(data.videoDimension?.width || 100, data.videoDimension?.height || 100);
163153
+ const storageImage = new Image;
163154
+ storageImage.onload = () => {
163155
+ this.onLoad();
163156
+ };
163157
+ storageImage.onerror = this.onError;
163158
+ if (data.previewUrl) {
163159
+ this.setPreview(storageImage, data.previewUrl);
163160
+ }
163161
+ return this;
163162
+ }
163163
+ apply(op) {
163164
+ switch (op.class) {
163165
+ case "Transformation":
163166
+ this.transformation.apply(op);
163167
+ break;
163168
+ case "LinkTo":
163169
+ this.linkTo.apply(op);
163170
+ break;
163171
+ case "Video":
163172
+ if (op.method === "updateVideoData") {
163173
+ this.applyVideoData({
163174
+ url: op.data.url,
163175
+ previewUrl: op.data.previewUrl
163176
+ });
163177
+ }
163178
+ this.subject.publish(this);
163179
+ break;
163180
+ }
163181
+ }
163182
+ emit(operation) {
163183
+ if (this.events) {
163184
+ const command = new VideoCommand([this], operation);
163185
+ command.apply();
163186
+ this.events.emit(operation, command);
163187
+ } else {
163188
+ this.apply(operation);
163189
+ }
163190
+ }
163191
+ setId(id) {
163192
+ this.id = id;
163193
+ this.transformation.setId(id);
163194
+ return this;
163195
+ }
163196
+ getId() {
163197
+ return this.id;
163198
+ }
163199
+ shootLoadCallbacks() {
163200
+ while (this.loadCallbacks.length > 0) {
163201
+ this.loadCallbacks.shift()(this);
163202
+ }
163203
+ }
163204
+ shootBeforeLoadCallbacks() {
163205
+ while (this.beforeLoadCallbacks.length > 0) {
163206
+ this.beforeLoadCallbacks.shift()(this);
163207
+ }
163208
+ }
163209
+ getPath() {
163210
+ const { left, top, right, bottom } = this.getMbr();
163211
+ const leftTop = new Point(left, top);
163212
+ const rightTop = new Point(right, top);
163213
+ const rightBottom = new Point(right, bottom);
163214
+ const leftBottom = new Point(left, bottom);
163215
+ return new Path([
163216
+ new Line(leftTop, rightTop),
163217
+ new Line(rightTop, rightBottom),
163218
+ new Line(rightBottom, leftBottom),
163219
+ new Line(leftBottom, leftTop)
163220
+ ], true);
163221
+ }
163222
+ getSnapAnchorPoints() {
163223
+ const mbr = this.getMbr();
163224
+ const width = mbr.getWidth();
163225
+ const height = mbr.getHeight();
163226
+ return [
163227
+ new Point(mbr.left + width / 2, mbr.top),
163228
+ new Point(mbr.left + width / 2, mbr.bottom),
163229
+ new Point(mbr.left, mbr.top + height / 2),
163230
+ new Point(mbr.right, mbr.top + height / 2)
163231
+ ];
163232
+ }
163233
+ isClosed() {
163234
+ return true;
163235
+ }
163236
+ getRichText() {
163237
+ return null;
163238
+ }
163239
+ getLinkTo() {
163240
+ return;
163241
+ }
163242
+ download() {
163243
+ if (this.isStorageUrl) {
163244
+ const linkElem = document.createElement("a");
163245
+ linkElem.href = this.url;
163246
+ linkElem.setAttribute("download", `${this.board.getBoardId()}.${this.extension}`);
163247
+ linkElem.click();
163248
+ }
163249
+ }
163250
+ }
163251
+ // src/Items/Image/calculatePosition.ts
163252
+ function calculatePosition(boardImage, board) {
163253
+ const viewportMbr = board.camera.getMbr();
163254
+ const viewportWidth = viewportMbr.getWidth();
163255
+ const viewportHeight = viewportMbr.getHeight();
163256
+ const centerPoint = viewportMbr.getCenter();
163257
+ const imageWidth = boardImage.getWidth();
163258
+ const imageHeight = boardImage.getHeight();
163259
+ const prevDimensions = tempStorage2.getImageDimensions();
163260
+ if (prevDimensions) {
163261
+ const scaleX2 = prevDimensions.width / imageWidth;
163262
+ const scaleY2 = prevDimensions.height / imageHeight;
163263
+ const finalScale2 = Math.min(scaleX2, scaleY2);
163264
+ return {
163265
+ scaleX: finalScale2,
163266
+ scaleY: finalScale2,
163267
+ translateX: centerPoint.x - imageWidth * finalScale2 / 2,
163268
+ translateY: centerPoint.y - imageHeight * finalScale2 / 2
163269
+ };
163270
+ }
163271
+ const margin = viewportHeight * 0.05;
163272
+ const viewportWidthWithMargin = viewportWidth - 2 * margin;
163273
+ const viewportHeightWithMargin = viewportHeight - 2 * margin;
163274
+ const scaleX = viewportWidthWithMargin / imageWidth;
163275
+ const scaleY = viewportHeightWithMargin / imageHeight;
163276
+ const scaleToFit = Math.min(scaleX, scaleY);
163277
+ const finalScale = scaleToFit;
163278
+ const scaledImageWidth = imageWidth * finalScale;
163279
+ const scaledImageHeight = imageHeight * finalScale;
163280
+ tempStorage2.setImageDimensions({
163281
+ width: scaledImageWidth,
163282
+ height: scaledImageHeight
163283
+ });
163284
+ const scaledImageCenterX = scaledImageWidth / 2;
163285
+ const scaledImageCenterY = scaledImageHeight / 2;
163286
+ const translateX = centerPoint.x - scaledImageCenterX;
163287
+ const translateY = centerPoint.y - scaledImageCenterY;
163288
+ return { scaleX: finalScale, scaleY: finalScale, translateX, translateY };
163289
+ }
163290
+
163291
+ // src/sha256.ts
163292
+ async function sha256(message) {
163293
+ const msgBuffer = new TextEncoder().encode(message);
163294
+ const hashBuffer = await crypto.subtle.digest("SHA-256", msgBuffer);
163295
+ const hashArray = Array.from(new Uint8Array(hashBuffer));
163296
+ const hashHex = hashArray.map((byte) => byte.toString(16).padStart(2, "0")).join("");
163297
+ return hashHex;
163298
+ }
163299
+ async function fileTosha256(file) {
163300
+ const buffer = await file.arrayBuffer();
163301
+ const hashBuffer = await crypto.subtle.digest("SHA-256", buffer);
163302
+ const hashArray = Array.from(new Uint8Array(hashBuffer));
163303
+ return hashArray.map((byte) => byte.toString(16).padStart(2, "0")).join("");
163304
+ }
163305
+
163306
+ // src/Items/Image/ImageHelpers.ts
163307
+ var catchErrorResponse = async (response, mediaType) => {
163308
+ if (response.status === 403) {
163309
+ const data = await response.json();
163310
+ let errorBody = conf.i18n.t("toolsPanel.addMedia.limitReached.bodyWithoutLimit");
163311
+ if (!data.isOwnerRequest) {
163312
+ errorBody = conf.i18n.t("toolsPanel.addMedia.limitReached.bodyOwner");
163313
+ } else if (data.currentUsage && data.storageLimit) {
163314
+ errorBody = conf.i18n.t(`toolsPanel.addMedia.limitReached.body.${parseInt(data.storageLimit) < 1e5 ? "basic" : "plus"}`);
163315
+ }
163316
+ conf.notify({
163317
+ variant: "warning",
163318
+ header: conf.i18n.t("toolsPanel.addMedia.limitReached.header"),
163319
+ body: errorBody,
163320
+ button: data.isOwnerRequest && data.storageLimit <= 100 ? {
163321
+ text: conf.i18n.t("toolsPanel.addMedia.upgradeToPlus"),
163322
+ onClick: () => conf.openModal("USER_PLAN_MODAL_ID")
163323
+ } : undefined,
163324
+ duration: 8000
163325
+ });
163326
+ } else if (response.status === 413) {
163327
+ const data = await response.json();
163328
+ let errorBody = conf.i18n.t("toolsPanel.addMedia.tooLarge.bodyWithoutLimit");
163329
+ let isBasicPlan = false;
163330
+ if (data.fileSizeLimit && data.fileSize) {
163331
+ if (mediaType === "image") {
163332
+ isBasicPlan = parseInt(data.fileSizeLimit) < 20;
163333
+ errorBody = conf.i18n.t(`toolsPanel.addMedia.tooLarge.imageBody.${isBasicPlan ? "basic" : "plus"}`);
163334
+ } else {
163335
+ isBasicPlan = parseInt(data.fileSizeLimit) < 1000;
163336
+ errorBody = conf.i18n.t(`toolsPanel.addMedia.tooLarge.audioOrVideoBody.${isBasicPlan ? "basic" : "plus"}`);
163337
+ }
163338
+ }
163339
+ conf.notify({
163340
+ variant: "warning",
163341
+ header: conf.i18n.t("toolsPanel.addMedia.tooLarge.header"),
163342
+ body: errorBody,
163343
+ button: isBasicPlan ? {
163344
+ text: conf.i18n.t("toolsPanel.addMedia.upgradeToPlus"),
163345
+ onClick: () => conf.openModal("USER_PLAN_MODAL_ID")
163346
+ } : undefined,
163347
+ duration: 4000
163348
+ });
163349
+ } else if (response.status === 401) {
163350
+ conf.openModal("MEDIA_UNAVAILABLE_MODAL_ID");
163351
+ } else if (response.status === 415) {
163352
+ conf.notify({
163353
+ variant: "warning",
163354
+ header: conf.i18n.t("toolsPanel.addMedia.unsupportedFormat.header"),
163355
+ body: conf.i18n.t("toolsPanel.addMedia.unsupportedFormat.body"),
163356
+ duration: 4000
163357
+ });
163358
+ } else {
163359
+ conf.notify({
163360
+ variant: "error",
163361
+ header: conf.i18n.t("toolsPanel.addMedia.unhandled.header"),
163362
+ body: conf.i18n.t("toolsPanel.addMedia.unhandled.body"),
163363
+ duration: 4000
163364
+ });
163365
+ }
163366
+ throw new Error(`HTTP status: ${response.status}`);
163367
+ };
163368
+ var catchDuplicateErrorResponse = async (response) => {
163369
+ if (response.status === 403) {
163370
+ conf.notify({
163371
+ variant: "warning",
163372
+ header: conf.i18n.t("toolsPanel.addMedia.limitReached.header"),
163373
+ body: conf.i18n.t("toolsPanel.addMedia.limitReached.duplicateBody"),
163374
+ duration: 4000
163375
+ });
163376
+ } else {
163377
+ conf.notify({
163378
+ variant: "error",
163379
+ header: conf.i18n.t("toolsPanel.addMedia.unhandled.header"),
163380
+ body: conf.i18n.t("toolsPanel.addMedia.unhandled.body"),
163381
+ duration: 4000
163382
+ });
163383
+ }
163384
+ throw new Error(`HTTP status: ${response.status}`);
163385
+ };
163386
+ var deleteMedia = async (mediaIds, boardId) => {
163387
+ fetch(`${window?.location.origin}/api/v1/media/usage/${boardId}`, {
163388
+ method: "POST",
163389
+ headers: {
163390
+ "content-type": "application/json"
163391
+ },
163392
+ body: JSON.stringify({ mediaIds, shouldIncrease: false })
163393
+ }).catch((error) => {
163394
+ console.error("Media storage error:", error);
163395
+ });
163396
+ };
163397
+ var updateMediaUsage = async (mediaIds, boardId) => {
163398
+ try {
163399
+ const response = await fetch(`${window?.location.origin}/api/v1/media/usage/${boardId}`, {
163400
+ method: "POST",
163401
+ headers: {
163402
+ "Content-Type": "application/json"
163403
+ },
163404
+ body: JSON.stringify({ mediaIds, shouldIncrease: true })
163405
+ });
163406
+ if (response.status !== 200) {
163407
+ await catchDuplicateErrorResponse(response);
163408
+ return false;
163409
+ }
163410
+ return true;
163411
+ } catch (error) {
163412
+ console.error("Media storage error:", error);
163413
+ return false;
163414
+ }
163415
+ };
163416
+ var uploadToTheStorage = async (hash, dataURL, accessToken, boardId) => {
163417
+ return new Promise((resolve, reject) => {
163418
+ const base64String = dataURL.split(",")[1];
163419
+ const mimeType = dataURL.split(",")[0].split(":")[1].split(";")[0];
163420
+ const binaryString = window.atob(base64String);
163421
+ const bytes = Uint8Array.from(binaryString, (char) => char.charCodeAt(0));
163422
+ const blob = new Blob([bytes], { type: mimeType });
163423
+ fetch(`${window?.location.origin}/api/v1/media/image/${boardId}`, {
163424
+ method: "POST",
163425
+ headers: {
163426
+ "Content-Type": mimeType,
163427
+ "X-Image-Id": hash,
163428
+ Authorization: `Bearer ${accessToken}`
163429
+ },
163430
+ body: blob
163431
+ }).then(async (response) => {
163432
+ if (response.status !== 200) {
163433
+ return catchErrorResponse(response, "image");
163434
+ }
163435
+ return response.json();
163436
+ }).then((data) => {
163437
+ resolve(data.src);
163438
+ }).catch((error) => {
163439
+ console.error("Media storage error:", error);
163440
+ reject(error);
163441
+ });
163442
+ });
163443
+ };
163444
+ var resizeAndConvertToPng = async (inp) => {
163445
+ return new Promise((resolve, reject) => {
163446
+ if (typeof inp !== "string") {
163447
+ return reject("Can't process such input");
163448
+ }
163449
+ const base64String = inp;
163450
+ const image = new Image;
163451
+ image.src = base64String;
163452
+ image.onerror = () => {
163453
+ return reject("Failed to load image");
163454
+ };
163455
+ if (base64String.startsWith("data:image/svg+xml")) {
163456
+ image.onload = async () => {
163457
+ const parser = conf.getDOMParser();
163458
+ const svgDoc = parser.parseFromString(atob(base64String.split(",")[1]), "image/svg+xml");
163459
+ const svgElement = svgDoc.documentElement;
163460
+ svgElement.removeAttribute("width");
163461
+ svgElement.removeAttribute("height");
163462
+ if (!svgElement.getAttribute("viewBox")) {
163463
+ svgElement.setAttribute("viewBox", `0 0 ${image.width} ${image.height}`);
163464
+ }
163465
+ svgElement.setAttribute("width", `${image.width}`);
163466
+ svgElement.setAttribute("height", `${image.height}`);
163467
+ svgElement.setAttribute("preserveAspectRatio", "xMidYMid meet");
163468
+ const newSvgString = new XMLSerializer().serializeToString(svgElement);
163469
+ const newBase64 = `data:image/svg+xml;base64,${btoa(newSvgString)}`;
163470
+ sha256(newBase64).then((hash) => {
163471
+ resolve({
163472
+ dataURL: newBase64,
163473
+ width: image.width,
163474
+ height: image.height,
163475
+ hash: `${hash}.svg`
163476
+ });
163477
+ }).catch(() => {
163478
+ return reject(new Error("Failed to generate hash"));
163479
+ });
163480
+ };
163481
+ } else {
163482
+ image.onload = async () => {
163483
+ const canvas = document.createElement("canvas");
163484
+ const context = canvas.getContext("2d");
163485
+ if (!context) {
163486
+ return reject("Failed to get canvas context");
163487
+ }
163488
+ const { width, height } = image;
163489
+ const scale = 1920 / Math.max(width, height);
163490
+ const canvasWidth = width > 1920 || height > 1920 ? width * scale : width;
163491
+ const canvasHeight = width > 1920 || height > 1920 ? height * scale : height;
163492
+ canvas.width = canvasWidth;
163493
+ canvas.height = canvasHeight;
163494
+ context.drawImage(image, 0, 0, canvasWidth, canvasHeight);
163495
+ const dataURL = canvas.toDataURL("image/webp");
163496
+ sha256(dataURL).then((hash) => {
163497
+ resolve({
163498
+ dataURL,
163499
+ width: canvasWidth,
163500
+ height: canvasHeight,
163501
+ hash
163502
+ });
163503
+ }).catch(() => {
163504
+ return reject(new Error("Failed to generate hash"));
163505
+ });
163506
+ };
163507
+ }
163508
+ });
163509
+ };
163510
+ var prepareImage = (inp, accessToken, boardId) => resizeAndConvertToPng(inp).then(({ width, height, dataURL, hash }) => {
163511
+ return uploadToTheStorage(hash, dataURL, accessToken, boardId).then((src) => {
163512
+ return {
163513
+ imageDimension: { width, height },
163514
+ base64: dataURL,
163515
+ storageLink: src
163516
+ };
163517
+ });
163518
+ });
163519
+
163520
+ // src/Items/Video/VideoHelpers.ts
163521
+ var uploadVideoToStorage = async (hash, videoBlob, accessToken, boardId) => {
163522
+ return new Promise((resolve, reject) => {
163523
+ fetch(`${window.location.origin}/api/v1/media/video/${boardId}`, {
163524
+ method: "POST",
163525
+ headers: {
163526
+ "Content-Type": videoBlob.type,
163527
+ "x-video-id": hash,
163528
+ Authorization: `Bearer ${accessToken}`
163529
+ },
163530
+ body: videoBlob
163531
+ }).then(async (response) => {
163532
+ if (response.status !== 200) {
163533
+ return catchErrorResponse(response, "video");
163534
+ }
163535
+ return response.json();
163536
+ }).then((data) => {
163537
+ resolve(data.src);
163538
+ }).catch((error) => {
163539
+ console.error("Media storage error:", error);
163540
+ reject(error);
163541
+ });
163542
+ });
163543
+ };
163544
+ var getVideoMetadata = (file) => {
163545
+ return new Promise((resolve, reject) => {
163546
+ const video = document.createElement("video");
163547
+ video.preload = "metadata";
163548
+ video.onloadedmetadata = () => {
163549
+ const { videoWidth: width, videoHeight: height } = video;
163550
+ URL.revokeObjectURL(video.src);
163551
+ resolve({ width, height });
163552
+ };
163553
+ video.onerror = () => {
163554
+ URL.revokeObjectURL(video.src);
163555
+ reject(new Error("Failed to load video metadata"));
163556
+ };
163557
+ video.src = URL.createObjectURL(file);
163558
+ });
163559
+ };
163560
+ var createVideoItem = (board, extension2, videoData, onLoadCb) => {
163561
+ const video = new VideoItem(videoData, board, board.events, "", extension2);
163562
+ video.doOnceBeforeOnLoad(() => {
163563
+ const { scaleX, scaleY, translateX, translateY } = calculatePosition(video, board);
163564
+ video.transformation.applyTranslateTo(translateX, translateY);
163565
+ video.transformation.applyScaleTo(scaleX, scaleY);
163566
+ video.updateMbr();
163567
+ const boardVideo = board.add(video);
163568
+ board.selection.removeAll();
163569
+ board.selection.add(boardVideo);
163570
+ onLoadCb(boardVideo);
163571
+ });
163572
+ };
163573
+ var prepareVideo = (file, accessToken, boardId) => {
163574
+ return new Promise((resolve, reject) => {
163575
+ const video = document.createElement("video");
163576
+ video.src = URL.createObjectURL(file);
163577
+ video.onloadedmetadata = () => {
163578
+ video.onseeked = () => {
163579
+ video.onseeked = null;
163580
+ prepareImage(captureFrame(0.1, video)?.src, accessToken, boardId).then((imageData) => {
163581
+ fileTosha256(file).then((hash) => {
163582
+ uploadVideoToStorage(hash, file, accessToken, boardId).then((url) => {
163583
+ resolve({
163584
+ url,
163585
+ previewUrl: imageData.storageLink
163586
+ });
163587
+ }).catch(reject);
163588
+ }).catch(() => {
163589
+ reject(new Error("Failed to generate hash"));
163590
+ });
163591
+ }).catch(() => reject(new Error("Failed to load video preview")));
163592
+ };
163593
+ video.currentTime = 0.1;
163594
+ };
163595
+ video.onerror = () => {
163596
+ reject(new Error("Failed to load video"));
163597
+ };
163598
+ });
163599
+ };
163600
+ var getYouTubeVideoPreview = (youtubeUrl) => {
163601
+ return new Promise((resolve, reject) => {
163602
+ const preview = document.createElement("img");
163603
+ preview.src = youtubeUrl;
163604
+ preview.onload = () => {
163605
+ resolve(preview);
163606
+ };
163607
+ preview.onerror = () => {
163608
+ reject(new Error("Failed to load preview"));
163609
+ };
163610
+ });
163611
+ };
163612
+ var getYouTubeThumbnail = (videoId, quality = "maxres") => {
163613
+ const qualities = {
163614
+ maxres: "maxresdefault",
163615
+ sd: "sddefault",
163616
+ hq: "hqdefault",
163617
+ mq: "mqdefault",
163618
+ default: "default"
163619
+ };
163620
+ return `https://img.youtube.com/vi/${videoId}/${qualities[quality]}.jpg`;
163621
+ };
163622
+ var captureFrame = (frameTime, video) => {
163623
+ video.currentTime = frameTime;
163624
+ const canvas = document.createElement("canvas");
163625
+ canvas.width = video.videoWidth;
163626
+ canvas.height = video.videoHeight;
163627
+ const ctx = canvas.getContext("2d");
163628
+ if (ctx) {
163629
+ ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
163630
+ const frame = new Image;
163631
+ frame.src = canvas.toDataURL();
163632
+ return frame;
163633
+ } else {
163634
+ return null;
163635
+ }
163636
+ };
163637
+ // src/Items/Video/uploadVideo.ts
163638
+ function uploadVideo(file, board, notify, extension2, accessToken) {
163639
+ getVideoMetadata(file).then((dimension) => {
163640
+ const onLoadCb = (videoItem) => {
163641
+ const notificationId = notify({
163642
+ variant: "info",
163643
+ header: conf.i18n.t("toolsPanel.addMedia.loading"),
163644
+ body: "",
163645
+ duration: 1e5,
163646
+ loader: "MediaLoader"
163647
+ });
163648
+ prepareVideo(file, accessToken, board.getBoardId()).then((urls) => {
163649
+ videoItem.setVideoData(urls);
163650
+ }).catch((er) => {
163651
+ board.remove(videoItem);
163652
+ console.error("Could not create video:", er);
163653
+ }).finally(() => conf.disMissNotification(notificationId));
163654
+ };
163655
+ createVideoItem(board, extension2, { videoDimension: dimension }, onLoadCb);
163656
+ }).catch((er) => {
163657
+ console.error("Could not create video:", er);
163658
+ });
163659
+ }
162860
163660
  // src/Items/Comment/CommentCommand.ts
162861
163661
  class CommentCommand {
162862
163662
  comment;
@@ -164146,70 +164946,6 @@ class AudioItem extends Mbr {
164146
164946
  }
164147
164947
  }
164148
164948
  }
164149
- // src/sha256.ts
164150
- async function sha256(message) {
164151
- const msgBuffer = new TextEncoder().encode(message);
164152
- const hashBuffer = await crypto.subtle.digest("SHA-256", msgBuffer);
164153
- const hashArray = Array.from(new Uint8Array(hashBuffer));
164154
- const hashHex = hashArray.map((byte) => byte.toString(16).padStart(2, "0")).join("");
164155
- return hashHex;
164156
- }
164157
- async function fileTosha256(file) {
164158
- const buffer = await file.arrayBuffer();
164159
- const hashBuffer = await crypto.subtle.digest("SHA-256", buffer);
164160
- const hashArray = Array.from(new Uint8Array(hashBuffer));
164161
- return hashArray.map((byte) => byte.toString(16).padStart(2, "0")).join("");
164162
- }
164163
-
164164
- // src/Items/Image/ImageHelpers.ts
164165
- var catchDuplicateErrorResponse = async (response) => {
164166
- if (response.status === 403) {
164167
- conf.notify({
164168
- variant: "warning",
164169
- header: conf.i18n.t("toolsPanel.addMedia.limitReached.header"),
164170
- body: conf.i18n.t("toolsPanel.addMedia.limitReached.duplicateBody"),
164171
- duration: 4000
164172
- });
164173
- } else {
164174
- conf.notify({
164175
- variant: "error",
164176
- header: conf.i18n.t("toolsPanel.addMedia.unhandled.header"),
164177
- body: conf.i18n.t("toolsPanel.addMedia.unhandled.body"),
164178
- duration: 4000
164179
- });
164180
- }
164181
- throw new Error(`HTTP status: ${response.status}`);
164182
- };
164183
- var deleteMedia = async (mediaIds, boardId) => {
164184
- fetch(`${window?.location.origin}/api/v1/media/usage/${boardId}`, {
164185
- method: "POST",
164186
- headers: {
164187
- "content-type": "application/json"
164188
- },
164189
- body: JSON.stringify({ mediaIds, shouldIncrease: false })
164190
- }).catch((error) => {
164191
- console.error("Media storage error:", error);
164192
- });
164193
- };
164194
- var updateMediaUsage = async (mediaIds, boardId) => {
164195
- try {
164196
- const response = await fetch(`${window?.location.origin}/api/v1/media/usage/${boardId}`, {
164197
- method: "POST",
164198
- headers: {
164199
- "Content-Type": "application/json"
164200
- },
164201
- body: JSON.stringify({ mediaIds, shouldIncrease: true })
164202
- });
164203
- if (response.status !== 200) {
164204
- await catchDuplicateErrorResponse(response);
164205
- return false;
164206
- }
164207
- return true;
164208
- } catch (error) {
164209
- console.error("Media storage error:", error);
164210
- return false;
164211
- }
164212
- };
164213
164949
  // src/Items/Drawing/DrawingCommand.ts
164214
164950
  class DrawingCommand {
164215
164951
  item;
@@ -166062,382 +166798,6 @@ class Sticker {
166062
166798
  return this.linkTo.link;
166063
166799
  }
166064
166800
  }
166065
- // src/Items/Video/VideoCommand.ts
166066
- class VideoCommand {
166067
- videos;
166068
- operation;
166069
- constructor(videos, operation) {
166070
- this.videos = videos;
166071
- this.operation = operation;
166072
- }
166073
- apply() {
166074
- for (const video of this.videos) {
166075
- video.apply(this.operation);
166076
- }
166077
- }
166078
- revert() {}
166079
- }
166080
-
166081
- // src/Items/Video/Video.ts
166082
- var VIDEO_ICON_SRC = "data:image/svg+xml;charset=utf-8,%3Csvg viewBox='0 0 22 16' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M15 0C15.2652 0 15.5196 0.105357 15.7071 0.292893C15.8946 0.48043 16 0.734784 16 1V5.2L21.213 1.55C21.288 1.49746 21.3759 1.4665 21.4672 1.4605C21.5586 1.4545 21.6498 1.4737 21.731 1.51599C21.8122 1.55829 21.8802 1.62206 21.9276 1.70035C21.9751 1.77865 22.0001 1.86846 22 1.96V14.04C22.0001 14.1315 21.9751 14.2214 21.9276 14.2996C21.8802 14.3779 21.8122 14.4417 21.731 14.484C21.6498 14.5263 21.5586 14.5455 21.4672 14.5395C21.3759 14.5335 21.288 14.5025 21.213 14.45L16 10.8V15C16 15.2652 15.8946 15.5196 15.7071 15.7071C15.5196 15.8946 15.2652 16 15 16H1C0.734784 16 0.48043 15.8946 0.292893 15.7071C0.105357 15.5196 0 15.2652 0 15V1C0 0.734784 0.105357 0.48043 0.292893 0.292893C0.48043 0.105357 0.734784 0 1 0H15ZM14 2H2V14H14V2ZM6.4 4.829C6.47611 4.82879 6.55069 4.8503 6.615 4.891L10.97 7.663C11.0266 7.69917 11.0731 7.749 11.1054 7.80789C11.1376 7.86679 11.1545 7.93285 11.1545 8C11.1545 8.06715 11.1376 8.13321 11.1054 8.19211C11.0731 8.251 11.0266 8.30083 10.97 8.337L6.615 11.11C6.55434 11.1487 6.48438 11.1703 6.41248 11.1725C6.34059 11.1748 6.26941 11.1576 6.20646 11.1228C6.14351 11.088 6.0911 11.0368 6.05477 10.9747C6.01844 10.9127 5.99951 10.8419 6 10.77V5.23C6 5.009 6.18 4.83 6.4 4.83V4.829ZM20 4.84L16 7.64V8.358L20 11.158V4.84Z' fill='%23FFFFFF'/%3E%3C/svg%3E";
166083
- var videoIcon = conf.documentFactory.createElement("img");
166084
- videoIcon.src = VIDEO_ICON_SRC;
166085
- var createPlaceholderImage = (width2, height2) => {
166086
- const canvas = conf.documentFactory.createElement("canvas");
166087
- canvas.width = width2;
166088
- canvas.height = height2;
166089
- const ctx = canvas.getContext("2d");
166090
- if (ctx) {
166091
- ctx.fillStyle = "rgba(229, 229, 234, 1)";
166092
- ctx.fillRect(0, 0, width2, height2);
166093
- const iconSize = Math.min(width2, height2) * 0.3;
166094
- const iconX = (width2 - iconSize) / 2;
166095
- const iconY = (height2 - iconSize) / 2;
166096
- ctx.drawImage(videoIcon, iconX, iconY, iconSize * 1.375, iconSize);
166097
- }
166098
- const image = new Image;
166099
- image.src = canvas.toDataURL();
166100
- return image;
166101
- };
166102
-
166103
- class VideoItem extends Mbr {
166104
- events;
166105
- id;
166106
- extension;
166107
- itemType = "Video";
166108
- parent = "Board";
166109
- preview;
166110
- transformation;
166111
- linkTo;
166112
- subject = new Subject;
166113
- loadCallbacks = [];
166114
- beforeLoadCallbacks = [];
166115
- transformationRenderBlock = undefined;
166116
- url = "";
166117
- previewUrl = "";
166118
- isStorageUrl = false;
166119
- videoDimension;
166120
- board;
166121
- isPlaying = false;
166122
- shouldShowControls = false;
166123
- playBtnMbr = new Mbr;
166124
- currentTime = 0;
166125
- constructor({ url, videoDimension, previewUrl }, board, events, id = "", extension2 = "mp4") {
166126
- super();
166127
- this.events = events;
166128
- this.id = id;
166129
- this.extension = extension2;
166130
- this.isStorageUrl = !conf.getYouTubeId(url);
166131
- this.preview = createPlaceholderImage(videoDimension.width, videoDimension.height);
166132
- this.linkTo = new LinkTo(this.id, events);
166133
- this.board = board;
166134
- if (previewUrl) {
166135
- this.previewUrl = previewUrl;
166136
- this.setPreview(this.preview, previewUrl);
166137
- }
166138
- this.preview.onload = this.onLoad;
166139
- this.preview.onerror = this.onError;
166140
- if (url) {
166141
- this.setUrl(url);
166142
- }
166143
- this.videoDimension = videoDimension;
166144
- this.transformation = new Transformation(id, events);
166145
- this.linkTo.subject.subscribe(() => {
166146
- this.updateMbr();
166147
- this.subject.publish(this);
166148
- });
166149
- this.transformation.subject.subscribe(this.onTransform);
166150
- }
166151
- setCurrentTime(time) {
166152
- this.currentTime = time;
166153
- }
166154
- getCurrentTime() {
166155
- return this.currentTime;
166156
- }
166157
- onTransform = () => {
166158
- this.updateMbr();
166159
- this.subject.publish(this);
166160
- };
166161
- doOnceBeforeOnLoad = (callback) => {
166162
- this.loadCallbacks.push(callback);
166163
- };
166164
- doOnceOnLoad = (callback) => {
166165
- this.loadCallbacks.push(callback);
166166
- };
166167
- getStorageId() {
166168
- return this.url.split("/").pop();
166169
- }
166170
- getIsStorageUrl() {
166171
- return this.isStorageUrl;
166172
- }
166173
- setVideoData({ previewUrl, url }) {
166174
- this.emit({
166175
- class: "Video",
166176
- item: [this.id],
166177
- method: "updateVideoData",
166178
- data: { previewUrl, url, videoDimension: this.videoDimension }
166179
- });
166180
- }
166181
- applyVideoData({ previewUrl = "", url = "" }) {
166182
- this.previewUrl = previewUrl;
166183
- this.setPreview(this.preview, previewUrl);
166184
- this.setUrl(url);
166185
- }
166186
- setIsPlaying(isPlaying) {
166187
- this.isPlaying = isPlaying;
166188
- this.subject.publish(this);
166189
- }
166190
- getIsPlaying() {
166191
- return this.isPlaying;
166192
- }
166193
- setShouldShowControls(shouldShowControls) {
166194
- this.shouldShowControls = shouldShowControls;
166195
- this.subject.publish(this);
166196
- }
166197
- getShouldShowControls() {
166198
- return this.shouldShowControls;
166199
- }
166200
- getPlayBtnMbr() {
166201
- return this.playBtnMbr;
166202
- }
166203
- setUrl(url) {
166204
- if (this.isStorageUrl) {
166205
- try {
166206
- const newUrl = new URL(url);
166207
- this.url = `${window.location.origin}${newUrl.pathname}`;
166208
- } catch (_) {}
166209
- } else {
166210
- this.url = url;
166211
- }
166212
- }
166213
- setPreview(image, previewUrl) {
166214
- if (this.isStorageUrl) {
166215
- try {
166216
- const newUrl = new URL(previewUrl);
166217
- image.src = `${window.location.origin}${newUrl.pathname}`;
166218
- } catch (_) {}
166219
- } else {
166220
- image.src = previewUrl;
166221
- }
166222
- image.onload = () => {
166223
- this.preview = image;
166224
- };
166225
- }
166226
- setPreviewImage(image) {
166227
- this.preview = image;
166228
- this.preview.onload = this.onLoad;
166229
- this.preview.onerror = () => {
166230
- const defaultPreview = new Image;
166231
- defaultPreview.src = this.getPreviewUrl();
166232
- this.preview = defaultPreview;
166233
- this.preview.onload = this.onLoad;
166234
- this.preview.onerror = this.onError;
166235
- this.subject.publish(this);
166236
- };
166237
- this.subject.publish(this);
166238
- }
166239
- getPreviewUrl() {
166240
- return this.previewUrl;
166241
- }
166242
- getUrl() {
166243
- return this.url;
166244
- }
166245
- onLoad = async () => {
166246
- this.shootBeforeLoadCallbacks();
166247
- this.updateMbr();
166248
- this.subject.publish(this);
166249
- this.shootLoadCallbacks();
166250
- };
166251
- onError = (_error) => {
166252
- this.preview = createPlaceholderImage(this.videoDimension.width, this.videoDimension.height);
166253
- this.updateMbr();
166254
- this.subject.publish(this);
166255
- this.shootLoadCallbacks();
166256
- };
166257
- updateMbr() {
166258
- const { translateX, translateY, scaleX, scaleY } = this.transformation.matrix;
166259
- this.left = translateX;
166260
- this.top = translateY;
166261
- this.right = this.left + this.videoDimension.width * scaleX;
166262
- this.bottom = this.top + this.videoDimension.height * scaleY;
166263
- const playBtnSize = 50;
166264
- const scaledPlayBtn = playBtnSize * this.transformation.matrix.scaleX;
166265
- this.playBtnMbr = new Mbr(this.left + this.getWidth() / 2 - scaledPlayBtn / 2, this.top + this.getHeight() / 2 - scaledPlayBtn / 2, this.right - this.getWidth() / 2 + scaledPlayBtn / 2, this.bottom - this.getHeight() / 2 + scaledPlayBtn / 2);
166266
- }
166267
- render(context) {
166268
- if (this.transformationRenderBlock || !this.preview.complete) {
166269
- return;
166270
- }
166271
- const ctx = context.ctx;
166272
- if (this.isPlaying) {
166273
- ctx.save();
166274
- ctx.globalCompositeOperation = "destination-out";
166275
- ctx.fillRect(this.left, this.top, this.getWidth(), this.getHeight());
166276
- ctx.restore();
166277
- return;
166278
- }
166279
- ctx.save();
166280
- this.transformation.matrix.applyToContext(ctx);
166281
- ctx.drawImage(this.preview, 0, 0);
166282
- if (this.shouldShowControls && this.previewUrl) {
166283
- ctx.restore();
166284
- ctx.fillStyle = "rgba(0, 0, 0, 0.5)";
166285
- ctx.fillRect(this.left, this.top, this.getWidth(), this.getHeight());
166286
- const playBtnSize = this.playBtnMbr.getWidth();
166287
- const left = this.playBtnMbr.left;
166288
- const top = this.playBtnMbr.top;
166289
- ctx.fillStyle = "white";
166290
- ctx.beginPath();
166291
- ctx.moveTo(left, top);
166292
- ctx.lineTo(left + playBtnSize, top + playBtnSize / 2);
166293
- ctx.lineTo(left, top + playBtnSize);
166294
- ctx.closePath();
166295
- ctx.fill();
166296
- }
166297
- ctx.restore();
166298
- }
166299
- renderHTML(documentFactory) {
166300
- const div = documentFactory.createElement("video-item");
166301
- const { translateX, translateY, scaleX, scaleY } = this.transformation.matrix;
166302
- const transform = `translate(${translateX}px, ${translateY}px) scale(${scaleX}, ${scaleY})`;
166303
- div.style.backgroundImage = this.previewUrl ? `url(${this.previewUrl})` : `url(${createPlaceholderImage(this.videoDimension.width, this.videoDimension.height).src})`;
166304
- div.id = this.getId();
166305
- div.style.width = `${this.videoDimension.width}px`;
166306
- div.style.height = `${this.videoDimension.height}px`;
166307
- div.style.transformOrigin = "top left";
166308
- div.style.transform = transform;
166309
- div.style.position = "absolute";
166310
- div.style.backgroundSize = "cover";
166311
- div.setAttribute("video-url", this.getUrl());
166312
- div.setAttribute("preview-url", this.getPreviewUrl());
166313
- div.setAttribute("extension", this.extension);
166314
- div.setAttribute("is-storage-url", this.isStorageUrl ? "1" : "");
166315
- div.setAttribute("data-link-to", "");
166316
- return div;
166317
- }
166318
- serialize() {
166319
- return {
166320
- itemType: "Video",
166321
- url: this.url,
166322
- videoDimension: this.videoDimension,
166323
- transformation: this.transformation.serialize(),
166324
- isStorageUrl: this.isStorageUrl,
166325
- previewUrl: this.previewUrl,
166326
- extension: this.extension
166327
- };
166328
- }
166329
- deserialize(data) {
166330
- if (data.transformation) {
166331
- this.transformation.deserialize(data.transformation);
166332
- }
166333
- if (data.isStorageUrl) {
166334
- this.isStorageUrl = data.isStorageUrl;
166335
- }
166336
- if (data.url) {
166337
- this.setUrl(data.url);
166338
- }
166339
- if (data.extension) {
166340
- this.extension = data.extension;
166341
- }
166342
- this.preview = createPlaceholderImage(data.videoDimension?.width || 100, data.videoDimension?.height || 100);
166343
- const storageImage = new Image;
166344
- storageImage.onload = () => {
166345
- this.onLoad();
166346
- };
166347
- storageImage.onerror = this.onError;
166348
- if (data.previewUrl) {
166349
- this.setPreview(storageImage, data.previewUrl);
166350
- }
166351
- return this;
166352
- }
166353
- apply(op) {
166354
- switch (op.class) {
166355
- case "Transformation":
166356
- this.transformation.apply(op);
166357
- break;
166358
- case "LinkTo":
166359
- this.linkTo.apply(op);
166360
- break;
166361
- case "Video":
166362
- if (op.method === "updateVideoData") {
166363
- this.applyVideoData({
166364
- url: op.data.url,
166365
- previewUrl: op.data.previewUrl
166366
- });
166367
- }
166368
- this.subject.publish(this);
166369
- break;
166370
- }
166371
- }
166372
- emit(operation) {
166373
- if (this.events) {
166374
- const command = new VideoCommand([this], operation);
166375
- command.apply();
166376
- this.events.emit(operation, command);
166377
- } else {
166378
- this.apply(operation);
166379
- }
166380
- }
166381
- setId(id) {
166382
- this.id = id;
166383
- this.transformation.setId(id);
166384
- return this;
166385
- }
166386
- getId() {
166387
- return this.id;
166388
- }
166389
- shootLoadCallbacks() {
166390
- while (this.loadCallbacks.length > 0) {
166391
- this.loadCallbacks.shift()(this);
166392
- }
166393
- }
166394
- shootBeforeLoadCallbacks() {
166395
- while (this.beforeLoadCallbacks.length > 0) {
166396
- this.beforeLoadCallbacks.shift()(this);
166397
- }
166398
- }
166399
- getPath() {
166400
- const { left, top, right, bottom } = this.getMbr();
166401
- const leftTop = new Point(left, top);
166402
- const rightTop = new Point(right, top);
166403
- const rightBottom = new Point(right, bottom);
166404
- const leftBottom = new Point(left, bottom);
166405
- return new Path([
166406
- new Line(leftTop, rightTop),
166407
- new Line(rightTop, rightBottom),
166408
- new Line(rightBottom, leftBottom),
166409
- new Line(leftBottom, leftTop)
166410
- ], true);
166411
- }
166412
- getSnapAnchorPoints() {
166413
- const mbr = this.getMbr();
166414
- const width2 = mbr.getWidth();
166415
- const height2 = mbr.getHeight();
166416
- return [
166417
- new Point(mbr.left + width2 / 2, mbr.top),
166418
- new Point(mbr.left + width2 / 2, mbr.bottom),
166419
- new Point(mbr.left, mbr.top + height2 / 2),
166420
- new Point(mbr.right, mbr.top + height2 / 2)
166421
- ];
166422
- }
166423
- isClosed() {
166424
- return true;
166425
- }
166426
- getRichText() {
166427
- return null;
166428
- }
166429
- getLinkTo() {
166430
- return;
166431
- }
166432
- download() {
166433
- if (this.isStorageUrl) {
166434
- const linkElem = document.createElement("a");
166435
- linkElem.href = this.url;
166436
- linkElem.setAttribute("download", `${this.board.getBoardId()}.${this.extension}`);
166437
- linkElem.click();
166438
- }
166439
- }
166440
- }
166441
166801
  // src/itemFactories.ts
166442
166802
  var itemFactories = {
166443
166803
  Sticker: createSticker,
@@ -179073,7 +179433,7 @@ function createEventsLog(board) {
179073
179433
  return new EventsLog(board);
179074
179434
  }
179075
179435
  // src/Events/Events.ts
179076
- class Events {
179436
+ class Events2 {
179077
179437
  subject;
179078
179438
  log;
179079
179439
  board;
@@ -179199,7 +179559,7 @@ class Events {
179199
179559
  }
179200
179560
  }
179201
179561
  function createEvents(board, connection, lastIndex) {
179202
- return new Events(board, connection, lastIndex);
179562
+ return new Events2(board, connection, lastIndex);
179203
179563
  }
179204
179564
  // src/api/NodeDOMParser.ts
179205
179565
  function getNodeDOMParser() {
@@ -179354,5 +179714,5 @@ function initNodeSettings() {
179354
179714
  return conf;
179355
179715
  }
179356
179716
 
179357
- // src/node-entry.ts
179717
+ // src/node.ts
179358
179718
  initNodeSettings();