@netless/forge-whiteboard 1.2.0-alpha.1 → 1.2.0-beta.3

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.
Files changed (45) hide show
  1. package/changelog.md +13 -1
  2. package/dist/LiveCursor.d.ts +2 -1
  3. package/dist/LiveCursor.d.ts.map +1 -1
  4. package/dist/Whiteboard.d.ts +10 -0
  5. package/dist/Whiteboard.d.ts.map +1 -1
  6. package/dist/WhiteboardApplication.d.ts +6 -0
  7. package/dist/WhiteboardApplication.d.ts.map +1 -1
  8. package/dist/edit/Editor.d.ts.map +1 -1
  9. package/dist/model/RenderableModel.d.ts +15 -1
  10. package/dist/model/RenderableModel.d.ts.map +1 -1
  11. package/dist/model/renderable/CurveModel.d.ts +4 -3
  12. package/dist/model/renderable/CurveModel.d.ts.map +1 -1
  13. package/dist/model/renderable/ElementModel.d.ts +20 -1
  14. package/dist/model/renderable/ElementModel.d.ts.map +1 -1
  15. package/dist/model/renderable/EraserModel.d.ts +5 -1
  16. package/dist/model/renderable/EraserModel.d.ts.map +1 -1
  17. package/dist/model/renderable/ImageModel.d.ts +4 -1
  18. package/dist/model/renderable/ImageModel.d.ts.map +1 -1
  19. package/dist/model/renderable/LaserPointerModel.d.ts +8 -2
  20. package/dist/model/renderable/LaserPointerModel.d.ts.map +1 -1
  21. package/dist/model/renderable/LineModel.d.ts +5 -1
  22. package/dist/model/renderable/LineModel.d.ts.map +1 -1
  23. package/dist/model/renderable/PointTextModel.d.ts +6 -1
  24. package/dist/model/renderable/PointTextModel.d.ts.map +1 -1
  25. package/dist/model/renderable/RectangleModel.d.ts +5 -1
  26. package/dist/model/renderable/RectangleModel.d.ts.map +1 -1
  27. package/dist/model/renderable/SegmentsModel.d.ts +5 -1
  28. package/dist/model/renderable/SegmentsModel.d.ts.map +1 -1
  29. package/dist/model/renderable/SelectorModel.d.ts +5 -1
  30. package/dist/model/renderable/SelectorModel.d.ts.map +1 -1
  31. package/dist/model/renderable/StraightLineModel.d.ts +5 -1
  32. package/dist/model/renderable/StraightLineModel.d.ts.map +1 -1
  33. package/dist/model/renderable/TriangleModel.d.ts +5 -1
  34. package/dist/model/renderable/TriangleModel.d.ts.map +1 -1
  35. package/dist/tool/CurveTool.d.ts +3 -0
  36. package/dist/tool/CurveTool.d.ts.map +1 -1
  37. package/dist/tool/LaserPointerTool.d.ts.map +1 -1
  38. package/dist/tool/WhiteboardTool.d.ts +4 -0
  39. package/dist/tool/WhiteboardTool.d.ts.map +1 -1
  40. package/dist/utils/paperjs.d.ts.map +1 -1
  41. package/dist/whiteboard.esm.js +757 -268
  42. package/dist/whiteboard.esm.js.map +3 -3
  43. package/dist/whiteboard.js +793 -304
  44. package/dist/whiteboard.js.map +3 -3
  45. package/package.json +2 -2
@@ -20839,8 +20839,8 @@ var require_lodash = __commonJS({
20839
20839
  }
20840
20840
  var runInContext = function runInContext2(context) {
20841
20841
  context = context == null ? root : _.defaults(root.Object(), context, _.pick(root, contextProps));
20842
- var Array13 = context.Array, Date2 = context.Date, Error2 = context.Error, Function2 = context.Function, Math2 = context.Math, Object2 = context.Object, RegExp2 = context.RegExp, String2 = context.String, TypeError2 = context.TypeError;
20843
- var arrayProto = Array13.prototype, funcProto = Function2.prototype, objectProto = Object2.prototype;
20842
+ var Array14 = context.Array, Date2 = context.Date, Error2 = context.Error, Function2 = context.Function, Math2 = context.Math, Object2 = context.Object, RegExp2 = context.RegExp, String2 = context.String, TypeError2 = context.TypeError;
20843
+ var arrayProto = Array14.prototype, funcProto = Function2.prototype, objectProto = Object2.prototype;
20844
20844
  var coreJsData = context["__core-js_shared__"];
20845
20845
  var funcToString = funcProto.toString;
20846
20846
  var hasOwnProperty = objectProto.hasOwnProperty;
@@ -21263,7 +21263,7 @@ var require_lodash = __commonJS({
21263
21263
  }
21264
21264
  }
21265
21265
  function baseAt(object, paths) {
21266
- var index = -1, length = paths.length, result2 = Array13(length), skip = object == null;
21266
+ var index = -1, length = paths.length, result2 = Array14(length), skip = object == null;
21267
21267
  while (++index < length) {
21268
21268
  result2[index] = skip ? undefined2 : get(object, paths[index]);
21269
21269
  }
@@ -21509,7 +21509,7 @@ var require_lodash = __commonJS({
21509
21509
  return number >= nativeMin(start, end) && number < nativeMax(start, end);
21510
21510
  }
21511
21511
  function baseIntersection(arrays, iteratee2, comparator) {
21512
- var includes2 = comparator ? arrayIncludesWith : arrayIncludes, length = arrays[0].length, othLength = arrays.length, othIndex = othLength, caches = Array13(othLength), maxLength = Infinity, result2 = [];
21512
+ var includes2 = comparator ? arrayIncludesWith : arrayIncludes, length = arrays[0].length, othLength = arrays.length, othIndex = othLength, caches = Array14(othLength), maxLength = Infinity, result2 = [];
21513
21513
  while (othIndex--) {
21514
21514
  var array = arrays[othIndex];
21515
21515
  if (othIndex && iteratee2) {
@@ -21690,7 +21690,7 @@ var require_lodash = __commonJS({
21690
21690
  return value < other;
21691
21691
  }
21692
21692
  function baseMap(collection, iteratee2) {
21693
- var index = -1, result2 = isArrayLike(collection) ? Array13(collection.length) : [];
21693
+ var index = -1, result2 = isArrayLike(collection) ? Array14(collection.length) : [];
21694
21694
  baseEach(collection, function(value, key, collection2) {
21695
21695
  result2[++index] = iteratee2(value, key, collection2);
21696
21696
  });
@@ -21865,7 +21865,7 @@ var require_lodash = __commonJS({
21865
21865
  return lower + nativeFloor(nativeRandom() * (upper - lower + 1));
21866
21866
  }
21867
21867
  function baseRange(start, end, step, fromRight) {
21868
- var index = -1, length = nativeMax(nativeCeil((end - start) / (step || 1)), 0), result2 = Array13(length);
21868
+ var index = -1, length = nativeMax(nativeCeil((end - start) / (step || 1)), 0), result2 = Array14(length);
21869
21869
  while (length--) {
21870
21870
  result2[fromRight ? length : ++index] = start;
21871
21871
  start += step;
@@ -21947,7 +21947,7 @@ var require_lodash = __commonJS({
21947
21947
  }
21948
21948
  length = start > end ? 0 : end - start >>> 0;
21949
21949
  start >>>= 0;
21950
- var result2 = Array13(length);
21950
+ var result2 = Array14(length);
21951
21951
  while (++index < length) {
21952
21952
  result2[index] = array[index + start];
21953
21953
  }
@@ -22107,7 +22107,7 @@ var require_lodash = __commonJS({
22107
22107
  if (length < 2) {
22108
22108
  return length ? baseUniq(arrays[0]) : [];
22109
22109
  }
22110
- var index = -1, result2 = Array13(length);
22110
+ var index = -1, result2 = Array14(length);
22111
22111
  while (++index < length) {
22112
22112
  var array = arrays[index], othIndex = -1;
22113
22113
  while (++othIndex < length) {
@@ -22204,7 +22204,7 @@ var require_lodash = __commonJS({
22204
22204
  return object.index - other.index;
22205
22205
  }
22206
22206
  function composeArgs(args, partials, holders, isCurried) {
22207
- var argsIndex = -1, argsLength = args.length, holdersLength = holders.length, leftIndex = -1, leftLength = partials.length, rangeLength = nativeMax(argsLength - holdersLength, 0), result2 = Array13(leftLength + rangeLength), isUncurried = !isCurried;
22207
+ var argsIndex = -1, argsLength = args.length, holdersLength = holders.length, leftIndex = -1, leftLength = partials.length, rangeLength = nativeMax(argsLength - holdersLength, 0), result2 = Array14(leftLength + rangeLength), isUncurried = !isCurried;
22208
22208
  while (++leftIndex < leftLength) {
22209
22209
  result2[leftIndex] = partials[leftIndex];
22210
22210
  }
@@ -22219,7 +22219,7 @@ var require_lodash = __commonJS({
22219
22219
  return result2;
22220
22220
  }
22221
22221
  function composeArgsRight(args, partials, holders, isCurried) {
22222
- var argsIndex = -1, argsLength = args.length, holdersIndex = -1, holdersLength = holders.length, rightIndex = -1, rightLength = partials.length, rangeLength = nativeMax(argsLength - holdersLength, 0), result2 = Array13(rangeLength + rightLength), isUncurried = !isCurried;
22222
+ var argsIndex = -1, argsLength = args.length, holdersIndex = -1, holdersLength = holders.length, rightIndex = -1, rightLength = partials.length, rangeLength = nativeMax(argsLength - holdersLength, 0), result2 = Array14(rangeLength + rightLength), isUncurried = !isCurried;
22223
22223
  while (++argsIndex < rangeLength) {
22224
22224
  result2[argsIndex] = args[argsIndex];
22225
22225
  }
@@ -22236,7 +22236,7 @@ var require_lodash = __commonJS({
22236
22236
  }
22237
22237
  function copyArray(source, array) {
22238
22238
  var index = -1, length = source.length;
22239
- array || (array = Array13(length));
22239
+ array || (array = Array14(length));
22240
22240
  while (++index < length) {
22241
22241
  array[index] = source[index];
22242
22242
  }
@@ -22369,7 +22369,7 @@ var require_lodash = __commonJS({
22369
22369
  function createCurry(func, bitmask, arity) {
22370
22370
  var Ctor = createCtor(func);
22371
22371
  function wrapper() {
22372
- var length = arguments.length, args = Array13(length), index = length, placeholder = getHolder(wrapper);
22372
+ var length = arguments.length, args = Array14(length), index = length, placeholder = getHolder(wrapper);
22373
22373
  while (index--) {
22374
22374
  args[index] = arguments[index];
22375
22375
  }
@@ -22449,7 +22449,7 @@ var require_lodash = __commonJS({
22449
22449
  function createHybrid(func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary2, arity) {
22450
22450
  var isAry = bitmask & WRAP_ARY_FLAG, isBind = bitmask & WRAP_BIND_FLAG, isBindKey = bitmask & WRAP_BIND_KEY_FLAG, isCurried = bitmask & (WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG), isFlip = bitmask & WRAP_FLIP_FLAG, Ctor = isBindKey ? undefined2 : createCtor(func);
22451
22451
  function wrapper() {
22452
- var length = arguments.length, args = Array13(length), index = length;
22452
+ var length = arguments.length, args = Array14(length), index = length;
22453
22453
  while (index--) {
22454
22454
  args[index] = arguments[index];
22455
22455
  }
@@ -22548,7 +22548,7 @@ var require_lodash = __commonJS({
22548
22548
  function createPartial(func, bitmask, thisArg, partials) {
22549
22549
  var isBind = bitmask & WRAP_BIND_FLAG, Ctor = createCtor(func);
22550
22550
  function wrapper() {
22551
- var argsIndex = -1, argsLength = arguments.length, leftIndex = -1, leftLength = partials.length, args = Array13(leftLength + argsLength), fn = this && this !== root && this instanceof wrapper ? Ctor : func;
22551
+ var argsIndex = -1, argsLength = arguments.length, leftIndex = -1, leftLength = partials.length, args = Array14(leftLength + argsLength), fn = this && this !== root && this instanceof wrapper ? Ctor : func;
22552
22552
  while (++leftIndex < leftLength) {
22553
22553
  args[leftIndex] = partials[leftIndex];
22554
22554
  }
@@ -23161,12 +23161,12 @@ var require_lodash = __commonJS({
23161
23161
  function overRest(func, start, transform2) {
23162
23162
  start = nativeMax(start === undefined2 ? func.length - 1 : start, 0);
23163
23163
  return function() {
23164
- var args = arguments, index = -1, length = nativeMax(args.length - start, 0), array = Array13(length);
23164
+ var args = arguments, index = -1, length = nativeMax(args.length - start, 0), array = Array14(length);
23165
23165
  while (++index < length) {
23166
23166
  array[index] = args[start + index];
23167
23167
  }
23168
23168
  index = -1;
23169
- var otherArgs = Array13(start + 1);
23169
+ var otherArgs = Array14(start + 1);
23170
23170
  while (++index < start) {
23171
23171
  otherArgs[index] = args[index];
23172
23172
  }
@@ -23288,7 +23288,7 @@ var require_lodash = __commonJS({
23288
23288
  if (!length || size2 < 1) {
23289
23289
  return [];
23290
23290
  }
23291
- var index = 0, resIndex = 0, result2 = Array13(nativeCeil(length / size2));
23291
+ var index = 0, resIndex = 0, result2 = Array14(nativeCeil(length / size2));
23292
23292
  while (index < length) {
23293
23293
  result2[resIndex++] = baseSlice(array, index, index += size2);
23294
23294
  }
@@ -23309,7 +23309,7 @@ var require_lodash = __commonJS({
23309
23309
  if (!length) {
23310
23310
  return [];
23311
23311
  }
23312
- var args = Array13(length - 1), array = arguments[0], index = length;
23312
+ var args = Array14(length - 1), array = arguments[0], index = length;
23313
23313
  while (index--) {
23314
23314
  args[index - 1] = arguments[index];
23315
23315
  }
@@ -23811,7 +23811,7 @@ var require_lodash = __commonJS({
23811
23811
  return isString(collection) ? fromIndex <= length && collection.indexOf(value, fromIndex) > -1 : !!length && baseIndexOf(collection, value, fromIndex) > -1;
23812
23812
  }
23813
23813
  var invokeMap = baseRest(function(collection, path, args) {
23814
- var index = -1, isFunc = typeof path == "function", result2 = isArrayLike(collection) ? Array13(collection.length) : [];
23814
+ var index = -1, isFunc = typeof path == "function", result2 = isArrayLike(collection) ? Array14(collection.length) : [];
23815
23815
  baseEach(collection, function(value) {
23816
23816
  result2[++index] = isFunc ? apply(path, value, args) : baseInvoke(value, path, args);
23817
23817
  });
@@ -24194,7 +24194,7 @@ var require_lodash = __commonJS({
24194
24194
  }()) ? baseIsArguments : function(value) {
24195
24195
  return isObjectLike(value) && hasOwnProperty.call(value, "callee") && !propertyIsEnumerable.call(value, "callee");
24196
24196
  };
24197
- var isArray = Array13.isArray;
24197
+ var isArray = Array14.isArray;
24198
24198
  var isArrayBuffer = nodeIsArrayBuffer ? baseUnary(nodeIsArrayBuffer) : baseIsArrayBuffer;
24199
24199
  function isArrayLike(value) {
24200
24200
  return value != null && isLength(value.length) && !isFunction(value);
@@ -25637,9 +25637,10 @@ import * as Y15 from "yjs";
25637
25637
  import * as Y12 from "yjs";
25638
25638
  import EventEmitter from "eventemitter3";
25639
25639
  import { v4 as uuidv4 } from "uuid";
25640
- import { log, removeObserver as removeObserver2 } from "@netless/forge-room";
25640
+ import { log, removeObserver as removeObserver3 } from "@netless/forge-room";
25641
25641
 
25642
25642
  // src/model/renderable/CurveModel.ts
25643
+ var import_lodash = __toESM(require_lodash(), 1);
25643
25644
  import * as Y2 from "yjs";
25644
25645
 
25645
25646
  // ../../node_modules/.pnpm/perfect-freehand@1.2.2/node_modules/perfect-freehand/dist/esm/index.mjs
@@ -25790,9 +25791,6 @@ function ae(e, t = {}) {
25790
25791
  return ce(me(e, t), t);
25791
25792
  }
25792
25793
 
25793
- // src/model/renderable/CurveModel.ts
25794
- var import_lodash = __toESM(require_lodash(), 1);
25795
-
25796
25794
  // src/model/renderable/ElementModel.ts
25797
25795
  import * as Y from "yjs";
25798
25796
  import { removeDeepObserver } from "@netless/forge-room";
@@ -25880,12 +25878,23 @@ var ElementModel = class _ElementModel {
25880
25878
  set shadow(value) {
25881
25879
  this.root.set(_ElementModel.KEYS.shadow, value);
25882
25880
  }
25883
- constructor(root, scope, liveCursor) {
25881
+ get isPerformanceEnvironment() {
25882
+ return this.isPerformanceMode() && this.shouldUseLocalPoints;
25883
+ }
25884
+ constructor(root, scope, liveCursor, isPerformanceMode) {
25884
25885
  _defineProperty(this, "shadowEmitter", null);
25885
25886
  _defineProperty(this, "root", void 0);
25886
25887
  _defineProperty(this, "scope", void 0);
25887
25888
  _defineProperty(this, "item", void 0);
25889
+ _defineProperty(this, "clearLocalPointsWhenYPointsChange", void 0);
25890
+ _defineProperty(this, "shouldUseLocalPoints", void 0);
25891
+ _defineProperty(this, "localPointsPick", void 0);
25888
25892
  _defineProperty(this, "liveCursor", void 0);
25893
+ _defineProperty(this, "appendPointsTimer", null);
25894
+ _defineProperty(this, "setPointsTimer", null);
25895
+ _defineProperty(this, "pointsUpdateTimer", null);
25896
+ _defineProperty(this, "isPerformanceMode", void 0);
25897
+ _defineProperty(this, "localPoints", []);
25889
25898
  _defineProperty(this, "handlePropChange", (events) => {
25890
25899
  if (!this.item) {
25891
25900
  return;
@@ -25924,23 +25933,80 @@ var ElementModel = class _ElementModel {
25924
25933
  }
25925
25934
  }
25926
25935
  } else if (event.target === this.root.get(_ElementModel.KEYS.points)) {
25927
- this.onVectorUpdate();
25928
- const liveCursorPoint = this.liveCursorPoint();
25929
- const ownerId = this.root.get(_ElementModel.KEYS.ownerId);
25930
- if (liveCursorPoint && ownerId) {
25931
- this.liveCursor.updateCursorPosition(liveCursorPoint, this.root.get(_ElementModel.KEYS.ownerId));
25936
+ if (this.isPerformanceEnvironment) {
25937
+ this.handlePointsChangePerformance();
25938
+ } else {
25939
+ this.handlePointsChangeDirect();
25932
25940
  }
25933
25941
  } else {
25934
25942
  }
25935
25943
  }
25936
25944
  });
25945
+ _defineProperty(this, "onPointsArrayChange", (points) => {
25946
+ if (this.localPoints.length >= points.length) {
25947
+ return;
25948
+ }
25949
+ const pointsChunk = points.slice(this.localPoints.length, this.localPoints.length + this.localPointsPick);
25950
+ this.localPoints = this.localPoints.concat(pointsChunk);
25951
+ this.onVectorUpdate();
25952
+ this.pointsUpdateTimer = window.requestAnimationFrame(() => {
25953
+ this.onPointsArrayChange(points);
25954
+ });
25955
+ });
25956
+ this.isPerformanceMode = isPerformanceMode;
25937
25957
  this.scope = scope;
25938
25958
  this.liveCursor = liveCursor;
25939
25959
  this.root = root;
25940
- if (!this.root.has(_ElementModel.KEYS.pointsMatrix)) {
25960
+ if (this.root.doc) {
25961
+ if (!this.root.has(_ElementModel.KEYS.pointsMatrix)) {
25962
+ this.root.set(_ElementModel.KEYS.pointsMatrix, [1, 0, 0, 1, 0, 0]);
25963
+ }
25964
+ } else {
25941
25965
  this.root.set(_ElementModel.KEYS.pointsMatrix, [1, 0, 0, 1, 0, 0]);
25942
25966
  }
25967
+ }
25968
+ bindObserver() {
25969
+ const beforeL = this.root._eH?.l?.length ?? -1;
25970
+ const beforeDL = this.root._dEH?.l?.length ?? -1;
25971
+ removeDeepObserver(this.root, this.handlePropChange);
25972
+ this.subBindObserver();
25973
+ const afterRemoveL = this.root._eH?.l?.length ?? -1;
25974
+ const afterRemoveDL = this.root._dEH?.l?.length ?? -1;
25943
25975
  this.root.observeDeep(this.handlePropChange);
25976
+ const afterAddL = this.root._eH?.l?.length ?? -1;
25977
+ const afterAddDL = this.root._dEH?.l?.length ?? -1;
25978
+ console.log(`[][][] bindObserver uuid=${this.uuid} doc=${!!this.root.doc} _eH: ${beforeL}->${afterRemoveL}->${afterAddL} _dEH: ${beforeDL}->${afterRemoveDL}->${afterAddDL}`);
25979
+ }
25980
+ subBindObserver() {
25981
+ }
25982
+ handlePointsChangeDirect() {
25983
+ this.onVectorUpdate();
25984
+ const liveCursorPoint = this.liveCursorPoint();
25985
+ const ownerId = this.root.get(_ElementModel.KEYS.ownerId);
25986
+ if (liveCursorPoint && ownerId) {
25987
+ this.liveCursor.updateCursorPosition(liveCursorPoint, this.root.get(_ElementModel.KEYS.ownerId));
25988
+ }
25989
+ }
25990
+ handlePointsChangePerformance() {
25991
+ const liveCursorPoint = this.liveCursorPoint();
25992
+ const ownerId = this.root.get(_ElementModel.KEYS.ownerId);
25993
+ if (liveCursorPoint && ownerId) {
25994
+ this.liveCursor.updateCursorPosition(liveCursorPoint, this.root.get(_ElementModel.KEYS.ownerId));
25995
+ }
25996
+ if (this.liveCursor.userManager.selfId !== ownerId || this.localPoints.length === 0) {
25997
+ if (this.pointsUpdateTimer) {
25998
+ window.cancelAnimationFrame(this.pointsUpdateTimer);
25999
+ }
26000
+ if (this.shadow == "") {
26001
+ this.localPoints = this.points;
26002
+ this.onVectorUpdate();
26003
+ } else {
26004
+ if (this.clearLocalPointsWhenYPointsChange) {
26005
+ this.localPoints = [];
26006
+ }
26007
+ this.onPointsArrayChange(this.points);
26008
+ }
26009
+ }
25944
26010
  }
25945
26011
  createPaperElement() {
25946
26012
  this.createPaperItem();
@@ -25953,14 +26019,48 @@ var ElementModel = class _ElementModel {
25953
26019
  }
25954
26020
  }
25955
26021
  appendPoints(points) {
26022
+ if (this.isPerformanceEnvironment) {
26023
+ this.appendPointsPerformance(points);
26024
+ } else {
26025
+ this.appendPointsDirect(points);
26026
+ }
26027
+ }
26028
+ appendPointsDirect(points) {
25956
26029
  this.root.get(_ElementModel.KEYS.points).push(points);
25957
26030
  }
26031
+ appendPointsPerformance(points) {
26032
+ this.localPoints = this.localPoints.concat(points);
26033
+ this.onVectorUpdate();
26034
+ if (this.appendPointsTimer) {
26035
+ window.clearTimeout(this.appendPointsTimer);
26036
+ }
26037
+ if (this.localPoints.length % 80 === 0) {
26038
+ const yArray = this.root.get(_ElementModel.KEYS.points);
26039
+ yArray?.push(this.localPoints.slice(yArray.length));
26040
+ }
26041
+ this.appendPointsTimer = window.setTimeout(() => {
26042
+ this.appendPointsTimer = null;
26043
+ if (this.localPoints.length > 0) {
26044
+ const yArray = this.root.get(_ElementModel.KEYS.points);
26045
+ yArray?.push(this.localPoints.slice(yArray.length));
26046
+ }
26047
+ }, 100);
26048
+ }
25958
26049
  setPoints(points) {
26050
+ if (this.isPerformanceEnvironment) {
26051
+ this.setPointsPerformance(points);
26052
+ } else {
26053
+ this.setPointsDirect(points);
26054
+ }
26055
+ }
26056
+ setPointsDirect(points) {
25959
26057
  if (this.root.doc) {
25960
26058
  this.root.doc.transact(() => {
25961
26059
  const yArray = this.root.get(_ElementModel.KEYS.points);
25962
- yArray.delete(0, yArray.length);
25963
- yArray.push(points);
26060
+ if (yArray) {
26061
+ yArray.delete(0, yArray.length);
26062
+ yArray.push(points);
26063
+ }
25964
26064
  });
25965
26065
  } else {
25966
26066
  const yArray = this.root.get(_ElementModel.KEYS.points) || new Y.Array();
@@ -25969,6 +26069,29 @@ var ElementModel = class _ElementModel {
25969
26069
  this.root.set(_ElementModel.KEYS.points, yArray);
25970
26070
  }
25971
26071
  }
26072
+ setPointsPerformance(points) {
26073
+ this.localPoints = points;
26074
+ this.onVectorUpdate();
26075
+ if (this.setPointsTimer) {
26076
+ window.clearTimeout(this.setPointsTimer);
26077
+ }
26078
+ this.setPointsTimer = window.setTimeout(() => {
26079
+ if (this.root.doc) {
26080
+ this.root.doc.transact(() => {
26081
+ const yArray = this.root.get(_ElementModel.KEYS.points);
26082
+ if (yArray) {
26083
+ yArray.delete(0, yArray.length);
26084
+ yArray.push(points);
26085
+ }
26086
+ });
26087
+ } else {
26088
+ const yArray = this.root.get(_ElementModel.KEYS.points) || new Y.Array();
26089
+ yArray.delete(0, yArray.length);
26090
+ yArray.push(points);
26091
+ this.root.set(_ElementModel.KEYS.points, yArray);
26092
+ }
26093
+ }, 100);
26094
+ }
25972
26095
  appendPointsMatrix(matrix) {
25973
26096
  const current = new this.scope.Matrix(this.pointsMatrix);
25974
26097
  const next = matrix.appended(current);
@@ -25995,6 +26118,9 @@ var ElementModel = class _ElementModel {
25995
26118
  }
25996
26119
  dispose() {
25997
26120
  this.subDispose();
26121
+ }
26122
+ disposeObserver() {
26123
+ console.log(`[][][] disposeObserver uuid=${this.uuid}`);
25998
26124
  removeDeepObserver(this.root, this.handlePropChange);
25999
26125
  }
26000
26126
  };
@@ -26067,49 +26193,50 @@ function _toPrimitive3(t, r) {
26067
26193
  return ("string" === r ? String : Number)(t);
26068
26194
  }
26069
26195
  var CurveModel = class extends ElementModel {
26070
- constructor(root, scope, liveCursor) {
26071
- super(root, scope, liveCursor);
26196
+ constructor(root, scope, liveCursor, isPerformanceMode) {
26197
+ super(root, scope, liveCursor, isPerformanceMode);
26072
26198
  _defineProperty3(this, "item", null);
26073
- _defineProperty3(this, "debugPath", void 0);
26074
26199
  _defineProperty3(this, "debug", false);
26075
- if (!this.root.has("type")) {
26200
+ _defineProperty3(this, "clearLocalPointsWhenYPointsChange", false);
26201
+ _defineProperty3(this, "shouldUseLocalPoints", true);
26202
+ _defineProperty3(this, "localPointsPick", 4);
26203
+ if (!this.root.doc || !this.root.has("type")) {
26076
26204
  this.root.set("type", "curve");
26077
26205
  }
26078
- if (!this.root.has("points")) {
26206
+ if (!this.root.doc || !this.root.has("points")) {
26079
26207
  this.root.set("points", new Y2.Array());
26080
26208
  }
26081
- this.debugPath = new scope.Path();
26082
26209
  }
26083
26210
  average(a2, b2) {
26084
26211
  return (a2 + b2) / 2;
26085
26212
  }
26086
26213
  parsePoints(points) {
26214
+ const viewScale = this.scope.project.view.matrix.scaling.x || 1;
26215
+ const taper = this.strokeWidth * 5 / viewScale;
26216
+ const streamline = Math.min(0.7, 0.7 * viewScale);
26087
26217
  return ae(points, {
26088
26218
  size: this.strokeWidth,
26089
- smoothing: 0.5,
26090
- thinning: -0.5,
26091
- streamline: 0.5,
26219
+ smoothing: 0.7,
26220
+ thinning: 0.5,
26221
+ streamline,
26092
26222
  simulatePressure: true,
26093
26223
  start: {
26094
- taper: this.strokeWidth * 10,
26224
+ taper,
26095
26225
  cap: true
26096
26226
  },
26097
26227
  end: {
26098
- taper: this.strokeWidth * 20,
26228
+ taper,
26099
26229
  cap: true
26100
26230
  }
26101
26231
  });
26102
26232
  }
26103
26233
  matrixedPoints() {
26104
- const points = this.points;
26234
+ const points = this.localPoints.length === 0 ? this.points : this.localPoints;
26105
26235
  const matrix = new this.scope.Matrix(this.pointsMatrix);
26106
- const output = [];
26107
- for (let i = 0, len = points.length; i < len; i += 2) {
26108
- const p = new this.scope.Point(points[i], points[i + 1]);
26109
- const tp = p.transform(matrix);
26110
- output.push([tp.x, tp.y]);
26111
- }
26112
- return output;
26236
+ return (0, import_lodash.chunk)(points, 2).filter((point) => point.length === 2).map((_ref) => {
26237
+ let [x, y] = _ref;
26238
+ return new this.scope.Point(x, y).transform(matrix);
26239
+ }).map((point) => [point.x, point.y]);
26113
26240
  }
26114
26241
  createPath(points) {
26115
26242
  const path = new this.scope.Path();
@@ -26136,34 +26263,30 @@ var CurveModel = class extends ElementModel {
26136
26263
  }
26137
26264
  return path;
26138
26265
  }
26139
- updateDebugPath() {
26140
- this.debugPath = new this.scope.Path();
26141
- const points = (0, import_lodash.chunk)(this.points, 2);
26142
- for (let i = 0, len = points.length; i < len; i++) {
26143
- const point = new this.scope.Point(points[i][0], points[i][1]);
26144
- if (i === 0) {
26145
- this.debugPath.moveTo(point);
26146
- } else {
26147
- this.debugPath.lineTo(point);
26148
- }
26149
- this.debugPath.strokeWidth = 1;
26150
- this.debugPath.strokeColor = new this.scope.Color(1, 0, 0, 1);
26151
- }
26152
- }
26153
26266
  onVectorUpdate() {
26154
26267
  if (!this.item) {
26155
26268
  return;
26156
26269
  }
26270
+ const matrixedPts = this.matrixedPoints();
26157
26271
  if (this.debug) {
26158
- this.debugPath.remove();
26159
- this.updateDebugPath();
26160
- }
26161
- const points = this.parsePoints(this.matrixedPoints());
26162
- const path = this.createPath(points);
26163
- this.item.removeSegments();
26164
- this.item.addSegments(path.segments);
26165
- if (this.debug) {
26166
- this.item.addChild(this.debugPath);
26272
+ const path = new this.scope.Path();
26273
+ for (let i = 0; i < matrixedPts.length; i++) {
26274
+ const p = new this.scope.Point(matrixedPts[i][0], matrixedPts[i][1]);
26275
+ if (i === 0) {
26276
+ path.moveTo(p);
26277
+ } else {
26278
+ path.lineTo(p);
26279
+ }
26280
+ }
26281
+ this.item.removeSegments();
26282
+ this.item.addSegments(path.segments);
26283
+ this.item.fillColor = null;
26284
+ this.item.strokeWidth = this.strokeWidth;
26285
+ } else {
26286
+ const points = this.parsePoints(matrixedPts);
26287
+ const path = this.createPath(points);
26288
+ this.item.removeSegments();
26289
+ this.item.addSegments(path.segments);
26167
26290
  }
26168
26291
  }
26169
26292
  createPaperItem() {
@@ -26186,11 +26309,12 @@ var CurveModel = class extends ElementModel {
26186
26309
  }
26187
26310
  liveCursorPoint() {
26188
26311
  const yArray = this.root.get(ElementModel.KEYS.points);
26189
- if (yArray.length < 2) {
26312
+ const points = yArray.toArray();
26313
+ if (points.length < 2) {
26190
26314
  return null;
26191
26315
  }
26192
- const len = yArray.length;
26193
- const point = new this.scope.Point(yArray.get(len - 2), yArray.get(len - 1));
26316
+ const len = points.length;
26317
+ const point = new this.scope.Point(points[len - 2], points[len - 1]);
26194
26318
  return point.transform(new this.scope.Matrix(this.pointsMatrix));
26195
26319
  }
26196
26320
  onStyleKeyUpdate(key) {
@@ -26228,15 +26352,24 @@ function _toPrimitive4(t, r) {
26228
26352
  return ("string" === r ? String : Number)(t);
26229
26353
  }
26230
26354
  var SelectorModel = class extends ElementModel {
26231
- constructor(root, scope, liveCursor) {
26232
- super(root, scope, liveCursor);
26355
+ get drawPoints() {
26356
+ if (this.localPoints.length >= 4) {
26357
+ return this.localPoints;
26358
+ }
26359
+ return this.points;
26360
+ }
26361
+ constructor(root, scope, liveCursor, isPerformanceMode) {
26362
+ super(root, scope, liveCursor, isPerformanceMode);
26233
26363
  _defineProperty4(this, "item", null);
26234
- if (!this.root.has("type")) {
26364
+ _defineProperty4(this, "clearLocalPointsWhenYPointsChange", true);
26365
+ _defineProperty4(this, "shouldUseLocalPoints", true);
26366
+ _defineProperty4(this, "localPointsPick", 4);
26367
+ if (this.root.doc && !this.root.has("type")) {
26235
26368
  this.root.set("type", "selector");
26236
26369
  }
26237
- if (!this.root.has("points")) {
26370
+ if (this.root.doc && !this.root.has("points")) {
26238
26371
  const initPoints = new Y3.Array();
26239
- initPoints.push([0, 0, 0, 0, 0]);
26372
+ initPoints.push([0, 0, 0, 0]);
26240
26373
  this.root.set("points", initPoints);
26241
26374
  }
26242
26375
  }
@@ -26247,8 +26380,8 @@ var SelectorModel = class extends ElementModel {
26247
26380
  }
26248
26381
  createPaperRect() {
26249
26382
  const scope = this.scope;
26250
- const bounds = new scope.Rectangle(new scope.Point(this.points[0], this.points[1]), new scope.Size(this.points[2], this.points[3]));
26251
- return new scope.Path.Rectangle(bounds, new scope.Point(this.points[4], this.points[4]));
26383
+ const bounds = new scope.Rectangle(new scope.Point(this.drawPoints[0], this.drawPoints[1]), new scope.Size(this.drawPoints[2], this.drawPoints[3]));
26384
+ return new scope.Path.Rectangle(bounds);
26252
26385
  }
26253
26386
  onVectorUpdate() {
26254
26387
  if (!this.item) {
@@ -26283,6 +26416,7 @@ import * as Y4 from "yjs";
26283
26416
 
26284
26417
  // src/utils/paperjs.ts
26285
26418
  var import_lodash2 = __toESM(require_lodash(), 1);
26419
+ import { metrics } from "@netless/forge-room";
26286
26420
  function _defineProperty5(e, r, t) {
26287
26421
  return (r = _toPropertyKey5(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: true, configurable: true, writable: true }) : e[r] = t, e;
26288
26422
  }
@@ -26325,7 +26459,27 @@ var AnimationFrame = class {
26325
26459
  _defineProperty5(this, "callbacks", []);
26326
26460
  _defineProperty5(this, "lastTime", 0);
26327
26461
  _defineProperty5(this, "fps", 45);
26462
+ _defineProperty5(this, "lastCallbackTime", 0);
26463
+ _defineProperty5(this, "fpsBuffer", []);
26464
+ _defineProperty5(this, "FPS_REPORT_INTERVAL", 2700);
26328
26465
  _defineProperty5(this, "handleCallbacks", () => {
26466
+ const now = performance.now();
26467
+ if (this.lastCallbackTime > 0) {
26468
+ const actualFps = 1e3 / (now - this.lastCallbackTime);
26469
+ this.fpsBuffer.push(actualFps);
26470
+ if (this.fpsBuffer.length >= this.FPS_REPORT_INTERVAL) {
26471
+ const avg = this.fpsBuffer.reduce((a2, b2) => a2 + b2, 0) / this.fpsBuffer.length;
26472
+ const min = Math.min(...this.fpsBuffer);
26473
+ const sorted = [...this.fpsBuffer].sort((a2, b2) => a2 - b2);
26474
+ const p90 = sorted[Math.floor(sorted.length * 0.9)];
26475
+ metrics().gauge("fps", Math.round(avg), {
26476
+ min: Math.round(min),
26477
+ p90: Math.round(p90)
26478
+ });
26479
+ this.fpsBuffer = [];
26480
+ }
26481
+ }
26482
+ this.lastCallbackTime = now;
26329
26483
  const functions = this.callbacks;
26330
26484
  this.callbacks = [];
26331
26485
  for (let i = 0, l2 = functions.length; i < l2; i++) {
@@ -26369,13 +26523,22 @@ function _toPrimitive6(t, r) {
26369
26523
  return ("string" === r ? String : Number)(t);
26370
26524
  }
26371
26525
  var SegmentsModel = class extends ElementModel {
26372
- constructor(root, scope, type, liveCursor) {
26373
- super(root, scope, liveCursor);
26526
+ get drawPoints() {
26527
+ if (this.localPoints.length >= 4) {
26528
+ return this.localPoints;
26529
+ }
26530
+ return this.points;
26531
+ }
26532
+ constructor(root, scope, type, liveCursor, isPerformanceMode) {
26533
+ super(root, scope, liveCursor, isPerformanceMode);
26374
26534
  _defineProperty6(this, "item", null);
26375
- if (!this.root.has("type")) {
26535
+ _defineProperty6(this, "clearLocalPointsWhenYPointsChange", true);
26536
+ _defineProperty6(this, "shouldUseLocalPoints", true);
26537
+ _defineProperty6(this, "localPointsPick", 24);
26538
+ if (this.root.doc && !this.root.has("type")) {
26376
26539
  this.root.set("type", type);
26377
26540
  }
26378
- if (!this.root.has("points")) {
26541
+ if (this.root.doc && !this.root.has("points")) {
26379
26542
  this.root.set("points", new Y4.Array());
26380
26543
  }
26381
26544
  }
@@ -26395,13 +26558,13 @@ var SegmentsModel = class extends ElementModel {
26395
26558
  }
26396
26559
  const matrix = new this.scope.Matrix(this.pointsMatrix);
26397
26560
  this.item.removeSegments();
26398
- const next = deserializePath(this.points, this.scope, matrix);
26561
+ const next = deserializePath(this.drawPoints, this.scope, matrix);
26399
26562
  this.item.addSegments(next.segments);
26400
26563
  this.item.closePath();
26401
26564
  }
26402
26565
  createPaperItem() {
26403
26566
  const matrix = new this.scope.Matrix(this.pointsMatrix);
26404
- this.item = deserializePath(this.points, this.scope, matrix);
26567
+ this.item = deserializePath(this.drawPoints, this.scope, matrix);
26405
26568
  this.item.strokeColor = new this.scope.Color(this.strokeColor);
26406
26569
  this.item.dashArray = this.dashArray;
26407
26570
  this.item.strokeWidth = this.strokeWidth;
@@ -26449,6 +26612,8 @@ function _toPrimitive7(t, r) {
26449
26612
  }
26450
26613
  return ("string" === r ? String : Number)(t);
26451
26614
  }
26615
+ var DRAG_FPS = 10;
26616
+ var DRAG_FRAME_MS = 1e3 / DRAG_FPS;
26452
26617
  var WhiteboardTool = class {
26453
26618
  constructor(enableToolEvent, modelGetter, shadowEmitter, scope) {
26454
26619
  _defineProperty7(this, "modelGetter", void 0);
@@ -26457,24 +26622,60 @@ var WhiteboardTool = class {
26457
26622
  _defineProperty7(this, "shadowEmitter", void 0);
26458
26623
  _defineProperty7(this, "enableToolEvent", void 0);
26459
26624
  _defineProperty7(this, "eventAvailable", false);
26625
+ _defineProperty7(this, "lastDragTime", 0);
26626
+ _defineProperty7(this, "dragRafId", 0);
26627
+ _defineProperty7(this, "pendingDragEvent", null);
26460
26628
  _defineProperty7(this, "onMouseDownSelf", (event) => {
26461
26629
  this.eventAvailable = this.enableToolEvent();
26462
26630
  if (!this.eventAvailable) {
26463
26631
  return;
26464
26632
  }
26633
+ this.lastDragTime = 0;
26634
+ if (this.dragRafId) {
26635
+ cancelAnimationFrame(this.dragRafId);
26636
+ this.dragRafId = 0;
26637
+ }
26638
+ this.pendingDragEvent = null;
26465
26639
  this.shadowEmitter.setActive(true);
26466
26640
  this.onMouseDown(event);
26467
26641
  });
26642
+ _defineProperty7(this, "flushPendingDrag", () => {
26643
+ this.dragRafId = 0;
26644
+ if (this.pendingDragEvent) {
26645
+ this.lastDragTime = performance.now();
26646
+ const event = this.pendingDragEvent;
26647
+ this.pendingDragEvent = null;
26648
+ this.onMouseDrag(event);
26649
+ }
26650
+ });
26468
26651
  _defineProperty7(this, "onMouseDragSelf", (event) => {
26469
26652
  if (!this.eventAvailable) {
26470
26653
  return;
26471
26654
  }
26472
- this.onMouseDrag(event);
26655
+ const now = performance.now();
26656
+ if (now - this.lastDragTime >= DRAG_FRAME_MS) {
26657
+ this.lastDragTime = now;
26658
+ this.pendingDragEvent = null;
26659
+ this.onMouseDrag(event);
26660
+ } else {
26661
+ this.pendingDragEvent = event;
26662
+ if (!this.dragRafId) {
26663
+ this.dragRafId = requestAnimationFrame(this.flushPendingDrag);
26664
+ }
26665
+ }
26473
26666
  });
26474
26667
  _defineProperty7(this, "onMouseUpSelf", (event) => {
26475
26668
  if (!this.eventAvailable) {
26476
26669
  return;
26477
26670
  }
26671
+ if (this.dragRafId) {
26672
+ cancelAnimationFrame(this.dragRafId);
26673
+ this.dragRafId = 0;
26674
+ }
26675
+ if (this.pendingDragEvent) {
26676
+ this.onMouseDrag(this.pendingDragEvent);
26677
+ this.pendingDragEvent = null;
26678
+ }
26478
26679
  this.onMouseUp(event);
26479
26680
  this.shadowEmitter.setActive(false);
26480
26681
  });
@@ -26569,6 +26770,12 @@ function _toPrimitive9(t, r) {
26569
26770
  return ("string" === r ? String : Number)(t);
26570
26771
  }
26571
26772
  var LineModel = class extends ElementModel {
26773
+ get drawPoints() {
26774
+ if (this.localPoints.length > 0) {
26775
+ return this.localPoints;
26776
+ }
26777
+ return this.points;
26778
+ }
26572
26779
  get arrowSize() {
26573
26780
  return this.strokeWidth * 5 + 15;
26574
26781
  }
@@ -26584,20 +26791,23 @@ var LineModel = class extends ElementModel {
26584
26791
  set tailArrow(value) {
26585
26792
  this.root.set("tailArrow", value);
26586
26793
  }
26587
- constructor(root, scope, liveCursor) {
26588
- super(root, scope, liveCursor);
26794
+ constructor(root, scope, liveCursor, isPerformanceMode) {
26795
+ super(root, scope, liveCursor, isPerformanceMode);
26589
26796
  _defineProperty9(this, "controlledPoints", []);
26797
+ _defineProperty9(this, "clearLocalPointsWhenYPointsChange", true);
26798
+ _defineProperty9(this, "shouldUseLocalPoints", true);
26799
+ _defineProperty9(this, "localPointsPick", 99);
26590
26800
  _defineProperty9(this, "item", null);
26591
- if (!this.root.has("type")) {
26801
+ if (this.root.doc && !this.root.has("type")) {
26592
26802
  this.root.set("type", "arrow");
26593
26803
  }
26594
- if (!this.root.has("points")) {
26804
+ if (this.root.doc && !this.root.has("points")) {
26595
26805
  this.root.set("points", new Y5.Array());
26596
26806
  }
26597
- if (!this.root.has("headArrow")) {
26807
+ if (this.root.doc && !this.root.has("headArrow")) {
26598
26808
  this.root.set("headArrow", "none");
26599
26809
  }
26600
- if (!this.root.has("tailArrow")) {
26810
+ if (this.root.doc && !this.root.has("tailArrow")) {
26601
26811
  this.root.set("tailArrow", "normal");
26602
26812
  }
26603
26813
  }
@@ -26613,7 +26823,7 @@ var LineModel = class extends ElementModel {
26613
26823
  }
26614
26824
  renderLine() {
26615
26825
  const matrix = new this.scope.Matrix(this.pointsMatrix);
26616
- const papperPoints = (0, import_lodash4.chunk)(this.points, 2).map((item) => {
26826
+ const papperPoints = (0, import_lodash4.chunk)(this.drawPoints, 2).map((item) => {
26617
26827
  return new this.scope.Point(item[0], item[1]).transform(matrix);
26618
26828
  });
26619
26829
  const path = new this.scope.Path();
@@ -26727,13 +26937,14 @@ var LineControlPoint = class {
26727
26937
  if (this.position) {
26728
26938
  return this.model.scope.project.view.projectToView(this.position.transform(matrix));
26729
26939
  }
26940
+ const points = this.model["drawPoints"];
26730
26941
  const from = {
26731
- x: this.model.points[0],
26732
- y: this.model.points[1]
26942
+ x: points[0],
26943
+ y: points[1]
26733
26944
  };
26734
26945
  const to = {
26735
- x: this.model.points[this.model.points.length - 2],
26736
- y: this.model.points[this.model.points.length - 1]
26946
+ x: points[points.length - 2],
26947
+ y: points[points.length - 1]
26737
26948
  };
26738
26949
  const clonedPath = new this.scope.Path.Line(from, to);
26739
26950
  this.position = clonedPath.getPointAt(clonedPath.length * distance);
@@ -26746,7 +26957,7 @@ var LineControlPoint = class {
26746
26957
  }
26747
26958
  const pointsMatrix = new this.model.scope.Matrix(this.model.pointsMatrix);
26748
26959
  const invertedPoint = point.transform(pointsMatrix.inverted());
26749
- const points = this.model.points;
26960
+ const points = this.model["drawPoints"];
26750
26961
  this.position = invertedPoint;
26751
26962
  const clonedPoints = (0, import_lodash4.cloneDeep)(points);
26752
26963
  clonedPoints[this.options.index * 2] = invertedPoint.x;
@@ -26794,9 +27005,18 @@ var PointTextModel = class extends ElementModel {
26794
27005
  set fontFamily(value) {
26795
27006
  this.root.set("font-family", value);
26796
27007
  }
26797
- constructor(root, scope, liveCursor) {
26798
- super(root, scope, liveCursor);
27008
+ get drawPoints() {
27009
+ if (this.localPoints.length > 1) {
27010
+ return this.localPoints;
27011
+ }
27012
+ return this.points;
27013
+ }
27014
+ constructor(root, scope, liveCursor, isPerformanceMode) {
27015
+ super(root, scope, liveCursor, isPerformanceMode);
26799
27016
  _defineProperty10(this, "item", null);
27017
+ _defineProperty10(this, "clearLocalPointsWhenYPointsChange", true);
27018
+ _defineProperty10(this, "shouldUseLocalPoints", false);
27019
+ _defineProperty10(this, "localPointsPick", 2);
26800
27020
  _defineProperty10(this, "handleTextPropChange", (event) => {
26801
27021
  if (!this.item) {
26802
27022
  return;
@@ -26813,22 +27033,28 @@ var PointTextModel = class extends ElementModel {
26813
27033
  }
26814
27034
  }
26815
27035
  });
26816
- if (!this.root.has("type")) {
27036
+ if (this.root.doc && !this.root.has("type")) {
26817
27037
  this.root.set("type", "point-text");
26818
27038
  }
26819
- if (!this.root.has(ElementModel.KEYS.points)) {
27039
+ if (this.root.doc && !this.root.has(ElementModel.KEYS.points)) {
26820
27040
  this.root.set(ElementModel.KEYS.points, new Y6.Array());
26821
27041
  }
26822
27042
  this.root.observe(this.handleTextPropChange);
26823
- if (this.root.has("font-size")) {
26824
- setTimeout(() => {
26825
- this.updateTextPosition();
26826
- }, 60);
26827
- }
27043
+ setTimeout(() => {
27044
+ if (this.root && this.root.has("font-size")) {
27045
+ setTimeout(() => {
27046
+ this.updateTextPosition();
27047
+ }, 60);
27048
+ }
27049
+ }, 60);
26828
27050
  }
26829
27051
  subDispose() {
26830
27052
  removeObserver(this.root, this.handleTextPropChange);
26831
27053
  }
27054
+ subBindObserver() {
27055
+ removeObserver(this.root, this.handleTextPropChange);
27056
+ this.root.observe(this.handleTextPropChange);
27057
+ }
26832
27058
  liveCursorPoint() {
26833
27059
  const points = this.points;
26834
27060
  if (points.length < 1) {
@@ -26842,10 +27068,11 @@ var PointTextModel = class extends ElementModel {
26842
27068
  if (!this.item) {
26843
27069
  return null;
26844
27070
  }
27071
+ console.log("[][][] drawPoints", this.drawPoints);
26845
27072
  const bounds = this.item.internalBounds;
26846
27073
  const matrix = new this.scope.Matrix(this.pointsMatrix);
26847
- const topLeft = new this.scope.Point(this.points[0], this.points[1]).transform(matrix);
26848
- const topRight = new this.scope.Point(this.points[0] + bounds.width, this.points[1]).transform(matrix);
27074
+ const topLeft = new this.scope.Point(this.drawPoints[0], this.drawPoints[1]).transform(matrix);
27075
+ const topRight = new this.scope.Point(this.drawPoints[0] + bounds.width, this.drawPoints[1]).transform(matrix);
26849
27076
  let scaleX = topRight.getDistance(topLeft) / bounds.width;
26850
27077
  scaleX = Number.isNaN(scaleX) ? 1 : scaleX;
26851
27078
  const angle = topRight.subtract(topLeft).angle;
@@ -26933,13 +27160,22 @@ function _toPrimitive11(t, r) {
26933
27160
  return ("string" === r ? String : Number)(t);
26934
27161
  }
26935
27162
  var TriangleModel = class extends ElementModel {
26936
- constructor(root, scope, liveCursor) {
26937
- super(root, scope, liveCursor);
27163
+ get drawPoints() {
27164
+ if (this.localPoints.length >= 6) {
27165
+ return this.localPoints;
27166
+ }
27167
+ return this.points;
27168
+ }
27169
+ constructor(root, scope, liveCursor, isPerformanceMode) {
27170
+ super(root, scope, liveCursor, isPerformanceMode);
26938
27171
  _defineProperty11(this, "item", null);
26939
- if (!this.root.has("type")) {
27172
+ _defineProperty11(this, "clearLocalPointsWhenYPointsChange", true);
27173
+ _defineProperty11(this, "shouldUseLocalPoints", true);
27174
+ _defineProperty11(this, "localPointsPick", 6);
27175
+ if (this.root.doc && !this.root.has("type")) {
26940
27176
  this.root.set("type", "triangle");
26941
27177
  }
26942
- if (!this.root.has("points")) {
27178
+ if (this.root.doc && !this.root.has("points")) {
26943
27179
  this.root.set("points", new Y7.Array());
26944
27180
  }
26945
27181
  }
@@ -26971,9 +27207,9 @@ var TriangleModel = class extends ElementModel {
26971
27207
  return;
26972
27208
  }
26973
27209
  const matrix = new this.scope.Matrix(this.pointsMatrix);
26974
- const p1 = new this.scope.Point(this.points[0], this.points[1]).transform(matrix);
26975
- const p2 = new this.scope.Point(this.points[2], this.points[3]).transform(matrix);
26976
- const p3 = new this.scope.Point(this.points[4], this.points[5]).transform(matrix);
27210
+ const p1 = new this.scope.Point(this.drawPoints[0], this.drawPoints[1]).transform(matrix);
27211
+ const p2 = new this.scope.Point(this.drawPoints[2], this.drawPoints[3]).transform(matrix);
27212
+ const p3 = new this.scope.Point(this.drawPoints[4], this.drawPoints[5]).transform(matrix);
26977
27213
  this.item.removeSegments();
26978
27214
  this.item.moveTo(p1);
26979
27215
  this.item.lineTo(p2);
@@ -26985,7 +27221,7 @@ var TriangleModel = class extends ElementModel {
26985
27221
  config.controlPoints.push({
26986
27222
  name: "triangle",
26987
27223
  getPosition: () => {
26988
- const point = new this.scope.Point(this.points[0], this.points[1]);
27224
+ const point = new this.scope.Point(this.drawPoints[0], this.drawPoints[1]);
26989
27225
  const pointsMatrix = new this.scope.Matrix(this.pointsMatrix);
26990
27226
  return this.scope.project.view.projectToView(point.transform(pointsMatrix));
26991
27227
  },
@@ -26995,7 +27231,7 @@ var TriangleModel = class extends ElementModel {
26995
27231
  }
26996
27232
  const pointsMatrix = new this.scope.Matrix(this.pointsMatrix);
26997
27233
  const trPoint = point.transform(pointsMatrix.inverted());
26998
- const oldPoints = this.points;
27234
+ const oldPoints = this.drawPoints;
26999
27235
  this.setPoints([trPoint.x, trPoint.y, oldPoints[2], oldPoints[3], oldPoints[4], oldPoints[5]]);
27000
27236
  }
27001
27237
  });
@@ -27034,25 +27270,34 @@ function _toPrimitive12(t, r) {
27034
27270
  return ("string" === r ? String : Number)(t);
27035
27271
  }
27036
27272
  var RectangleModel = class extends ElementModel {
27037
- constructor(root, scope, liveCursor) {
27038
- super(root, scope, liveCursor);
27273
+ get drawPoints() {
27274
+ if (this.localPoints.length >= 4) {
27275
+ return this.localPoints;
27276
+ }
27277
+ return this.points;
27278
+ }
27279
+ constructor(root, scope, liveCursor, isPerformanceMode) {
27280
+ super(root, scope, liveCursor, isPerformanceMode);
27039
27281
  _defineProperty12(this, "item", null);
27040
- if (!this.root.has("type")) {
27282
+ _defineProperty12(this, "clearLocalPointsWhenYPointsChange", true);
27283
+ _defineProperty12(this, "shouldUseLocalPoints", true);
27284
+ _defineProperty12(this, "localPointsPick", 4);
27285
+ if (this.root.doc && !this.root.has("type")) {
27041
27286
  this.root.set("type", "rectangle");
27042
27287
  }
27043
- if (!this.root.has("points")) {
27288
+ if (this.root.doc && !this.root.has("points")) {
27044
27289
  const initPoints = new Y8.Array();
27045
27290
  initPoints.push([0, 0, 0, 0]);
27046
27291
  this.root.set("points", initPoints);
27047
27292
  }
27048
- if (!this.root.has("radius")) {
27293
+ if (this.root.doc && !this.root.has("radius")) {
27049
27294
  this.root.set("radius", 0);
27050
27295
  }
27051
27296
  }
27052
27297
  subDispose() {
27053
27298
  }
27054
27299
  liveCursorPoint() {
27055
- const points = this.points;
27300
+ const points = this.drawPoints;
27056
27301
  if (points.length < 4) {
27057
27302
  return null;
27058
27303
  }
@@ -27060,7 +27305,7 @@ var RectangleModel = class extends ElementModel {
27060
27305
  return new this.scope.Point(points[2], points[3]).transform(matrix);
27061
27306
  }
27062
27307
  createSegments() {
27063
- const [a2, b2, c, d] = this.points;
27308
+ const [a2, b2, c, d] = this.drawPoints;
27064
27309
  const matrix = new this.scope.Matrix(this.pointsMatrix);
27065
27310
  const maxRadius = this.maxRadiusLength();
27066
27311
  const radius = this.root.get("radius") * maxRadius;
@@ -27125,7 +27370,7 @@ var RectangleModel = class extends ElementModel {
27125
27370
  }
27126
27371
  maxRadiusLength() {
27127
27372
  const pointsMatrix = new this.scope.Matrix(this.pointsMatrix);
27128
- const points = this.points;
27373
+ const points = this.drawPoints;
27129
27374
  const topLeft = new this.scope.Point(points[0], points[1]).transform(pointsMatrix);
27130
27375
  const topRight = new this.scope.Point(points[2], points[1]).transform(pointsMatrix);
27131
27376
  const bottomLeft = new this.scope.Point(points[0], points[3]).transform(pointsMatrix);
@@ -27150,7 +27395,7 @@ var RectangleModel = class extends ElementModel {
27150
27395
  name: "rect-radius",
27151
27396
  getPosition: () => {
27152
27397
  const matrix = new this.scope.Matrix(this.pointsMatrix);
27153
- const points = this.points;
27398
+ const points = this.drawPoints;
27154
27399
  const radius = this.root.get("radius") * this.maxRadiusLength();
27155
27400
  let c1 = new this.scope.Point(points[0], points[1]).transform(matrix);
27156
27401
  const c3 = new this.scope.Point(points[2], points[3]).transform(matrix);
@@ -27169,7 +27414,7 @@ var RectangleModel = class extends ElementModel {
27169
27414
  if (!this.item) {
27170
27415
  return;
27171
27416
  }
27172
- const points = this.points;
27417
+ const points = this.drawPoints;
27173
27418
  const pointsMatrix = new this.scope.Matrix(this.pointsMatrix);
27174
27419
  const maxRadius = Math.min(points[2] - points[0], points[3] - points[1]) / 2;
27175
27420
  const trPoint = point.transform(pointsMatrix.inverted());
@@ -27218,14 +27463,23 @@ function _toPrimitive13(t, r) {
27218
27463
  return ("string" === r ? String : Number)(t);
27219
27464
  }
27220
27465
  var EraserModel = class extends ElementModel {
27221
- constructor(root, scope, liveCursor) {
27222
- super(root, scope, liveCursor);
27466
+ get drawPoints() {
27467
+ if (this.localPoints.length > 0) {
27468
+ return this.localPoints;
27469
+ }
27470
+ return this.points;
27471
+ }
27472
+ constructor(root, scope, liveCursor, isPerformanceMode) {
27473
+ super(root, scope, liveCursor, isPerformanceMode);
27223
27474
  _defineProperty13(this, "item", null);
27224
27475
  _defineProperty13(this, "sliceBegin", 0);
27225
- if (!this.root.has("type")) {
27476
+ _defineProperty13(this, "clearLocalPointsWhenYPointsChange", false);
27477
+ _defineProperty13(this, "shouldUseLocalPoints", true);
27478
+ _defineProperty13(this, "localPointsPick", 4);
27479
+ if (this.root.doc && !this.root.has("type")) {
27226
27480
  this.root.set("type", "eraser");
27227
27481
  }
27228
- if (!this.root.has("points")) {
27482
+ if (this.root.doc && !this.root.has("points")) {
27229
27483
  this.root.set("points", new Y9.Array());
27230
27484
  }
27231
27485
  }
@@ -27276,7 +27530,7 @@ var EraserModel = class extends ElementModel {
27276
27530
  });
27277
27531
  }
27278
27532
  matrixedPoints() {
27279
- const currentPoints = (0, import_lodash5.chunk)(this.points, 2).slice(this.sliceBegin);
27533
+ const currentPoints = (0, import_lodash5.chunk)(this.drawPoints, 2).slice(this.sliceBegin);
27280
27534
  return currentPoints.map((_ref) => {
27281
27535
  let [x, y] = _ref;
27282
27536
  return new this.scope.Point(x, y);
@@ -27304,11 +27558,11 @@ var EraserModel = class extends ElementModel {
27304
27558
  this.item.fillColor = new this.scope.Color(this.strokeColor);
27305
27559
  this.onVectorUpdate();
27306
27560
  this.item.onFrame = () => {
27307
- if (!this.points) {
27561
+ if (!this.drawPoints) {
27308
27562
  return;
27309
27563
  }
27310
- if (this.points.length / 2 > 50) {
27311
- this.sliceBegin = this.points.length / 2 - 50;
27564
+ if (this.drawPoints.length / 2 > 50) {
27565
+ this.sliceBegin = this.drawPoints.length / 2 - 50;
27312
27566
  }
27313
27567
  };
27314
27568
  }
@@ -27343,6 +27597,7 @@ var EraserModel = class extends ElementModel {
27343
27597
  // src/model/renderable/LaserPointerModel.ts
27344
27598
  var import_lodash6 = __toESM(require_lodash(), 1);
27345
27599
  import * as Y10 from "yjs";
27600
+ import { removeObserver as removeObserver2 } from "@netless/forge-room";
27346
27601
  function _defineProperty14(e, r, t) {
27347
27602
  return (r = _toPropertyKey14(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: true, configurable: true, writable: true }) : e[r] = t, e;
27348
27603
  }
@@ -27361,24 +27616,18 @@ function _toPrimitive14(t, r) {
27361
27616
  return ("string" === r ? String : Number)(t);
27362
27617
  }
27363
27618
  var LaserPointerModel = class extends ElementModel {
27364
- constructor(clientId, root, scope, liveCursor, removeElement) {
27365
- super(root, scope, liveCursor);
27619
+ constructor(clientId, root, scope, liveCursor, removeElement, isPerformanceMode) {
27620
+ super(root, scope, liveCursor, isPerformanceMode);
27366
27621
  _defineProperty14(this, "item", null);
27367
27622
  _defineProperty14(this, "clientId", void 0);
27368
27623
  _defineProperty14(this, "sliceBegin", 0);
27369
27624
  _defineProperty14(this, "displayStrokeWidth", 8);
27370
27625
  _defineProperty14(this, "cachedPoints", null);
27371
- this.clientId = clientId;
27372
- if (!this.root.has("type")) {
27373
- this.root.set("type", "laser");
27374
- }
27375
- if (!this.root.has("points")) {
27376
- this.root.set("points", new Y10.Array());
27377
- }
27378
- if (!this.root.has("removed")) {
27379
- this.root.set("removed", false);
27380
- }
27381
- this.root.observe((event) => {
27626
+ _defineProperty14(this, "clearLocalPointsWhenYPointsChange", false);
27627
+ _defineProperty14(this, "shouldUseLocalPoints", false);
27628
+ _defineProperty14(this, "localPointsPick", 4);
27629
+ _defineProperty14(this, "removeElement", void 0);
27630
+ _defineProperty14(this, "handleLaserPropChange", (event) => {
27382
27631
  if (!this.item) {
27383
27632
  return;
27384
27633
  }
@@ -27396,13 +27645,31 @@ var LaserPointerModel = class extends ElementModel {
27396
27645
  this.onVectorUpdate();
27397
27646
  if (evt.count >= 30) {
27398
27647
  if (this.ownerId === this.clientId) {
27399
- removeElement(this.uuid);
27648
+ this.removeElement(this.uuid);
27400
27649
  }
27401
27650
  }
27402
27651
  };
27403
27652
  }
27404
27653
  }
27405
27654
  });
27655
+ this.clientId = clientId;
27656
+ this.removeElement = removeElement;
27657
+ if (this.root.doc && !this.root.has("type")) {
27658
+ this.root.set("type", "laser");
27659
+ }
27660
+ if (this.root.doc && !this.root.has("points")) {
27661
+ this.root.set("points", new Y10.Array());
27662
+ }
27663
+ if (this.root.doc && !this.root.has("removed")) {
27664
+ this.root.set("removed", false);
27665
+ }
27666
+ }
27667
+ subBindObserver() {
27668
+ removeObserver2(this.root, this.handleLaserPropChange);
27669
+ this.root.observe(this.handleLaserPropChange);
27670
+ }
27671
+ subDispose() {
27672
+ removeObserver2(this.root, this.handleLaserPropChange);
27406
27673
  }
27407
27674
  beginRemoveAnimate() {
27408
27675
  this.root.set("removed", true);
@@ -27455,6 +27722,7 @@ var LaserPointerModel = class extends ElementModel {
27455
27722
  matrixedPoints() {
27456
27723
  const matrix = new this.scope.Matrix(this.pointsMatrix);
27457
27724
  const points = this.cachedPoints || this.points;
27725
+ console.log("[][][] ,", this.points.length, this.cachedPoints?.length, this.localPoints.length);
27458
27726
  const groupPoints = (0, import_lodash6.chunk)(points, 2).slice(this.sliceBegin);
27459
27727
  return groupPoints.map((_ref) => {
27460
27728
  let [x, y] = _ref;
@@ -27497,8 +27765,6 @@ var LaserPointerModel = class extends ElementModel {
27497
27765
  onStyleKeyUpdate(_key) {
27498
27766
  return;
27499
27767
  }
27500
- subDispose() {
27501
- }
27502
27768
  liveCursorPoint() {
27503
27769
  const yArray = this.root.get(ElementModel.KEYS.points);
27504
27770
  if (yArray.length < 2) {
@@ -27556,13 +27822,22 @@ function _toPrimitive15(t, r) {
27556
27822
  return ("string" === r ? String : Number)(t);
27557
27823
  }
27558
27824
  var StraightLineModel = class extends ElementModel {
27559
- constructor(root, scope, liveCursor) {
27560
- super(root, scope, liveCursor);
27825
+ get drawPoints() {
27826
+ if (this.localPoints.length >= 4) {
27827
+ return this.localPoints;
27828
+ }
27829
+ return this.points;
27830
+ }
27831
+ constructor(root, scope, liveCursor, isPerformanceMode) {
27832
+ super(root, scope, liveCursor, isPerformanceMode);
27561
27833
  _defineProperty15(this, "item", null);
27562
- if (!this.root.has("type")) {
27834
+ _defineProperty15(this, "clearLocalPointsWhenYPointsChange", true);
27835
+ _defineProperty15(this, "shouldUseLocalPoints", true);
27836
+ _defineProperty15(this, "localPointsPick", 4);
27837
+ if (this.root.doc && !this.root.has("type")) {
27563
27838
  this.root.set("type", "line");
27564
27839
  }
27565
- if (!this.root.has("points")) {
27840
+ if (this.root.doc && !this.root.has("points")) {
27566
27841
  this.root.set("points", new Y11.Array());
27567
27842
  }
27568
27843
  }
@@ -27587,7 +27862,7 @@ var StraightLineModel = class extends ElementModel {
27587
27862
  }
27588
27863
  renderLine() {
27589
27864
  const matrix = new this.scope.Matrix(this.pointsMatrix);
27590
- const papperPoints = (0, import_lodash7.chunk)(this.points, 2).map((item) => {
27865
+ const papperPoints = (0, import_lodash7.chunk)(this.drawPoints, 2).map((item) => {
27591
27866
  return new this.scope.Point(item[0], item[1]).transform(matrix);
27592
27867
  });
27593
27868
  const path = new this.scope.Path();
@@ -27609,7 +27884,7 @@ var StraightLineModel = class extends ElementModel {
27609
27884
  name: "line-start",
27610
27885
  getPosition: () => {
27611
27886
  const matrix = new this.scope.Matrix(this.pointsMatrix);
27612
- const points = this.points;
27887
+ const points = this.drawPoints;
27613
27888
  const start = new this.scope.Point(points[0], points[1]);
27614
27889
  return this.scope.project.view.projectToView(start.transform(matrix));
27615
27890
  },
@@ -27619,14 +27894,15 @@ var StraightLineModel = class extends ElementModel {
27619
27894
  }
27620
27895
  const pointsMatrix = new this.scope.Matrix(this.pointsMatrix);
27621
27896
  const trPoint = point.transform(pointsMatrix.inverted());
27622
- this.setPoints([trPoint.x, trPoint.y, this.points[2], this.points[3]]);
27897
+ const oldPoints = this.drawPoints;
27898
+ this.setPoints([trPoint.x, trPoint.y, oldPoints[2], oldPoints[3]]);
27623
27899
  }
27624
27900
  });
27625
27901
  cfg.controlPoints.push({
27626
27902
  name: "line-end",
27627
27903
  getPosition: () => {
27628
27904
  const matrix = new this.scope.Matrix(this.pointsMatrix);
27629
- const points = this.points;
27905
+ const points = this.drawPoints;
27630
27906
  const end = new this.scope.Point(points[2], points[3]);
27631
27907
  return this.scope.project.view.projectToView(end.transform(matrix));
27632
27908
  },
@@ -27636,7 +27912,8 @@ var StraightLineModel = class extends ElementModel {
27636
27912
  }
27637
27913
  const pointsMatrix = new this.scope.Matrix(this.pointsMatrix);
27638
27914
  const trPoint = point.transform(pointsMatrix.inverted());
27639
- this.setPoints([this.points[0], this.points[1], trPoint.x, trPoint.y]);
27915
+ const oldPoints = this.drawPoints;
27916
+ this.setPoints([oldPoints[0], oldPoints[1], trPoint.x, trPoint.y]);
27640
27917
  }
27641
27918
  });
27642
27919
  return cfg;
@@ -27682,10 +27959,13 @@ var ImageModel = class extends ElementModel {
27682
27959
  get src() {
27683
27960
  return this.root.get("src");
27684
27961
  }
27685
- constructor(root, scope, imageSets, liveCursor) {
27686
- super(root, scope, liveCursor);
27962
+ constructor(root, scope, imageSets, liveCursor, isPerformanceMode) {
27963
+ super(root, scope, liveCursor, isPerformanceMode);
27687
27964
  _defineProperty16(this, "item", null);
27688
27965
  _defineProperty16(this, "imageSets", void 0);
27966
+ _defineProperty16(this, "clearLocalPointsWhenYPointsChange", true);
27967
+ _defineProperty16(this, "shouldUseLocalPoints", true);
27968
+ _defineProperty16(this, "localPointsPick", 4);
27689
27969
  this.imageSets = imageSets;
27690
27970
  if (!this.root.has("type")) {
27691
27971
  this.root.set("type", "image");
@@ -27704,6 +27984,7 @@ var ImageModel = class extends ElementModel {
27704
27984
  }
27705
27985
  if (!this.imageSets.querySelector(`[id='${this.uuid}']`)) {
27706
27986
  const img = document.createElement("img");
27987
+ img.crossOrigin = "anonymous";
27707
27988
  img.src = this.src;
27708
27989
  img.id = this.uuid;
27709
27990
  this.imageSets.appendChild(img);
@@ -27768,7 +28049,7 @@ var RenderableModel = class extends EventEmitter {
27768
28049
  get uuid() {
27769
28050
  return uuidv4().replace(/-/g, "");
27770
28051
  }
27771
- constructor(layerId, shadowEmitter, elements, scope, toolbarModel, userManager, imageSets, liveCursor, hasPermission) {
28052
+ constructor(options) {
27772
28053
  super();
27773
28054
  _defineProperty17(this, "scope", void 0);
27774
28055
  _defineProperty17(this, "toolbarModel", void 0);
@@ -27781,6 +28062,7 @@ var RenderableModel = class extends EventEmitter {
27781
28062
  _defineProperty17(this, "shadowEmitter", void 0);
27782
28063
  _defineProperty17(this, "imageSets", void 0);
27783
28064
  _defineProperty17(this, "liveCursor", void 0);
28065
+ _defineProperty17(this, "isPerformanceMode", void 0);
27784
28066
  _defineProperty17(this, "onElementsChange", (event) => {
27785
28067
  for (const [key, value] of event.changes.keys.entries()) {
27786
28068
  if (value.action === "add") {
@@ -27799,15 +28081,16 @@ var RenderableModel = class extends EventEmitter {
27799
28081
  }
27800
28082
  }
27801
28083
  });
27802
- this.liveCursor = liveCursor;
27803
- this.imageSets = imageSets;
27804
- this.hasPermission = hasPermission;
27805
- this.shadowEmitter = shadowEmitter;
27806
- this.layerId = layerId;
27807
- this.userManager = userManager;
27808
- this.elements = elements;
27809
- this.scope = scope;
27810
- this.toolbarModel = toolbarModel;
28084
+ this.isPerformanceMode = options.isPerformanceMode;
28085
+ this.liveCursor = options.liveCursor;
28086
+ this.imageSets = options.imageSets;
28087
+ this.hasPermission = options.hasPermission;
28088
+ this.shadowEmitter = options.shadowEmitter;
28089
+ this.layerId = options.layerId;
28090
+ this.userManager = options.userManager;
28091
+ this.elements = options.elements;
28092
+ this.scope = options.scope;
28093
+ this.toolbarModel = options.toolbarModel;
27811
28094
  this.elementModels = /* @__PURE__ */ new Map();
27812
28095
  for (const key of this.elements.keys()) {
27813
28096
  const type = this.elements.get(key)?.get("type");
@@ -27838,33 +28121,43 @@ var RenderableModel = class extends EventEmitter {
27838
28121
  convertToModel(yMap) {
27839
28122
  const type = yMap.get("type");
27840
28123
  let model = null;
28124
+ const uuid = yMap.get(ElementModel.KEYS.uuid);
28125
+ if (uuid) {
28126
+ const existingModel = this.elementModels.get(uuid);
28127
+ if (existingModel) {
28128
+ existingModel.shadowEmitter = this.shadowEmitter;
28129
+ existingModel.bindObserver();
28130
+ return existingModel;
28131
+ }
28132
+ }
27841
28133
  if (type === "curve") {
27842
- model = new CurveModel(yMap, this.scope, this.liveCursor);
28134
+ model = new CurveModel(yMap, this.scope, this.liveCursor, this.isPerformanceMode);
27843
28135
  } else if (["ellipse"].indexOf(type) >= 0) {
27844
- model = new SegmentsModel(yMap, this.scope, type, this.liveCursor);
28136
+ model = new SegmentsModel(yMap, this.scope, type, this.liveCursor, this.isPerformanceMode);
27845
28137
  } else if (type === "selector") {
27846
- model = new SelectorModel(yMap, this.scope, this.liveCursor);
28138
+ model = new SelectorModel(yMap, this.scope, this.liveCursor, this.isPerformanceMode);
27847
28139
  } else if (type === "arrow") {
27848
- model = new LineModel(yMap, this.scope, this.liveCursor);
28140
+ model = new LineModel(yMap, this.scope, this.liveCursor, this.isPerformanceMode);
27849
28141
  } else if (type === "line") {
27850
- model = new StraightLineModel(yMap, this.scope, this.liveCursor);
28142
+ model = new StraightLineModel(yMap, this.scope, this.liveCursor, this.isPerformanceMode);
27851
28143
  } else if (type === "point-text") {
27852
- model = new PointTextModel(yMap, this.scope, this.liveCursor);
28144
+ model = new PointTextModel(yMap, this.scope, this.liveCursor, this.isPerformanceMode);
27853
28145
  } else if (type === "triangle") {
27854
- model = new TriangleModel(yMap, this.scope, this.liveCursor);
28146
+ model = new TriangleModel(yMap, this.scope, this.liveCursor, this.isPerformanceMode);
27855
28147
  } else if (type === "rectangle") {
27856
- model = new RectangleModel(yMap, this.scope, this.liveCursor);
28148
+ model = new RectangleModel(yMap, this.scope, this.liveCursor, this.isPerformanceMode);
27857
28149
  } else if (type === "eraser") {
27858
- model = new EraserModel(yMap, this.scope, this.liveCursor);
28150
+ model = new EraserModel(yMap, this.scope, this.liveCursor, this.isPerformanceMode);
27859
28151
  } else if (type === "laser") {
27860
- model = new LaserPointerModel(this.userManager.selfId, yMap, this.scope, this.liveCursor, (uuid) => {
27861
- this.removeElementItem(uuid);
27862
- });
28152
+ model = new LaserPointerModel(this.userManager.selfId, yMap, this.scope, this.liveCursor, (uuid2) => {
28153
+ this.removeElementItem(uuid2);
28154
+ }, this.isPerformanceMode);
27863
28155
  } else if (type === "image") {
27864
- model = new ImageModel(yMap, this.scope, this.imageSets, this.liveCursor);
28156
+ model = new ImageModel(yMap, this.scope, this.imageSets, this.liveCursor, this.isPerformanceMode);
27865
28157
  }
27866
28158
  if (model) {
27867
28159
  model.shadowEmitter = this.shadowEmitter;
28160
+ model.bindObserver();
27868
28161
  this.elementModels.set(model.uuid, model);
27869
28162
  }
27870
28163
  return model;
@@ -27895,16 +28188,58 @@ var RenderableModel = class extends EventEmitter {
27895
28188
  yMap.set(ElementModel.KEYS.ownerId, this.userManager.selfId);
27896
28189
  this.elements.set(uuid, yMap);
27897
28190
  }, elementsUndoOrigin);
27898
- const model = new ImageModel(yMap, this.scope, this.imageSets, this.liveCursor);
28191
+ const model = new ImageModel(yMap, this.scope, this.imageSets, this.liveCursor, this.isPerformanceMode);
28192
+ model.bindObserver();
27899
28193
  model.root.set("src", src);
27900
- const initMatrix = new this.scope.Matrix();
28194
+ model.ownerId = this.userManager.selfId;
28195
+ this.fitImageToViewport(src, model);
28196
+ }
28197
+ fitImageToViewport(src, model) {
27901
28198
  const center = this.scope.project.view.center;
27902
- initMatrix.translate({
28199
+ const fallbackMatrix = new this.scope.Matrix();
28200
+ fallbackMatrix.translate({
27903
28201
  x: center.x,
27904
28202
  y: center.y
27905
28203
  });
27906
- model.appendPointsMatrix(initMatrix);
27907
- model.ownerId = this.userManager.selfId;
28204
+ this.setElementPointsMatrix(model, fallbackMatrix);
28205
+ const img = document.createElement("img");
28206
+ img.crossOrigin = "anonymous";
28207
+ img.onload = () => {
28208
+ const naturalWidth = img.naturalWidth || img.width;
28209
+ const naturalHeight = img.naturalHeight || img.height;
28210
+ if (naturalWidth <= 0 || naturalHeight <= 0) {
28211
+ return;
28212
+ }
28213
+ const viewportBounds = this.scope.project.view.bounds;
28214
+ const maxWidth = viewportBounds.width * 2 / 3;
28215
+ const maxHeight = viewportBounds.height * 2 / 3;
28216
+ const fitScale = Math.min(maxWidth / naturalWidth, maxHeight / naturalHeight, 1);
28217
+ const nextMatrix = new this.scope.Matrix();
28218
+ nextMatrix.translate({
28219
+ x: center.x,
28220
+ y: center.y
28221
+ });
28222
+ if (fitScale > 0 && Number.isFinite(fitScale)) {
28223
+ nextMatrix.scale(fitScale);
28224
+ }
28225
+ this.setElementPointsMatrix(model, nextMatrix);
28226
+ };
28227
+ img.onerror = () => {
28228
+ log("[@netless/forge-whiteboard] failed to preload image for viewport fitting", {
28229
+ src
28230
+ }, "warn");
28231
+ };
28232
+ img.src = src;
28233
+ }
28234
+ setElementPointsMatrix(model, matrix) {
28235
+ const values = [matrix.a, matrix.b, matrix.c, matrix.d, matrix.tx, matrix.ty];
28236
+ if (model.root.doc) {
28237
+ model.root.doc.transact(() => {
28238
+ model.root.set(ElementModel.KEYS.pointsMatrix, values);
28239
+ }, elementsUndoOrigin);
28240
+ } else {
28241
+ model.root.set(ElementModel.KEYS.pointsMatrix, values);
28242
+ }
27908
28243
  }
27909
28244
  createCurve() {
27910
28245
  let shadow = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : false;
@@ -27912,8 +28247,10 @@ var RenderableModel = class extends EventEmitter {
27912
28247
  return null;
27913
28248
  }
27914
28249
  const yMap = new Y12.Map();
28250
+ const uuid = this.uuid;
28251
+ const curveModel = new CurveModel(yMap, this.scope, this.liveCursor, this.isPerformanceMode);
28252
+ this.elementModels.set(uuid, curveModel);
27915
28253
  this.elements.doc?.transact(() => {
27916
- const uuid = this.uuid;
27917
28254
  yMap.set(ElementModel.KEYS.index, ++this.maxIndex);
27918
28255
  yMap.set(ElementModel.KEYS.uuid, uuid);
27919
28256
  yMap.set("type", "curve");
@@ -27926,7 +28263,7 @@ var RenderableModel = class extends EventEmitter {
27926
28263
  yMap.set(ElementModel.KEYS.ownerId, this.userManager.selfId);
27927
28264
  this.elements.set(uuid, yMap);
27928
28265
  }, elementsUndoOrigin);
27929
- const curveModel = new CurveModel(yMap, this.scope, this.liveCursor);
28266
+ curveModel.bindObserver();
27930
28267
  this.initElement(curveModel);
27931
28268
  return curveModel;
27932
28269
  }
@@ -27935,11 +28272,17 @@ var RenderableModel = class extends EventEmitter {
27935
28272
  return null;
27936
28273
  }
27937
28274
  const yMap = new Y12.Map();
28275
+ const uuid = this.uuid;
28276
+ const model = new LaserPointerModel(this.userManager.selfId, yMap, this.scope, this.liveCursor, (uuid2) => {
28277
+ this.removeElementItem(uuid2);
28278
+ }, this.isPerformanceMode);
28279
+ this.elementModels.set(uuid, model);
27938
28280
  this.elements.doc?.transact(() => {
27939
- const uuid = this.uuid;
27940
28281
  yMap.set(ElementModel.KEYS.index, ++this.maxIndex);
27941
28282
  yMap.set(ElementModel.KEYS.uuid, uuid);
27942
28283
  yMap.set("type", "laser");
28284
+ yMap.set(ElementModel.KEYS.points, new Y12.Array());
28285
+ yMap.set("removed", false);
27943
28286
  yMap.set(ElementModel.KEYS.shadow, "layer");
27944
28287
  yMap.set(ElementModel.KEYS.strokeWidth, 8);
27945
28288
  yMap.set(ElementModel.KEYS.strokeColor, "#F44336");
@@ -27947,9 +28290,8 @@ var RenderableModel = class extends EventEmitter {
27947
28290
  yMap.set(ElementModel.KEYS.ownerId, this.userManager.selfId);
27948
28291
  this.elements.set(uuid, yMap);
27949
28292
  }, elementsUndoOrigin);
27950
- const model = new LaserPointerModel(this.userManager.selfId, yMap, this.scope, this.liveCursor, (uuid) => {
27951
- this.removeElementItem(uuid);
27952
- });
28293
+ model.bindObserver();
28294
+ this.initElement(model);
27953
28295
  return model;
27954
28296
  }
27955
28297
  createEraser() {
@@ -27957,11 +28299,14 @@ var RenderableModel = class extends EventEmitter {
27957
28299
  return null;
27958
28300
  }
27959
28301
  const yMap = new Y12.Map();
28302
+ const uuid = this.uuid;
28303
+ const model = new EraserModel(yMap, this.scope, this.liveCursor, this.isPerformanceMode);
28304
+ this.elementModels.set(uuid, model);
27960
28305
  this.elements.doc?.transact(() => {
27961
- const uuid = this.uuid;
27962
28306
  yMap.set(ElementModel.KEYS.index, ++this.maxIndex);
27963
28307
  yMap.set(ElementModel.KEYS.uuid, uuid);
27964
28308
  yMap.set("type", "eraser");
28309
+ yMap.set(ElementModel.KEYS.points, new Y12.Array());
27965
28310
  yMap.set(ElementModel.KEYS.shadow, "layer");
27966
28311
  yMap.set(ElementModel.KEYS.strokeWidth, 4);
27967
28312
  yMap.set(ElementModel.KEYS.strokeColor, "#9E9E9E");
@@ -27969,7 +28314,7 @@ var RenderableModel = class extends EventEmitter {
27969
28314
  yMap.set(ElementModel.KEYS.ownerId, this.userManager.selfId);
27970
28315
  this.elements.set(uuid, yMap);
27971
28316
  }, elementsUndoOrigin);
27972
- const model = new EraserModel(yMap, this.scope, this.liveCursor);
28317
+ model.bindObserver();
27973
28318
  return model;
27974
28319
  }
27975
28320
  createTriangle(shadow) {
@@ -27977,45 +28322,54 @@ var RenderableModel = class extends EventEmitter {
27977
28322
  return null;
27978
28323
  }
27979
28324
  const yMap = new Y12.Map();
28325
+ const uuid = this.uuid;
28326
+ const triangleModel = new TriangleModel(yMap, this.scope, this.liveCursor, this.isPerformanceMode);
28327
+ this.elementModels.set(uuid, triangleModel);
27980
28328
  this.elements.doc?.transact(() => {
27981
- const uuid = this.uuid;
27982
28329
  yMap.set(ElementModel.KEYS.index, ++this.maxIndex);
27983
28330
  yMap.set(ElementModel.KEYS.uuid, uuid);
27984
28331
  yMap.set("type", "triangle");
27985
28332
  if (shadow) {
27986
28333
  yMap.set(ElementModel.KEYS.shadow, "layer");
27987
28334
  }
28335
+ yMap.set("points", new Y12.Array());
27988
28336
  yMap.set(ElementModel.KEYS.strokeWidth, this.toolbarModel.strokeWidth);
27989
28337
  yMap.set(ElementModel.KEYS.strokeColor, this.toolbarModel.strokeColor);
27990
28338
  yMap.set(ElementModel.KEYS.fillColor, this.toolbarModel.fillColor);
27991
28339
  yMap.set(ElementModel.KEYS.ownerId, this.userManager.selfId);
27992
28340
  this.elements.set(uuid, yMap);
27993
28341
  }, elementsUndoOrigin);
27994
- const triangle = new TriangleModel(yMap, this.scope, this.liveCursor);
27995
- this.initElement(triangle);
27996
- triangle.dashArray = this.toolbarModel.dashArray;
27997
- return triangle;
28342
+ triangleModel.bindObserver();
28343
+ this.initElement(triangleModel);
28344
+ triangleModel.dashArray = this.toolbarModel.dashArray;
28345
+ return triangleModel;
27998
28346
  }
27999
28347
  createRectangle(shadow) {
28000
28348
  if (!this.confirmPermission()) {
28001
28349
  return null;
28002
28350
  }
28003
28351
  const yMap = new Y12.Map();
28352
+ const uuid = this.uuid;
28353
+ const rect = new RectangleModel(yMap, this.scope, this.liveCursor, this.isPerformanceMode);
28354
+ this.elementModels.set(uuid, rect);
28004
28355
  this.elements.doc?.transact(() => {
28005
- const uuid = this.uuid;
28006
28356
  yMap.set(ElementModel.KEYS.index, ++this.maxIndex);
28007
28357
  yMap.set(ElementModel.KEYS.uuid, uuid);
28008
28358
  yMap.set("type", "rectangle");
28009
28359
  if (shadow) {
28010
28360
  yMap.set(ElementModel.KEYS.shadow, "layer");
28011
28361
  }
28362
+ const initPoints = new Y12.Array();
28363
+ initPoints.push([0, 0, 0, 0]);
28364
+ yMap.set("points", initPoints);
28365
+ yMap.set("radius", 0);
28012
28366
  yMap.set(ElementModel.KEYS.strokeWidth, this.toolbarModel.strokeWidth);
28013
28367
  yMap.set(ElementModel.KEYS.strokeColor, this.toolbarModel.strokeColor);
28014
28368
  yMap.set(ElementModel.KEYS.fillColor, this.toolbarModel.fillColor);
28015
28369
  yMap.set(ElementModel.KEYS.ownerId, this.userManager.selfId);
28016
28370
  this.elements.set(uuid, yMap);
28017
28371
  }, elementsUndoOrigin);
28018
- const rect = new RectangleModel(yMap, this.scope, this.liveCursor);
28372
+ rect.bindObserver();
28019
28373
  this.initElement(rect);
28020
28374
  rect.dashArray = this.toolbarModel.dashArray;
28021
28375
  return rect;
@@ -28025,21 +28379,24 @@ var RenderableModel = class extends EventEmitter {
28025
28379
  return null;
28026
28380
  }
28027
28381
  const yMap = new Y12.Map();
28382
+ const uuid = this.uuid;
28383
+ const segmentsModel = new SegmentsModel(yMap, this.scope, type, this.liveCursor, this.isPerformanceMode);
28384
+ this.elementModels.set(uuid, segmentsModel);
28028
28385
  this.elements.doc?.transact(() => {
28029
- const uuid = this.uuid;
28030
28386
  yMap.set(ElementModel.KEYS.index, ++this.maxIndex);
28031
28387
  yMap.set(ElementModel.KEYS.uuid, uuid);
28032
28388
  yMap.set("type", type);
28033
28389
  if (shadow) {
28034
28390
  yMap.set(ElementModel.KEYS.shadow, "layer");
28035
28391
  }
28392
+ yMap.set(ElementModel.KEYS.points, new Y12.Array());
28036
28393
  yMap.set(ElementModel.KEYS.strokeWidth, this.toolbarModel.strokeWidth);
28037
28394
  yMap.set(ElementModel.KEYS.strokeColor, this.toolbarModel.strokeColor);
28038
28395
  yMap.set(ElementModel.KEYS.fillColor, this.toolbarModel.fillColor);
28039
28396
  yMap.set(ElementModel.KEYS.ownerId, this.userManager.selfId);
28040
28397
  this.elements.set(uuid, yMap);
28041
28398
  }, elementsUndoOrigin);
28042
- const segmentsModel = new SegmentsModel(yMap, this.scope, type, this.liveCursor);
28399
+ segmentsModel.bindObserver();
28043
28400
  this.initElement(segmentsModel);
28044
28401
  segmentsModel.dashArray = this.toolbarModel.dashArray;
28045
28402
  return segmentsModel;
@@ -28050,16 +28407,21 @@ var RenderableModel = class extends EventEmitter {
28050
28407
  return null;
28051
28408
  }
28052
28409
  const yMap = new Y12.Map();
28410
+ const uuid = this.uuid;
28411
+ const selectorModel = new SelectorModel(yMap, this.scope, this.liveCursor, this.isPerformanceMode);
28412
+ this.elementModels.set(uuid, selectorModel);
28053
28413
  this.elements.doc?.transact(() => {
28054
- const uuid = this.uuid;
28055
28414
  yMap.set(ElementModel.KEYS.index, ++this.maxIndex);
28056
28415
  yMap.set(ElementModel.KEYS.uuid, uuid);
28057
28416
  yMap.set("type", "selector");
28417
+ const initPoints = new Y12.Array();
28418
+ initPoints.push([0, 0, 0, 0]);
28419
+ yMap.set(ElementModel.KEYS.points, initPoints);
28058
28420
  yMap.set(ElementModel.KEYS.shadow, "layer");
28059
28421
  yMap.set(ElementModel.KEYS.ownerId, this.userManager.selfId);
28060
28422
  this.elements.set(uuid, yMap);
28061
28423
  }, elementsUndoOrigin);
28062
- const selectorModel = new SelectorModel(yMap, this.scope, this.liveCursor);
28424
+ selectorModel.bindObserver();
28063
28425
  selectorModel.shadow = "layer";
28064
28426
  return selectorModel;
28065
28427
  }
@@ -28068,21 +28430,24 @@ var RenderableModel = class extends EventEmitter {
28068
28430
  return null;
28069
28431
  }
28070
28432
  const yMap = new Y12.Map();
28433
+ const uuid = this.uuid;
28434
+ const straightLineModel = new StraightLineModel(yMap, this.scope, this.liveCursor, this.isPerformanceMode);
28435
+ this.elementModels.set(uuid, straightLineModel);
28071
28436
  this.elements.doc?.transact(() => {
28072
- const uuid = this.uuid;
28073
28437
  yMap.set(ElementModel.KEYS.index, ++this.maxIndex);
28074
28438
  yMap.set(ElementModel.KEYS.uuid, uuid);
28075
28439
  yMap.set("type", "line");
28076
28440
  if (shadow) {
28077
28441
  yMap.set(ElementModel.KEYS.shadow, "layer");
28078
28442
  }
28443
+ yMap.set("points", new Y12.Array());
28079
28444
  yMap.set(ElementModel.KEYS.strokeWidth, this.toolbarModel.strokeWidth);
28080
28445
  yMap.set(ElementModel.KEYS.strokeColor, this.toolbarModel.strokeColor);
28081
28446
  yMap.set(ElementModel.KEYS.fillColor, this.toolbarModel.fillColor);
28082
28447
  yMap.set(ElementModel.KEYS.ownerId, this.userManager.selfId);
28083
28448
  this.elements.set(uuid, yMap);
28084
28449
  }, elementsUndoOrigin);
28085
- const straightLineModel = new StraightLineModel(yMap, this.scope, this.liveCursor);
28450
+ straightLineModel.bindObserver();
28086
28451
  this.initElement(straightLineModel);
28087
28452
  straightLineModel.dashArray = this.toolbarModel.dashArray;
28088
28453
  return straightLineModel;
@@ -28092,21 +28457,26 @@ var RenderableModel = class extends EventEmitter {
28092
28457
  return null;
28093
28458
  }
28094
28459
  const yMap = new Y12.Map();
28460
+ const uuid = this.uuid;
28461
+ const lineModel = new LineModel(yMap, this.scope, this.liveCursor, this.isPerformanceMode);
28462
+ this.elementModels.set(uuid, lineModel);
28095
28463
  this.elements.doc?.transact(() => {
28096
- const uuid = this.uuid;
28097
28464
  yMap.set(ElementModel.KEYS.index, ++this.maxIndex);
28098
28465
  yMap.set(ElementModel.KEYS.uuid, uuid);
28099
28466
  yMap.set("type", "arrow");
28100
28467
  if (shadow) {
28101
28468
  yMap.set(ElementModel.KEYS.shadow, "layer");
28102
28469
  }
28470
+ yMap.set("headArrow", "none");
28471
+ yMap.set("tailArrow", "normal");
28472
+ yMap.set(ElementModel.KEYS.points, new Y12.Array());
28103
28473
  yMap.set(ElementModel.KEYS.strokeWidth, this.toolbarModel.strokeWidth);
28104
28474
  yMap.set(ElementModel.KEYS.strokeColor, this.toolbarModel.strokeColor);
28105
28475
  yMap.set(ElementModel.KEYS.fillColor, this.toolbarModel.fillColor);
28106
28476
  yMap.set(ElementModel.KEYS.ownerId, this.userManager.selfId);
28107
28477
  this.elements.set(uuid, yMap);
28108
28478
  }, elementsUndoOrigin);
28109
- const lineModel = new LineModel(yMap, this.scope, this.liveCursor);
28479
+ lineModel.bindObserver();
28110
28480
  this.initElement(lineModel);
28111
28481
  lineModel.dashArray = this.toolbarModel.dashArray;
28112
28482
  return lineModel;
@@ -28116,22 +28486,24 @@ var RenderableModel = class extends EventEmitter {
28116
28486
  return null;
28117
28487
  }
28118
28488
  const yMap = new Y12.Map();
28489
+ const uuid = this.uuid;
28490
+ const pointTextModel = new PointTextModel(yMap, this.scope, this.liveCursor, this.isPerformanceMode);
28491
+ this.elementModels.set(uuid, pointTextModel);
28119
28492
  this.elements.doc?.transact(() => {
28120
- const uuid = this.uuid;
28121
28493
  yMap.set(ElementModel.KEYS.index, ++this.maxIndex);
28122
28494
  yMap.set(ElementModel.KEYS.uuid, uuid);
28123
28495
  yMap.set("type", "point-text");
28124
28496
  if (shadow) {
28125
28497
  yMap.set(ElementModel.KEYS.shadow, "layer");
28126
28498
  }
28499
+ yMap.set(ElementModel.KEYS.points, Y12.Array.from([x, y]));
28127
28500
  yMap.set(ElementModel.KEYS.strokeWidth, this.toolbarModel.strokeWidth);
28128
28501
  yMap.set(ElementModel.KEYS.strokeColor, this.toolbarModel.strokeColor);
28129
28502
  yMap.set(ElementModel.KEYS.fillColor, this.toolbarModel.fillColor);
28130
28503
  yMap.set(ElementModel.KEYS.ownerId, this.userManager.selfId);
28131
28504
  this.elements.set(uuid, yMap);
28132
28505
  }, elementsUndoOrigin);
28133
- const pointTextModel = new PointTextModel(yMap, this.scope, this.liveCursor);
28134
- pointTextModel.setPoints([x, y]);
28506
+ pointTextModel.bindObserver();
28135
28507
  pointTextModel.fontSize = this.toolbarModel.fontSize;
28136
28508
  pointTextModel.fontFamily = this.toolbarModel.fontFamily;
28137
28509
  this.initElement(pointTextModel);
@@ -28153,12 +28525,13 @@ var RenderableModel = class extends EventEmitter {
28153
28525
  });
28154
28526
  }
28155
28527
  dispose(clearElements) {
28156
- removeObserver2(this.elements, this.onElementsChange);
28528
+ removeObserver3(this.elements, this.onElementsChange);
28157
28529
  if (clearElements) {
28158
28530
  this.elements.clear();
28159
28531
  }
28160
28532
  Array.from(this.elementModels.values()).forEach((model) => {
28161
28533
  model.dispose();
28534
+ model.disposeObserver();
28162
28535
  });
28163
28536
  }
28164
28537
  };
@@ -28455,11 +28828,24 @@ var CurveTool = class extends WhiteboardTool {
28455
28828
  _defineProperty19(this, "elementModel", null);
28456
28829
  _defineProperty19(this, "recognizer", new Recognizer());
28457
28830
  _defineProperty19(this, "pointCount", 0);
28831
+ _defineProperty19(this, "pendingPoints", []);
28832
+ _defineProperty19(this, "flushRafId", 0);
28458
28833
  _defineProperty19(this, "showLiveCursor", true);
28459
- this.tool.minDistance = 5;
28834
+ _defineProperty19(this, "flushPendingPoints", () => {
28835
+ this.flushRafId = 0;
28836
+ if (this.elementModel && this.pendingPoints.length > 0) {
28837
+ this.elementModel.appendPoints(this.pendingPoints);
28838
+ this.pendingPoints = [];
28839
+ }
28840
+ });
28460
28841
  }
28461
28842
  onMouseDown(_event) {
28462
28843
  this.pointCount = 0;
28844
+ this.pendingPoints = [];
28845
+ if (this.flushRafId) {
28846
+ cancelAnimationFrame(this.flushRafId);
28847
+ this.flushRafId = 0;
28848
+ }
28463
28849
  if (this.elementModel) {
28464
28850
  this.elementModel.dispose();
28465
28851
  }
@@ -28474,27 +28860,36 @@ var CurveTool = class extends WhiteboardTool {
28474
28860
  if (this.pointCount > 1024) {
28475
28861
  return;
28476
28862
  }
28477
- const MIN_DISTANCE = 4;
28863
+ const MIN_DISTANCE = 2;
28478
28864
  if (this.elementModel) {
28479
- const len = this.elementModel.points.length;
28480
- let last = {
28481
- x: 0,
28482
- y: 0
28483
- };
28484
- if (len >= 2) {
28485
- last = {
28486
- x: this.elementModel.points[len - 2],
28487
- y: this.elementModel.points[len - 1]
28488
- };
28865
+ let lastX = 0;
28866
+ let lastY = 0;
28867
+ if (this.pendingPoints.length >= 2) {
28868
+ lastX = this.pendingPoints[this.pendingPoints.length - 2];
28869
+ lastY = this.pendingPoints[this.pendingPoints.length - 1];
28870
+ } else {
28871
+ const len = this.elementModel.points.length;
28872
+ if (len >= 2) {
28873
+ lastX = this.elementModel.points[len - 2];
28874
+ lastY = this.elementModel.points[len - 1];
28875
+ }
28489
28876
  }
28490
- const dist = Math.max(Math.abs(last.x - event.point.x), Math.abs(last.y - event.point.y));
28877
+ const dist = Math.max(Math.abs(lastX - event.point.x), Math.abs(lastY - event.point.y));
28491
28878
  if (dist >= MIN_DISTANCE) {
28492
28879
  this.pointCount += 1;
28493
- this.elementModel.appendPoints([Math.round(event.point.x), Math.round(event.point.y)]);
28880
+ this.pendingPoints.push(event.point.x, event.point.y);
28881
+ if (!this.flushRafId) {
28882
+ this.flushRafId = requestAnimationFrame(this.flushPendingPoints);
28883
+ }
28494
28884
  }
28495
28885
  }
28496
28886
  }
28497
28887
  onMouseUp(event) {
28888
+ if (this.flushRafId) {
28889
+ cancelAnimationFrame(this.flushRafId);
28890
+ this.flushRafId = 0;
28891
+ }
28892
+ this.flushPendingPoints();
28498
28893
  this.modelGetter().then((model) => {
28499
28894
  if (!model) {
28500
28895
  return;
@@ -28595,7 +28990,7 @@ var RectangleTool = class extends WhiteboardTool {
28595
28990
 
28596
28991
  // src/model/ToolbarModel.ts
28597
28992
  import EventEmitter2 from "eventemitter3";
28598
- import { removeObserver as removeObserver3 } from "@netless/forge-room";
28993
+ import { removeObserver as removeObserver4 } from "@netless/forge-room";
28599
28994
  function _defineProperty21(e, r, t) {
28600
28995
  return (r = _toPropertyKey21(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: true, configurable: true, writable: true }) : e[r] = t, e;
28601
28996
  }
@@ -28692,7 +29087,7 @@ var ToolbarModel = class extends EventEmitter2 {
28692
29087
  });
28693
29088
  }
28694
29089
  dispose() {
28695
- removeObserver3(this.root, this.handleRootUpdate);
29090
+ removeObserver4(this.root, this.handleRootUpdate);
28696
29091
  this.removeAllListeners();
28697
29092
  }
28698
29093
  };
@@ -29626,6 +30021,7 @@ var Editor = class extends EventEmitter5 {
29626
30021
  this.shadowContainer.remove();
29627
30022
  this.shadowScope.project.activeLayer.addChild(this.shadowContainer);
29628
30023
  this.targets.forEach((model) => {
30024
+ console.log("[][][] translateShadow model", model.root._dEH);
29629
30025
  model.shadow = this.shadowContainer.data.uuid;
29630
30026
  });
29631
30027
  }
@@ -29852,7 +30248,7 @@ var Gesture = class extends EventEmitter6 {
29852
30248
  };
29853
30249
 
29854
30250
  // src/Camera.ts
29855
- import { removeObserver as removeObserver4 } from "@netless/forge-room";
30251
+ import { removeObserver as removeObserver5 } from "@netless/forge-room";
29856
30252
  function _defineProperty28(e, r, t) {
29857
30253
  return (r = _toPropertyKey28(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: true, configurable: true, writable: true }) : e[r] = t, e;
29858
30254
  }
@@ -29929,14 +30325,14 @@ var Camera = class extends EventEmitter7 {
29929
30325
  }
29930
30326
  const cb = this.observers.get(user.id);
29931
30327
  if (cb) {
29932
- removeObserver4(this.requestUserMap(user.id), cb);
30328
+ removeObserver5(this.requestUserMap(user.id), cb);
29933
30329
  }
29934
30330
  });
29935
30331
  _defineProperty28(this, "handleUserJoin", (user) => {
29936
30332
  if (this.observers.has(user.id)) {
29937
30333
  const cb = this.observers.get(user.id);
29938
30334
  if (cb) {
29939
- removeObserver4(this.requestUserMap(user.id), cb);
30335
+ removeObserver5(this.requestUserMap(user.id), cb);
29940
30336
  this.observers.delete(user.id);
29941
30337
  }
29942
30338
  }
@@ -30048,7 +30444,7 @@ var Camera = class extends EventEmitter7 {
30048
30444
  this.handleViewMatrixUpdate(userId, evt);
30049
30445
  };
30050
30446
  if (this.observers.has(userId)) {
30051
- removeObserver4(this.requestUserMap(userId), observer);
30447
+ removeObserver5(this.requestUserMap(userId), observer);
30052
30448
  }
30053
30449
  this.requestUserMap(userId).observe(observer);
30054
30450
  this.observers.set(userId, observer);
@@ -30245,10 +30641,10 @@ var Camera = class extends EventEmitter7 {
30245
30641
  Array.from(this.observers.keys()).forEach((userId) => {
30246
30642
  const cb = this.observers.get(userId);
30247
30643
  if (cb) {
30248
- removeObserver4(this.requestUserMap(userId), cb);
30644
+ removeObserver5(this.requestUserMap(userId), cb);
30249
30645
  }
30250
30646
  });
30251
- removeObserver4(this.whiteboardAttrsMap, this.handleMainCameraChange);
30647
+ removeObserver5(this.whiteboardAttrsMap, this.handleMainCameraChange);
30252
30648
  this.userManager.off("join", this.handleUserJoin);
30253
30649
  this.userManager.off("leave", this.handleUserLeave);
30254
30650
  this.gesture.removeAllListeners();
@@ -30419,6 +30815,8 @@ var Whiteboard = class extends EventEmitter8 {
30419
30815
  _defineProperty31(this, "enableCameraBoundaryHighlight", void 0);
30420
30816
  _defineProperty31(this, "getElementAttribute", void 0);
30421
30817
  _defineProperty31(this, "setElementAttribute", void 0);
30818
+ _defineProperty31(this, "setPerformanceMode", void 0);
30819
+ _defineProperty31(this, "isPerformanceMode", void 0);
30422
30820
  _defineProperty31(this, "removeElement", void 0);
30423
30821
  _defineProperty31(this, "getCurrentTool", void 0);
30424
30822
  _defineProperty31(this, "setCurrentTool", void 0);
@@ -30717,9 +31115,24 @@ var LaserPointerTool = class extends WhiteboardTool {
30717
31115
  if (this.pointCount > 1024) {
30718
31116
  return;
30719
31117
  }
31118
+ const MIN_DISTANCE = 4;
30720
31119
  if (this.elementModel) {
30721
- this.pointCount += 1;
30722
- this.elementModel.appendPoints([event.point.x, event.point.y]);
31120
+ const len = this.elementModel.points.length;
31121
+ let last = {
31122
+ x: 0,
31123
+ y: 0
31124
+ };
31125
+ if (len >= 2) {
31126
+ last = {
31127
+ x: this.elementModel.points[len - 2],
31128
+ y: this.elementModel.points[len - 1]
31129
+ };
31130
+ }
31131
+ const dist = Math.max(Math.abs(last.x - event.point.x), Math.abs(last.y - event.point.y));
31132
+ if (dist >= MIN_DISTANCE) {
31133
+ this.pointCount += 1;
31134
+ this.elementModel.appendPoints([Math.round(event.point.x), Math.round(event.point.y)]);
31135
+ }
30723
31136
  }
30724
31137
  }
30725
31138
  onMouseUp(_event) {
@@ -30731,7 +31144,7 @@ var LaserPointerTool = class extends WhiteboardTool {
30731
31144
 
30732
31145
  // src/model/PageModel.ts
30733
31146
  import EventEmitter10 from "eventemitter3";
30734
- import { log as log2, removeObserver as removeObserver5 } from "@netless/forge-room";
31147
+ import { log as log2, removeObserver as removeObserver6 } from "@netless/forge-room";
30735
31148
  function _defineProperty35(e, r, t) {
30736
31149
  return (r = _toPropertyKey35(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: true, configurable: true, writable: true }) : e[r] = t, e;
30737
31150
  }
@@ -30764,7 +31177,7 @@ var PageModel = class extends EventEmitter10 {
30764
31177
  }
30765
31178
  const cb = this.observers.get(user.id);
30766
31179
  if (cb) {
30767
- removeObserver5(this.requestUserMap(user.id), cb);
31180
+ removeObserver6(this.requestUserMap(user.id), cb);
30768
31181
  }
30769
31182
  });
30770
31183
  _defineProperty35(this, "handleUserJoin", (user) => {
@@ -30825,7 +31238,7 @@ var PageModel = class extends EventEmitter10 {
30825
31238
  if (this.observers.has(userId)) {
30826
31239
  const cb = this.observers.get(userId);
30827
31240
  if (cb) {
30828
- removeObserver5(this.requestUserMap(userId), cb);
31241
+ removeObserver6(this.requestUserMap(userId), cb);
30829
31242
  this.observers.delete(userId);
30830
31243
  }
30831
31244
  }
@@ -30914,12 +31327,12 @@ var PageModel = class extends EventEmitter10 {
30914
31327
  dispose() {
30915
31328
  for (const entry of this.observers.entries()) {
30916
31329
  const [userId, observer] = entry;
30917
- removeObserver5(this.requestUserMap(userId), observer);
31330
+ removeObserver6(this.requestUserMap(userId), observer);
30918
31331
  }
30919
31332
  this.userManager.off("join", this.handleUserJoin);
30920
31333
  this.userManager.off("leave", this.handleUserLeave);
30921
- removeObserver5(this.whiteboardAttrsMap, this.handleMainPageChange);
30922
- removeObserver5(this.pageMap, this.handlePageMapChange);
31334
+ removeObserver6(this.whiteboardAttrsMap, this.handleMainPageChange);
31335
+ removeObserver6(this.pageMap, this.handlePageMapChange);
30923
31336
  }
30924
31337
  };
30925
31338
 
@@ -30935,7 +31348,7 @@ async function waitUntil(fn, timeout) {
30935
31348
  // src/IndexedNavigation.ts
30936
31349
  import EventEmitter11 from "eventemitter3";
30937
31350
  import { log as log3 } from "@netless/forge-room";
30938
- import { removeObserver as removeObserver6 } from "@netless/forge-room";
31351
+ import { removeObserver as removeObserver7 } from "@netless/forge-room";
30939
31352
  function _defineProperty36(e, r, t) {
30940
31353
  return (r = _toPropertyKey36(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: true, configurable: true, writable: true }) : e[r] = t, e;
30941
31354
  }
@@ -31278,7 +31691,7 @@ var IndexedNavigation = class extends EventEmitter11 {
31278
31691
  }
31279
31692
  }
31280
31693
  dispose() {
31281
- removeObserver6(this.indexedPageMap, this.handleIndexedPageMapUpdate);
31694
+ removeObserver7(this.indexedPageMap, this.handleIndexedPageMapUpdate);
31282
31695
  this.pageModel.off("switchPage");
31283
31696
  this.pageModel.off("pagesChange");
31284
31697
  }
@@ -31499,7 +31912,7 @@ var SequenceExecutor = class {
31499
31912
  };
31500
31913
 
31501
31914
  // src/WhiteboardApplication.ts
31502
- import { removeObserver as removeObserver7 } from "@netless/forge-room";
31915
+ import { removeObserver as removeObserver8 } from "@netless/forge-room";
31503
31916
 
31504
31917
  // src/LiveCursor.ts
31505
31918
  function _defineProperty42(e, r, t) {
@@ -31554,9 +31967,19 @@ var LiveCursor = class {
31554
31967
  cursor.style.fontSize = "12px";
31555
31968
  cursor.style.padding = "2px 4px";
31556
31969
  cursor.style.borderRadius = "4px";
31557
- cursor.textContent = this.userManager.getUser(userId)?.nickName ?? userId;
31970
+ this.updateCursorLabel(userId, cursor);
31558
31971
  return cursor;
31559
31972
  }
31973
+ updateCursorLabel(userId, cursor) {
31974
+ const target = cursor ?? this.cursors.get(userId);
31975
+ if (!target) {
31976
+ return;
31977
+ }
31978
+ if (target.textContent && target.textContent !== userId) {
31979
+ return;
31980
+ }
31981
+ target.textContent = this.userManager.getUser(userId)?.nickName ?? userId;
31982
+ }
31560
31983
  isOnSamePage(userId) {
31561
31984
  const otherPage = this.requestUserMap(userId).get(WhiteboardKeys.currentPage);
31562
31985
  const selfPage = this.requestUserMap(this.userManager.selfId).get(WhiteboardKeys.currentPage);
@@ -31592,6 +32015,7 @@ var LiveCursor = class {
31592
32015
  }
31593
32016
  const cursor = this.cursors.get(userId);
31594
32017
  if (cursor) {
32018
+ this.updateCursorLabel(userId, cursor);
31595
32019
  const viewPoint = this.paperScope.project.view.projectToView(point);
31596
32020
  cursor.style.left = viewPoint.x + "px";
31597
32021
  cursor.style.top = viewPoint.y + "px";
@@ -31707,6 +32131,7 @@ var WhiteboardApplication = class _WhiteboardApplication extends AbstractApplica
31707
32131
  _defineProperty43(this, "permissions", void 0);
31708
32132
  _defineProperty43(this, "inputType", "any");
31709
32133
  _defineProperty43(this, "isPenEvent", false);
32134
+ _defineProperty43(this, "activePenPointerId", null);
31710
32135
  _defineProperty43(this, "hasPenInput", null);
31711
32136
  _defineProperty43(this, "disableViewModelUpdate", false);
31712
32137
  _defineProperty43(this, "internalResizeObserver", true);
@@ -31823,6 +32248,9 @@ var WhiteboardApplication = class _WhiteboardApplication extends AbstractApplica
31823
32248
  _defineProperty43(this, "hasPermission", (flag) => {
31824
32249
  return this.permissions.hasPermission(flag, this.userId);
31825
32250
  });
32251
+ _defineProperty43(this, "isPerformanceMode", () => {
32252
+ return this.option.performance ?? false;
32253
+ });
31826
32254
  _defineProperty43(this, "handleStackItemAdded", () => {
31827
32255
  this.selectElementsModel.clearSelectElementForSelf();
31828
32256
  this.emitter.emit("redoStackLength", this.undoManager?.redoStack.length ?? 0);
@@ -31837,7 +32265,18 @@ var WhiteboardApplication = class _WhiteboardApplication extends AbstractApplica
31837
32265
  const id = ids[i];
31838
32266
  if (!this.layers.has(id)) {
31839
32267
  const elementsMap = this.getMap(`layer/${id}/elements`);
31840
- const renderableModel = new RenderableModel(id, this.shadowEmitter, elementsMap, this.paperScope, this.toolbarModel, this.userManager, this.imageSets, this.liveCursor, this.hasPermission);
32268
+ const renderableModel = new RenderableModel({
32269
+ layerId: id,
32270
+ shadowEmitter: this.shadowEmitter,
32271
+ elements: elementsMap,
32272
+ scope: this.paperScope,
32273
+ toolbarModel: this.toolbarModel,
32274
+ userManager: this.userManager,
32275
+ imageSets: this.imageSets,
32276
+ liveCursor: this.liveCursor,
32277
+ hasPermission: this.hasPermission,
32278
+ isPerformanceMode: this.isPerformanceMode
32279
+ });
31841
32280
  this.layers.set(id, renderableModel);
31842
32281
  }
31843
32282
  if (!this.undoManagers.has(id)) {
@@ -32021,11 +32460,34 @@ var WhiteboardApplication = class _WhiteboardApplication extends AbstractApplica
32021
32460
  this.imageSets.setAttribute("data-image-sets", "");
32022
32461
  this.rootElement.appendChild(this.imageSets);
32023
32462
  document.body.addEventListener("pointerdown", (evt) => {
32024
- this.isPenEvent = evt.pointerType === "pen";
32025
- if (evt.pointerType === "pen" && this.hasPenInput === null) {
32026
- this.hasPenInput = true;
32027
- this.inputType = "pen";
32028
- this.emitter.emit("inputTypeChange", this.inputType);
32463
+ if (evt.pointerType === "pen") {
32464
+ this.isPenEvent = true;
32465
+ this.activePenPointerId = evt.pointerId;
32466
+ if (this.hasPenInput === null) {
32467
+ this.hasPenInput = true;
32468
+ this.inputType = "pen";
32469
+ this.emitter.emit("inputTypeChange", this.inputType);
32470
+ }
32471
+ } else {
32472
+ if (this.activePenPointerId === null) {
32473
+ this.isPenEvent = false;
32474
+ }
32475
+ }
32476
+ }, {
32477
+ capture: true
32478
+ });
32479
+ document.body.addEventListener("pointerup", (evt) => {
32480
+ if (evt.pointerId === this.activePenPointerId) {
32481
+ this.activePenPointerId = null;
32482
+ this.isPenEvent = false;
32483
+ }
32484
+ }, {
32485
+ capture: true
32486
+ });
32487
+ document.body.addEventListener("pointercancel", (evt) => {
32488
+ if (evt.pointerId === this.activePenPointerId) {
32489
+ this.activePenPointerId = null;
32490
+ this.isPenEvent = false;
32029
32491
  }
32030
32492
  }, {
32031
32493
  capture: true
@@ -32104,6 +32566,12 @@ var WhiteboardApplication = class _WhiteboardApplication extends AbstractApplica
32104
32566
  this.camera.resetViewMatrixToFlow(flowId);
32105
32567
  }
32106
32568
  };
32569
+ this.emitter.setPerformanceMode = (enabled) => {
32570
+ this.option.performance = enabled;
32571
+ };
32572
+ this.emitter.isPerformanceMode = () => {
32573
+ return this.isPerformanceMode();
32574
+ };
32107
32575
  this.emitter.setViewModeToMain = (userId) => {
32108
32576
  if (that.disableViewModelUpdate) {
32109
32577
  console.warn("Operation failed. Perspective mode switching is disabled in the current environment.");
@@ -32158,7 +32626,18 @@ var WhiteboardApplication = class _WhiteboardApplication extends AbstractApplica
32158
32626
  const source = this.getMap(`layer/${sourceId}/elements`);
32159
32627
  const target = this.getMap(`layer/${targetId}/elements`);
32160
32628
  if (!this.layers.has(targetId)) {
32161
- this.layers.set(targetId, new RenderableModel(targetId, this.shadowEmitter, target, this.paperScope, this.toolbarModel, this.userManager, this.imageSets, this.liveCursor, this.hasPermission));
32629
+ this.layers.set(targetId, new RenderableModel({
32630
+ layerId: targetId,
32631
+ shadowEmitter: this.shadowEmitter,
32632
+ elements: target,
32633
+ scope: this.paperScope,
32634
+ toolbarModel: this.toolbarModel,
32635
+ userManager: this.userManager,
32636
+ imageSets: this.imageSets,
32637
+ liveCursor: this.liveCursor,
32638
+ hasPermission: this.hasPermission,
32639
+ isPerformanceMode: this.isPerformanceMode
32640
+ }));
32162
32641
  }
32163
32642
  if (!this.undoManagers.has(targetId)) {
32164
32643
  const undoManager = new Y15.UndoManager(target, {
@@ -32393,6 +32872,11 @@ var WhiteboardApplication = class _WhiteboardApplication extends AbstractApplica
32393
32872
  this.editors.forEach((editor) => {
32394
32873
  editor.updateBounds();
32395
32874
  });
32875
+ const area = this.paperScope.project.view.size.width * this.paperScope.project.view.size.height;
32876
+ const minDistance = Math.ceil(area / 4e5);
32877
+ Object.keys(this.tools).forEach((key) => {
32878
+ this.tools[key].tool.minDistance = minDistance;
32879
+ });
32396
32880
  });
32397
32881
  this.camera.on("userPageChange", (userId, pageId) => {
32398
32882
  this.emitter.emit("activePageChange", userId, pageId);
@@ -32661,9 +33145,14 @@ var WhiteboardApplication = class _WhiteboardApplication extends AbstractApplica
32661
33145
  this.snapshotScope.view.matrix.scale(scale, this.paperScope.project.view.bounds.topLeft);
32662
33146
  this.snapshotScope.view.viewSize = this.paperScope.project.view.viewSize.clone().multiply(scale);
32663
33147
  }
32664
- return new Promise((resolve) => {
33148
+ return new Promise((resolve, reject) => {
32665
33149
  setTimeout(() => {
32666
- resolve(this.snapshotScope.view.element.toDataURL("image/png"));
33150
+ try {
33151
+ const res = this.snapshotScope.view.element.toDataURL("image/png");
33152
+ resolve(res);
33153
+ } catch (error) {
33154
+ reject(error);
33155
+ }
32667
33156
  }, 32);
32668
33157
  });
32669
33158
  }
@@ -32741,7 +33230,7 @@ var WhiteboardApplication = class _WhiteboardApplication extends AbstractApplica
32741
33230
  this.toolbarModel.dispose();
32742
33231
  this.emitter.indexedNavigation.dispose();
32743
33232
  this.permissions.dispose();
32744
- removeObserver7(this.userMap(this.userId), this.handleSyncedWhiteboardStatusChange);
33233
+ removeObserver8(this.userMap(this.userId), this.handleSyncedWhiteboardStatusChange);
32745
33234
  log4(`whiteboard ${this.appId} disposed. instance count: ${_WhiteboardApplication.instanceCount.get(this.appId) ?? 0}`, {}, "info");
32746
33235
  }
32747
33236
  };