@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);
@@ -25639,7 +25639,7 @@ __export(src_exports, {
25639
25639
  module.exports = __toCommonJS(src_exports);
25640
25640
 
25641
25641
  // src/WhiteboardApplication.ts
25642
- var import_forge_room12 = require("@netless/forge-room");
25642
+ var import_forge_room14 = require("@netless/forge-room");
25643
25643
  var Y15 = __toESM(require("yjs"), 1);
25644
25644
  var import_paper = __toESM(require_paper_full(), 1);
25645
25645
 
@@ -25647,10 +25647,11 @@ var import_paper = __toESM(require_paper_full(), 1);
25647
25647
  var Y12 = __toESM(require("yjs"), 1);
25648
25648
  var import_eventemitter3 = __toESM(require("eventemitter3"), 1);
25649
25649
  var import_uuid = require("uuid");
25650
- var import_forge_room4 = require("@netless/forge-room");
25650
+ var import_forge_room6 = require("@netless/forge-room");
25651
25651
 
25652
25652
  // src/model/renderable/CurveModel.ts
25653
25653
  var Y2 = __toESM(require("yjs"), 1);
25654
+ var import_lodash = __toESM(require_lodash(), 1);
25654
25655
 
25655
25656
  // ../../node_modules/.pnpm/perfect-freehand@1.2.2/node_modules/perfect-freehand/dist/esm/index.mjs
25656
25657
  function $(e, t, u, x = (h) => h) {
@@ -25800,9 +25801,6 @@ function ae(e, t = {}) {
25800
25801
  return ce(me(e, t), t);
25801
25802
  }
25802
25803
 
25803
- // src/model/renderable/CurveModel.ts
25804
- var import_lodash = __toESM(require_lodash(), 1);
25805
-
25806
25804
  // src/model/renderable/ElementModel.ts
25807
25805
  var Y = __toESM(require("yjs"), 1);
25808
25806
  var import_forge_room = require("@netless/forge-room");
@@ -25890,12 +25888,23 @@ var ElementModel = class _ElementModel {
25890
25888
  set shadow(value) {
25891
25889
  this.root.set(_ElementModel.KEYS.shadow, value);
25892
25890
  }
25893
- constructor(root, scope, liveCursor) {
25891
+ get isPerformanceEnvironment() {
25892
+ return this.isPerformanceMode() && this.shouldUseLocalPoints;
25893
+ }
25894
+ constructor(root, scope, liveCursor, isPerformanceMode) {
25894
25895
  _defineProperty(this, "shadowEmitter", null);
25895
25896
  _defineProperty(this, "root", void 0);
25896
25897
  _defineProperty(this, "scope", void 0);
25897
25898
  _defineProperty(this, "item", void 0);
25899
+ _defineProperty(this, "clearLocalPointsWhenYPointsChange", void 0);
25900
+ _defineProperty(this, "shouldUseLocalPoints", void 0);
25901
+ _defineProperty(this, "localPointsPick", void 0);
25898
25902
  _defineProperty(this, "liveCursor", void 0);
25903
+ _defineProperty(this, "appendPointsTimer", null);
25904
+ _defineProperty(this, "setPointsTimer", null);
25905
+ _defineProperty(this, "pointsUpdateTimer", null);
25906
+ _defineProperty(this, "isPerformanceMode", void 0);
25907
+ _defineProperty(this, "localPoints", []);
25899
25908
  _defineProperty(this, "handlePropChange", (events) => {
25900
25909
  if (!this.item) {
25901
25910
  return;
@@ -25934,23 +25943,80 @@ var ElementModel = class _ElementModel {
25934
25943
  }
25935
25944
  }
25936
25945
  } else if (event.target === this.root.get(_ElementModel.KEYS.points)) {
25937
- this.onVectorUpdate();
25938
- const liveCursorPoint = this.liveCursorPoint();
25939
- const ownerId = this.root.get(_ElementModel.KEYS.ownerId);
25940
- if (liveCursorPoint && ownerId) {
25941
- this.liveCursor.updateCursorPosition(liveCursorPoint, this.root.get(_ElementModel.KEYS.ownerId));
25946
+ if (this.isPerformanceEnvironment) {
25947
+ this.handlePointsChangePerformance();
25948
+ } else {
25949
+ this.handlePointsChangeDirect();
25942
25950
  }
25943
25951
  } else {
25944
25952
  }
25945
25953
  }
25946
25954
  });
25955
+ _defineProperty(this, "onPointsArrayChange", (points) => {
25956
+ if (this.localPoints.length >= points.length) {
25957
+ return;
25958
+ }
25959
+ const pointsChunk = points.slice(this.localPoints.length, this.localPoints.length + this.localPointsPick);
25960
+ this.localPoints = this.localPoints.concat(pointsChunk);
25961
+ this.onVectorUpdate();
25962
+ this.pointsUpdateTimer = window.requestAnimationFrame(() => {
25963
+ this.onPointsArrayChange(points);
25964
+ });
25965
+ });
25966
+ this.isPerformanceMode = isPerformanceMode;
25947
25967
  this.scope = scope;
25948
25968
  this.liveCursor = liveCursor;
25949
25969
  this.root = root;
25950
- if (!this.root.has(_ElementModel.KEYS.pointsMatrix)) {
25970
+ if (this.root.doc) {
25971
+ if (!this.root.has(_ElementModel.KEYS.pointsMatrix)) {
25972
+ this.root.set(_ElementModel.KEYS.pointsMatrix, [1, 0, 0, 1, 0, 0]);
25973
+ }
25974
+ } else {
25951
25975
  this.root.set(_ElementModel.KEYS.pointsMatrix, [1, 0, 0, 1, 0, 0]);
25952
25976
  }
25977
+ }
25978
+ bindObserver() {
25979
+ const beforeL = this.root._eH?.l?.length ?? -1;
25980
+ const beforeDL = this.root._dEH?.l?.length ?? -1;
25981
+ (0, import_forge_room.removeDeepObserver)(this.root, this.handlePropChange);
25982
+ this.subBindObserver();
25983
+ const afterRemoveL = this.root._eH?.l?.length ?? -1;
25984
+ const afterRemoveDL = this.root._dEH?.l?.length ?? -1;
25953
25985
  this.root.observeDeep(this.handlePropChange);
25986
+ const afterAddL = this.root._eH?.l?.length ?? -1;
25987
+ const afterAddDL = this.root._dEH?.l?.length ?? -1;
25988
+ console.log(`[][][] bindObserver uuid=${this.uuid} doc=${!!this.root.doc} _eH: ${beforeL}->${afterRemoveL}->${afterAddL} _dEH: ${beforeDL}->${afterRemoveDL}->${afterAddDL}`);
25989
+ }
25990
+ subBindObserver() {
25991
+ }
25992
+ handlePointsChangeDirect() {
25993
+ this.onVectorUpdate();
25994
+ const liveCursorPoint = this.liveCursorPoint();
25995
+ const ownerId = this.root.get(_ElementModel.KEYS.ownerId);
25996
+ if (liveCursorPoint && ownerId) {
25997
+ this.liveCursor.updateCursorPosition(liveCursorPoint, this.root.get(_ElementModel.KEYS.ownerId));
25998
+ }
25999
+ }
26000
+ handlePointsChangePerformance() {
26001
+ const liveCursorPoint = this.liveCursorPoint();
26002
+ const ownerId = this.root.get(_ElementModel.KEYS.ownerId);
26003
+ if (liveCursorPoint && ownerId) {
26004
+ this.liveCursor.updateCursorPosition(liveCursorPoint, this.root.get(_ElementModel.KEYS.ownerId));
26005
+ }
26006
+ if (this.liveCursor.userManager.selfId !== ownerId || this.localPoints.length === 0) {
26007
+ if (this.pointsUpdateTimer) {
26008
+ window.cancelAnimationFrame(this.pointsUpdateTimer);
26009
+ }
26010
+ if (this.shadow == "") {
26011
+ this.localPoints = this.points;
26012
+ this.onVectorUpdate();
26013
+ } else {
26014
+ if (this.clearLocalPointsWhenYPointsChange) {
26015
+ this.localPoints = [];
26016
+ }
26017
+ this.onPointsArrayChange(this.points);
26018
+ }
26019
+ }
25954
26020
  }
25955
26021
  createPaperElement() {
25956
26022
  this.createPaperItem();
@@ -25963,14 +26029,48 @@ var ElementModel = class _ElementModel {
25963
26029
  }
25964
26030
  }
25965
26031
  appendPoints(points) {
26032
+ if (this.isPerformanceEnvironment) {
26033
+ this.appendPointsPerformance(points);
26034
+ } else {
26035
+ this.appendPointsDirect(points);
26036
+ }
26037
+ }
26038
+ appendPointsDirect(points) {
25966
26039
  this.root.get(_ElementModel.KEYS.points).push(points);
25967
26040
  }
26041
+ appendPointsPerformance(points) {
26042
+ this.localPoints = this.localPoints.concat(points);
26043
+ this.onVectorUpdate();
26044
+ if (this.appendPointsTimer) {
26045
+ window.clearTimeout(this.appendPointsTimer);
26046
+ }
26047
+ if (this.localPoints.length % 80 === 0) {
26048
+ const yArray = this.root.get(_ElementModel.KEYS.points);
26049
+ yArray?.push(this.localPoints.slice(yArray.length));
26050
+ }
26051
+ this.appendPointsTimer = window.setTimeout(() => {
26052
+ this.appendPointsTimer = null;
26053
+ if (this.localPoints.length > 0) {
26054
+ const yArray = this.root.get(_ElementModel.KEYS.points);
26055
+ yArray?.push(this.localPoints.slice(yArray.length));
26056
+ }
26057
+ }, 100);
26058
+ }
25968
26059
  setPoints(points) {
26060
+ if (this.isPerformanceEnvironment) {
26061
+ this.setPointsPerformance(points);
26062
+ } else {
26063
+ this.setPointsDirect(points);
26064
+ }
26065
+ }
26066
+ setPointsDirect(points) {
25969
26067
  if (this.root.doc) {
25970
26068
  this.root.doc.transact(() => {
25971
26069
  const yArray = this.root.get(_ElementModel.KEYS.points);
25972
- yArray.delete(0, yArray.length);
25973
- yArray.push(points);
26070
+ if (yArray) {
26071
+ yArray.delete(0, yArray.length);
26072
+ yArray.push(points);
26073
+ }
25974
26074
  });
25975
26075
  } else {
25976
26076
  const yArray = this.root.get(_ElementModel.KEYS.points) || new Y.Array();
@@ -25979,6 +26079,29 @@ var ElementModel = class _ElementModel {
25979
26079
  this.root.set(_ElementModel.KEYS.points, yArray);
25980
26080
  }
25981
26081
  }
26082
+ setPointsPerformance(points) {
26083
+ this.localPoints = points;
26084
+ this.onVectorUpdate();
26085
+ if (this.setPointsTimer) {
26086
+ window.clearTimeout(this.setPointsTimer);
26087
+ }
26088
+ this.setPointsTimer = window.setTimeout(() => {
26089
+ if (this.root.doc) {
26090
+ this.root.doc.transact(() => {
26091
+ const yArray = this.root.get(_ElementModel.KEYS.points);
26092
+ if (yArray) {
26093
+ yArray.delete(0, yArray.length);
26094
+ yArray.push(points);
26095
+ }
26096
+ });
26097
+ } else {
26098
+ const yArray = this.root.get(_ElementModel.KEYS.points) || new Y.Array();
26099
+ yArray.delete(0, yArray.length);
26100
+ yArray.push(points);
26101
+ this.root.set(_ElementModel.KEYS.points, yArray);
26102
+ }
26103
+ }, 100);
26104
+ }
25982
26105
  appendPointsMatrix(matrix) {
25983
26106
  const current = new this.scope.Matrix(this.pointsMatrix);
25984
26107
  const next = matrix.appended(current);
@@ -26005,6 +26128,9 @@ var ElementModel = class _ElementModel {
26005
26128
  }
26006
26129
  dispose() {
26007
26130
  this.subDispose();
26131
+ }
26132
+ disposeObserver() {
26133
+ console.log(`[][][] disposeObserver uuid=${this.uuid}`);
26008
26134
  (0, import_forge_room.removeDeepObserver)(this.root, this.handlePropChange);
26009
26135
  }
26010
26136
  };
@@ -26077,49 +26203,50 @@ function _toPrimitive3(t, r) {
26077
26203
  return ("string" === r ? String : Number)(t);
26078
26204
  }
26079
26205
  var CurveModel = class extends ElementModel {
26080
- constructor(root, scope, liveCursor) {
26081
- super(root, scope, liveCursor);
26206
+ constructor(root, scope, liveCursor, isPerformanceMode) {
26207
+ super(root, scope, liveCursor, isPerformanceMode);
26082
26208
  _defineProperty3(this, "item", null);
26083
- _defineProperty3(this, "debugPath", void 0);
26084
26209
  _defineProperty3(this, "debug", false);
26085
- if (!this.root.has("type")) {
26210
+ _defineProperty3(this, "clearLocalPointsWhenYPointsChange", false);
26211
+ _defineProperty3(this, "shouldUseLocalPoints", true);
26212
+ _defineProperty3(this, "localPointsPick", 4);
26213
+ if (!this.root.doc || !this.root.has("type")) {
26086
26214
  this.root.set("type", "curve");
26087
26215
  }
26088
- if (!this.root.has("points")) {
26216
+ if (!this.root.doc || !this.root.has("points")) {
26089
26217
  this.root.set("points", new Y2.Array());
26090
26218
  }
26091
- this.debugPath = new scope.Path();
26092
26219
  }
26093
26220
  average(a2, b2) {
26094
26221
  return (a2 + b2) / 2;
26095
26222
  }
26096
26223
  parsePoints(points) {
26224
+ const viewScale = this.scope.project.view.matrix.scaling.x || 1;
26225
+ const taper = this.strokeWidth * 5 / viewScale;
26226
+ const streamline = Math.min(0.7, 0.7 * viewScale);
26097
26227
  return ae(points, {
26098
26228
  size: this.strokeWidth,
26099
- smoothing: 0.5,
26100
- thinning: -0.5,
26101
- streamline: 0.5,
26229
+ smoothing: 0.7,
26230
+ thinning: 0.5,
26231
+ streamline,
26102
26232
  simulatePressure: true,
26103
26233
  start: {
26104
- taper: this.strokeWidth * 10,
26234
+ taper,
26105
26235
  cap: true
26106
26236
  },
26107
26237
  end: {
26108
- taper: this.strokeWidth * 20,
26238
+ taper,
26109
26239
  cap: true
26110
26240
  }
26111
26241
  });
26112
26242
  }
26113
26243
  matrixedPoints() {
26114
- const points = this.points;
26244
+ const points = this.localPoints.length === 0 ? this.points : this.localPoints;
26115
26245
  const matrix = new this.scope.Matrix(this.pointsMatrix);
26116
- const output = [];
26117
- for (let i = 0, len = points.length; i < len; i += 2) {
26118
- const p = new this.scope.Point(points[i], points[i + 1]);
26119
- const tp = p.transform(matrix);
26120
- output.push([tp.x, tp.y]);
26121
- }
26122
- return output;
26246
+ return (0, import_lodash.chunk)(points, 2).filter((point) => point.length === 2).map((_ref) => {
26247
+ let [x, y] = _ref;
26248
+ return new this.scope.Point(x, y).transform(matrix);
26249
+ }).map((point) => [point.x, point.y]);
26123
26250
  }
26124
26251
  createPath(points) {
26125
26252
  const path = new this.scope.Path();
@@ -26146,34 +26273,30 @@ var CurveModel = class extends ElementModel {
26146
26273
  }
26147
26274
  return path;
26148
26275
  }
26149
- updateDebugPath() {
26150
- this.debugPath = new this.scope.Path();
26151
- const points = (0, import_lodash.chunk)(this.points, 2);
26152
- for (let i = 0, len = points.length; i < len; i++) {
26153
- const point = new this.scope.Point(points[i][0], points[i][1]);
26154
- if (i === 0) {
26155
- this.debugPath.moveTo(point);
26156
- } else {
26157
- this.debugPath.lineTo(point);
26158
- }
26159
- this.debugPath.strokeWidth = 1;
26160
- this.debugPath.strokeColor = new this.scope.Color(1, 0, 0, 1);
26161
- }
26162
- }
26163
26276
  onVectorUpdate() {
26164
26277
  if (!this.item) {
26165
26278
  return;
26166
26279
  }
26280
+ const matrixedPts = this.matrixedPoints();
26167
26281
  if (this.debug) {
26168
- this.debugPath.remove();
26169
- this.updateDebugPath();
26170
- }
26171
- const points = this.parsePoints(this.matrixedPoints());
26172
- const path = this.createPath(points);
26173
- this.item.removeSegments();
26174
- this.item.addSegments(path.segments);
26175
- if (this.debug) {
26176
- this.item.addChild(this.debugPath);
26282
+ const path = new this.scope.Path();
26283
+ for (let i = 0; i < matrixedPts.length; i++) {
26284
+ const p = new this.scope.Point(matrixedPts[i][0], matrixedPts[i][1]);
26285
+ if (i === 0) {
26286
+ path.moveTo(p);
26287
+ } else {
26288
+ path.lineTo(p);
26289
+ }
26290
+ }
26291
+ this.item.removeSegments();
26292
+ this.item.addSegments(path.segments);
26293
+ this.item.fillColor = null;
26294
+ this.item.strokeWidth = this.strokeWidth;
26295
+ } else {
26296
+ const points = this.parsePoints(matrixedPts);
26297
+ const path = this.createPath(points);
26298
+ this.item.removeSegments();
26299
+ this.item.addSegments(path.segments);
26177
26300
  }
26178
26301
  }
26179
26302
  createPaperItem() {
@@ -26196,11 +26319,12 @@ var CurveModel = class extends ElementModel {
26196
26319
  }
26197
26320
  liveCursorPoint() {
26198
26321
  const yArray = this.root.get(ElementModel.KEYS.points);
26199
- if (yArray.length < 2) {
26322
+ const points = yArray.toArray();
26323
+ if (points.length < 2) {
26200
26324
  return null;
26201
26325
  }
26202
- const len = yArray.length;
26203
- const point = new this.scope.Point(yArray.get(len - 2), yArray.get(len - 1));
26326
+ const len = points.length;
26327
+ const point = new this.scope.Point(points[len - 2], points[len - 1]);
26204
26328
  return point.transform(new this.scope.Matrix(this.pointsMatrix));
26205
26329
  }
26206
26330
  onStyleKeyUpdate(key) {
@@ -26238,15 +26362,24 @@ function _toPrimitive4(t, r) {
26238
26362
  return ("string" === r ? String : Number)(t);
26239
26363
  }
26240
26364
  var SelectorModel = class extends ElementModel {
26241
- constructor(root, scope, liveCursor) {
26242
- super(root, scope, liveCursor);
26365
+ get drawPoints() {
26366
+ if (this.localPoints.length >= 4) {
26367
+ return this.localPoints;
26368
+ }
26369
+ return this.points;
26370
+ }
26371
+ constructor(root, scope, liveCursor, isPerformanceMode) {
26372
+ super(root, scope, liveCursor, isPerformanceMode);
26243
26373
  _defineProperty4(this, "item", null);
26244
- if (!this.root.has("type")) {
26374
+ _defineProperty4(this, "clearLocalPointsWhenYPointsChange", true);
26375
+ _defineProperty4(this, "shouldUseLocalPoints", true);
26376
+ _defineProperty4(this, "localPointsPick", 4);
26377
+ if (this.root.doc && !this.root.has("type")) {
26245
26378
  this.root.set("type", "selector");
26246
26379
  }
26247
- if (!this.root.has("points")) {
26380
+ if (this.root.doc && !this.root.has("points")) {
26248
26381
  const initPoints = new Y3.Array();
26249
- initPoints.push([0, 0, 0, 0, 0]);
26382
+ initPoints.push([0, 0, 0, 0]);
26250
26383
  this.root.set("points", initPoints);
26251
26384
  }
26252
26385
  }
@@ -26257,8 +26390,8 @@ var SelectorModel = class extends ElementModel {
26257
26390
  }
26258
26391
  createPaperRect() {
26259
26392
  const scope = this.scope;
26260
- const bounds = new scope.Rectangle(new scope.Point(this.points[0], this.points[1]), new scope.Size(this.points[2], this.points[3]));
26261
- return new scope.Path.Rectangle(bounds, new scope.Point(this.points[4], this.points[4]));
26393
+ const bounds = new scope.Rectangle(new scope.Point(this.drawPoints[0], this.drawPoints[1]), new scope.Size(this.drawPoints[2], this.drawPoints[3]));
26394
+ return new scope.Path.Rectangle(bounds);
26262
26395
  }
26263
26396
  onVectorUpdate() {
26264
26397
  if (!this.item) {
@@ -26293,6 +26426,7 @@ var Y4 = __toESM(require("yjs"), 1);
26293
26426
 
26294
26427
  // src/utils/paperjs.ts
26295
26428
  var import_lodash2 = __toESM(require_lodash(), 1);
26429
+ var import_forge_room2 = require("@netless/forge-room");
26296
26430
  function _defineProperty5(e, r, t) {
26297
26431
  return (r = _toPropertyKey5(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: true, configurable: true, writable: true }) : e[r] = t, e;
26298
26432
  }
@@ -26335,7 +26469,27 @@ var AnimationFrame = class {
26335
26469
  _defineProperty5(this, "callbacks", []);
26336
26470
  _defineProperty5(this, "lastTime", 0);
26337
26471
  _defineProperty5(this, "fps", 45);
26472
+ _defineProperty5(this, "lastCallbackTime", 0);
26473
+ _defineProperty5(this, "fpsBuffer", []);
26474
+ _defineProperty5(this, "FPS_REPORT_INTERVAL", 2700);
26338
26475
  _defineProperty5(this, "handleCallbacks", () => {
26476
+ const now = performance.now();
26477
+ if (this.lastCallbackTime > 0) {
26478
+ const actualFps = 1e3 / (now - this.lastCallbackTime);
26479
+ this.fpsBuffer.push(actualFps);
26480
+ if (this.fpsBuffer.length >= this.FPS_REPORT_INTERVAL) {
26481
+ const avg = this.fpsBuffer.reduce((a2, b2) => a2 + b2, 0) / this.fpsBuffer.length;
26482
+ const min = Math.min(...this.fpsBuffer);
26483
+ const sorted = [...this.fpsBuffer].sort((a2, b2) => a2 - b2);
26484
+ const p90 = sorted[Math.floor(sorted.length * 0.9)];
26485
+ (0, import_forge_room2.metrics)().gauge("fps", Math.round(avg), {
26486
+ min: Math.round(min),
26487
+ p90: Math.round(p90)
26488
+ });
26489
+ this.fpsBuffer = [];
26490
+ }
26491
+ }
26492
+ this.lastCallbackTime = now;
26339
26493
  const functions = this.callbacks;
26340
26494
  this.callbacks = [];
26341
26495
  for (let i = 0, l2 = functions.length; i < l2; i++) {
@@ -26379,13 +26533,22 @@ function _toPrimitive6(t, r) {
26379
26533
  return ("string" === r ? String : Number)(t);
26380
26534
  }
26381
26535
  var SegmentsModel = class extends ElementModel {
26382
- constructor(root, scope, type, liveCursor) {
26383
- super(root, scope, liveCursor);
26536
+ get drawPoints() {
26537
+ if (this.localPoints.length >= 4) {
26538
+ return this.localPoints;
26539
+ }
26540
+ return this.points;
26541
+ }
26542
+ constructor(root, scope, type, liveCursor, isPerformanceMode) {
26543
+ super(root, scope, liveCursor, isPerformanceMode);
26384
26544
  _defineProperty6(this, "item", null);
26385
- if (!this.root.has("type")) {
26545
+ _defineProperty6(this, "clearLocalPointsWhenYPointsChange", true);
26546
+ _defineProperty6(this, "shouldUseLocalPoints", true);
26547
+ _defineProperty6(this, "localPointsPick", 24);
26548
+ if (this.root.doc && !this.root.has("type")) {
26386
26549
  this.root.set("type", type);
26387
26550
  }
26388
- if (!this.root.has("points")) {
26551
+ if (this.root.doc && !this.root.has("points")) {
26389
26552
  this.root.set("points", new Y4.Array());
26390
26553
  }
26391
26554
  }
@@ -26405,13 +26568,13 @@ var SegmentsModel = class extends ElementModel {
26405
26568
  }
26406
26569
  const matrix = new this.scope.Matrix(this.pointsMatrix);
26407
26570
  this.item.removeSegments();
26408
- const next = deserializePath(this.points, this.scope, matrix);
26571
+ const next = deserializePath(this.drawPoints, this.scope, matrix);
26409
26572
  this.item.addSegments(next.segments);
26410
26573
  this.item.closePath();
26411
26574
  }
26412
26575
  createPaperItem() {
26413
26576
  const matrix = new this.scope.Matrix(this.pointsMatrix);
26414
- this.item = deserializePath(this.points, this.scope, matrix);
26577
+ this.item = deserializePath(this.drawPoints, this.scope, matrix);
26415
26578
  this.item.strokeColor = new this.scope.Color(this.strokeColor);
26416
26579
  this.item.dashArray = this.dashArray;
26417
26580
  this.item.strokeWidth = this.strokeWidth;
@@ -26459,6 +26622,8 @@ function _toPrimitive7(t, r) {
26459
26622
  }
26460
26623
  return ("string" === r ? String : Number)(t);
26461
26624
  }
26625
+ var DRAG_FPS = 10;
26626
+ var DRAG_FRAME_MS = 1e3 / DRAG_FPS;
26462
26627
  var WhiteboardTool = class {
26463
26628
  constructor(enableToolEvent, modelGetter, shadowEmitter, scope) {
26464
26629
  _defineProperty7(this, "modelGetter", void 0);
@@ -26467,24 +26632,60 @@ var WhiteboardTool = class {
26467
26632
  _defineProperty7(this, "shadowEmitter", void 0);
26468
26633
  _defineProperty7(this, "enableToolEvent", void 0);
26469
26634
  _defineProperty7(this, "eventAvailable", false);
26635
+ _defineProperty7(this, "lastDragTime", 0);
26636
+ _defineProperty7(this, "dragRafId", 0);
26637
+ _defineProperty7(this, "pendingDragEvent", null);
26470
26638
  _defineProperty7(this, "onMouseDownSelf", (event) => {
26471
26639
  this.eventAvailable = this.enableToolEvent();
26472
26640
  if (!this.eventAvailable) {
26473
26641
  return;
26474
26642
  }
26643
+ this.lastDragTime = 0;
26644
+ if (this.dragRafId) {
26645
+ cancelAnimationFrame(this.dragRafId);
26646
+ this.dragRafId = 0;
26647
+ }
26648
+ this.pendingDragEvent = null;
26475
26649
  this.shadowEmitter.setActive(true);
26476
26650
  this.onMouseDown(event);
26477
26651
  });
26652
+ _defineProperty7(this, "flushPendingDrag", () => {
26653
+ this.dragRafId = 0;
26654
+ if (this.pendingDragEvent) {
26655
+ this.lastDragTime = performance.now();
26656
+ const event = this.pendingDragEvent;
26657
+ this.pendingDragEvent = null;
26658
+ this.onMouseDrag(event);
26659
+ }
26660
+ });
26478
26661
  _defineProperty7(this, "onMouseDragSelf", (event) => {
26479
26662
  if (!this.eventAvailable) {
26480
26663
  return;
26481
26664
  }
26482
- this.onMouseDrag(event);
26665
+ const now = performance.now();
26666
+ if (now - this.lastDragTime >= DRAG_FRAME_MS) {
26667
+ this.lastDragTime = now;
26668
+ this.pendingDragEvent = null;
26669
+ this.onMouseDrag(event);
26670
+ } else {
26671
+ this.pendingDragEvent = event;
26672
+ if (!this.dragRafId) {
26673
+ this.dragRafId = requestAnimationFrame(this.flushPendingDrag);
26674
+ }
26675
+ }
26483
26676
  });
26484
26677
  _defineProperty7(this, "onMouseUpSelf", (event) => {
26485
26678
  if (!this.eventAvailable) {
26486
26679
  return;
26487
26680
  }
26681
+ if (this.dragRafId) {
26682
+ cancelAnimationFrame(this.dragRafId);
26683
+ this.dragRafId = 0;
26684
+ }
26685
+ if (this.pendingDragEvent) {
26686
+ this.onMouseDrag(this.pendingDragEvent);
26687
+ this.pendingDragEvent = null;
26688
+ }
26488
26689
  this.onMouseUp(event);
26489
26690
  this.shadowEmitter.setActive(false);
26490
26691
  });
@@ -26579,6 +26780,12 @@ function _toPrimitive9(t, r) {
26579
26780
  return ("string" === r ? String : Number)(t);
26580
26781
  }
26581
26782
  var LineModel = class extends ElementModel {
26783
+ get drawPoints() {
26784
+ if (this.localPoints.length > 0) {
26785
+ return this.localPoints;
26786
+ }
26787
+ return this.points;
26788
+ }
26582
26789
  get arrowSize() {
26583
26790
  return this.strokeWidth * 5 + 15;
26584
26791
  }
@@ -26594,20 +26801,23 @@ var LineModel = class extends ElementModel {
26594
26801
  set tailArrow(value) {
26595
26802
  this.root.set("tailArrow", value);
26596
26803
  }
26597
- constructor(root, scope, liveCursor) {
26598
- super(root, scope, liveCursor);
26804
+ constructor(root, scope, liveCursor, isPerformanceMode) {
26805
+ super(root, scope, liveCursor, isPerformanceMode);
26599
26806
  _defineProperty9(this, "controlledPoints", []);
26807
+ _defineProperty9(this, "clearLocalPointsWhenYPointsChange", true);
26808
+ _defineProperty9(this, "shouldUseLocalPoints", true);
26809
+ _defineProperty9(this, "localPointsPick", 99);
26600
26810
  _defineProperty9(this, "item", null);
26601
- if (!this.root.has("type")) {
26811
+ if (this.root.doc && !this.root.has("type")) {
26602
26812
  this.root.set("type", "arrow");
26603
26813
  }
26604
- if (!this.root.has("points")) {
26814
+ if (this.root.doc && !this.root.has("points")) {
26605
26815
  this.root.set("points", new Y5.Array());
26606
26816
  }
26607
- if (!this.root.has("headArrow")) {
26817
+ if (this.root.doc && !this.root.has("headArrow")) {
26608
26818
  this.root.set("headArrow", "none");
26609
26819
  }
26610
- if (!this.root.has("tailArrow")) {
26820
+ if (this.root.doc && !this.root.has("tailArrow")) {
26611
26821
  this.root.set("tailArrow", "normal");
26612
26822
  }
26613
26823
  }
@@ -26623,7 +26833,7 @@ var LineModel = class extends ElementModel {
26623
26833
  }
26624
26834
  renderLine() {
26625
26835
  const matrix = new this.scope.Matrix(this.pointsMatrix);
26626
- const papperPoints = (0, import_lodash4.chunk)(this.points, 2).map((item) => {
26836
+ const papperPoints = (0, import_lodash4.chunk)(this.drawPoints, 2).map((item) => {
26627
26837
  return new this.scope.Point(item[0], item[1]).transform(matrix);
26628
26838
  });
26629
26839
  const path = new this.scope.Path();
@@ -26737,13 +26947,14 @@ var LineControlPoint = class {
26737
26947
  if (this.position) {
26738
26948
  return this.model.scope.project.view.projectToView(this.position.transform(matrix));
26739
26949
  }
26950
+ const points = this.model["drawPoints"];
26740
26951
  const from = {
26741
- x: this.model.points[0],
26742
- y: this.model.points[1]
26952
+ x: points[0],
26953
+ y: points[1]
26743
26954
  };
26744
26955
  const to = {
26745
- x: this.model.points[this.model.points.length - 2],
26746
- y: this.model.points[this.model.points.length - 1]
26956
+ x: points[points.length - 2],
26957
+ y: points[points.length - 1]
26747
26958
  };
26748
26959
  const clonedPath = new this.scope.Path.Line(from, to);
26749
26960
  this.position = clonedPath.getPointAt(clonedPath.length * distance);
@@ -26756,7 +26967,7 @@ var LineControlPoint = class {
26756
26967
  }
26757
26968
  const pointsMatrix = new this.model.scope.Matrix(this.model.pointsMatrix);
26758
26969
  const invertedPoint = point.transform(pointsMatrix.inverted());
26759
- const points = this.model.points;
26970
+ const points = this.model["drawPoints"];
26760
26971
  this.position = invertedPoint;
26761
26972
  const clonedPoints = (0, import_lodash4.cloneDeep)(points);
26762
26973
  clonedPoints[this.options.index * 2] = invertedPoint.x;
@@ -26767,7 +26978,7 @@ var LineControlPoint = class {
26767
26978
 
26768
26979
  // src/model/renderable/PointTextModel.ts
26769
26980
  var Y6 = __toESM(require("yjs"), 1);
26770
- var import_forge_room2 = require("@netless/forge-room");
26981
+ var import_forge_room3 = require("@netless/forge-room");
26771
26982
  function _defineProperty10(e, r, t) {
26772
26983
  return (r = _toPropertyKey10(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: true, configurable: true, writable: true }) : e[r] = t, e;
26773
26984
  }
@@ -26804,9 +27015,18 @@ var PointTextModel = class extends ElementModel {
26804
27015
  set fontFamily(value) {
26805
27016
  this.root.set("font-family", value);
26806
27017
  }
26807
- constructor(root, scope, liveCursor) {
26808
- super(root, scope, liveCursor);
27018
+ get drawPoints() {
27019
+ if (this.localPoints.length > 1) {
27020
+ return this.localPoints;
27021
+ }
27022
+ return this.points;
27023
+ }
27024
+ constructor(root, scope, liveCursor, isPerformanceMode) {
27025
+ super(root, scope, liveCursor, isPerformanceMode);
26809
27026
  _defineProperty10(this, "item", null);
27027
+ _defineProperty10(this, "clearLocalPointsWhenYPointsChange", true);
27028
+ _defineProperty10(this, "shouldUseLocalPoints", false);
27029
+ _defineProperty10(this, "localPointsPick", 2);
26810
27030
  _defineProperty10(this, "handleTextPropChange", (event) => {
26811
27031
  if (!this.item) {
26812
27032
  return;
@@ -26823,21 +27043,27 @@ var PointTextModel = class extends ElementModel {
26823
27043
  }
26824
27044
  }
26825
27045
  });
26826
- if (!this.root.has("type")) {
27046
+ if (this.root.doc && !this.root.has("type")) {
26827
27047
  this.root.set("type", "point-text");
26828
27048
  }
26829
- if (!this.root.has(ElementModel.KEYS.points)) {
27049
+ if (this.root.doc && !this.root.has(ElementModel.KEYS.points)) {
26830
27050
  this.root.set(ElementModel.KEYS.points, new Y6.Array());
26831
27051
  }
26832
27052
  this.root.observe(this.handleTextPropChange);
26833
- if (this.root.has("font-size")) {
26834
- setTimeout(() => {
26835
- this.updateTextPosition();
26836
- }, 60);
26837
- }
27053
+ setTimeout(() => {
27054
+ if (this.root && this.root.has("font-size")) {
27055
+ setTimeout(() => {
27056
+ this.updateTextPosition();
27057
+ }, 60);
27058
+ }
27059
+ }, 60);
26838
27060
  }
26839
27061
  subDispose() {
26840
- (0, import_forge_room2.removeObserver)(this.root, this.handleTextPropChange);
27062
+ (0, import_forge_room3.removeObserver)(this.root, this.handleTextPropChange);
27063
+ }
27064
+ subBindObserver() {
27065
+ (0, import_forge_room3.removeObserver)(this.root, this.handleTextPropChange);
27066
+ this.root.observe(this.handleTextPropChange);
26841
27067
  }
26842
27068
  liveCursorPoint() {
26843
27069
  const points = this.points;
@@ -26852,10 +27078,11 @@ var PointTextModel = class extends ElementModel {
26852
27078
  if (!this.item) {
26853
27079
  return null;
26854
27080
  }
27081
+ console.log("[][][] drawPoints", this.drawPoints);
26855
27082
  const bounds = this.item.internalBounds;
26856
27083
  const matrix = new this.scope.Matrix(this.pointsMatrix);
26857
- const topLeft = new this.scope.Point(this.points[0], this.points[1]).transform(matrix);
26858
- const topRight = new this.scope.Point(this.points[0] + bounds.width, this.points[1]).transform(matrix);
27084
+ const topLeft = new this.scope.Point(this.drawPoints[0], this.drawPoints[1]).transform(matrix);
27085
+ const topRight = new this.scope.Point(this.drawPoints[0] + bounds.width, this.drawPoints[1]).transform(matrix);
26859
27086
  let scaleX = topRight.getDistance(topLeft) / bounds.width;
26860
27087
  scaleX = Number.isNaN(scaleX) ? 1 : scaleX;
26861
27088
  const angle = topRight.subtract(topLeft).angle;
@@ -26943,13 +27170,22 @@ function _toPrimitive11(t, r) {
26943
27170
  return ("string" === r ? String : Number)(t);
26944
27171
  }
26945
27172
  var TriangleModel = class extends ElementModel {
26946
- constructor(root, scope, liveCursor) {
26947
- super(root, scope, liveCursor);
27173
+ get drawPoints() {
27174
+ if (this.localPoints.length >= 6) {
27175
+ return this.localPoints;
27176
+ }
27177
+ return this.points;
27178
+ }
27179
+ constructor(root, scope, liveCursor, isPerformanceMode) {
27180
+ super(root, scope, liveCursor, isPerformanceMode);
26948
27181
  _defineProperty11(this, "item", null);
26949
- if (!this.root.has("type")) {
27182
+ _defineProperty11(this, "clearLocalPointsWhenYPointsChange", true);
27183
+ _defineProperty11(this, "shouldUseLocalPoints", true);
27184
+ _defineProperty11(this, "localPointsPick", 6);
27185
+ if (this.root.doc && !this.root.has("type")) {
26950
27186
  this.root.set("type", "triangle");
26951
27187
  }
26952
- if (!this.root.has("points")) {
27188
+ if (this.root.doc && !this.root.has("points")) {
26953
27189
  this.root.set("points", new Y7.Array());
26954
27190
  }
26955
27191
  }
@@ -26981,9 +27217,9 @@ var TriangleModel = class extends ElementModel {
26981
27217
  return;
26982
27218
  }
26983
27219
  const matrix = new this.scope.Matrix(this.pointsMatrix);
26984
- const p1 = new this.scope.Point(this.points[0], this.points[1]).transform(matrix);
26985
- const p2 = new this.scope.Point(this.points[2], this.points[3]).transform(matrix);
26986
- const p3 = new this.scope.Point(this.points[4], this.points[5]).transform(matrix);
27220
+ const p1 = new this.scope.Point(this.drawPoints[0], this.drawPoints[1]).transform(matrix);
27221
+ const p2 = new this.scope.Point(this.drawPoints[2], this.drawPoints[3]).transform(matrix);
27222
+ const p3 = new this.scope.Point(this.drawPoints[4], this.drawPoints[5]).transform(matrix);
26987
27223
  this.item.removeSegments();
26988
27224
  this.item.moveTo(p1);
26989
27225
  this.item.lineTo(p2);
@@ -26995,7 +27231,7 @@ var TriangleModel = class extends ElementModel {
26995
27231
  config.controlPoints.push({
26996
27232
  name: "triangle",
26997
27233
  getPosition: () => {
26998
- const point = new this.scope.Point(this.points[0], this.points[1]);
27234
+ const point = new this.scope.Point(this.drawPoints[0], this.drawPoints[1]);
26999
27235
  const pointsMatrix = new this.scope.Matrix(this.pointsMatrix);
27000
27236
  return this.scope.project.view.projectToView(point.transform(pointsMatrix));
27001
27237
  },
@@ -27005,7 +27241,7 @@ var TriangleModel = class extends ElementModel {
27005
27241
  }
27006
27242
  const pointsMatrix = new this.scope.Matrix(this.pointsMatrix);
27007
27243
  const trPoint = point.transform(pointsMatrix.inverted());
27008
- const oldPoints = this.points;
27244
+ const oldPoints = this.drawPoints;
27009
27245
  this.setPoints([trPoint.x, trPoint.y, oldPoints[2], oldPoints[3], oldPoints[4], oldPoints[5]]);
27010
27246
  }
27011
27247
  });
@@ -27044,25 +27280,34 @@ function _toPrimitive12(t, r) {
27044
27280
  return ("string" === r ? String : Number)(t);
27045
27281
  }
27046
27282
  var RectangleModel = class extends ElementModel {
27047
- constructor(root, scope, liveCursor) {
27048
- super(root, scope, liveCursor);
27283
+ get drawPoints() {
27284
+ if (this.localPoints.length >= 4) {
27285
+ return this.localPoints;
27286
+ }
27287
+ return this.points;
27288
+ }
27289
+ constructor(root, scope, liveCursor, isPerformanceMode) {
27290
+ super(root, scope, liveCursor, isPerformanceMode);
27049
27291
  _defineProperty12(this, "item", null);
27050
- if (!this.root.has("type")) {
27292
+ _defineProperty12(this, "clearLocalPointsWhenYPointsChange", true);
27293
+ _defineProperty12(this, "shouldUseLocalPoints", true);
27294
+ _defineProperty12(this, "localPointsPick", 4);
27295
+ if (this.root.doc && !this.root.has("type")) {
27051
27296
  this.root.set("type", "rectangle");
27052
27297
  }
27053
- if (!this.root.has("points")) {
27298
+ if (this.root.doc && !this.root.has("points")) {
27054
27299
  const initPoints = new Y8.Array();
27055
27300
  initPoints.push([0, 0, 0, 0]);
27056
27301
  this.root.set("points", initPoints);
27057
27302
  }
27058
- if (!this.root.has("radius")) {
27303
+ if (this.root.doc && !this.root.has("radius")) {
27059
27304
  this.root.set("radius", 0);
27060
27305
  }
27061
27306
  }
27062
27307
  subDispose() {
27063
27308
  }
27064
27309
  liveCursorPoint() {
27065
- const points = this.points;
27310
+ const points = this.drawPoints;
27066
27311
  if (points.length < 4) {
27067
27312
  return null;
27068
27313
  }
@@ -27070,7 +27315,7 @@ var RectangleModel = class extends ElementModel {
27070
27315
  return new this.scope.Point(points[2], points[3]).transform(matrix);
27071
27316
  }
27072
27317
  createSegments() {
27073
- const [a2, b2, c, d] = this.points;
27318
+ const [a2, b2, c, d] = this.drawPoints;
27074
27319
  const matrix = new this.scope.Matrix(this.pointsMatrix);
27075
27320
  const maxRadius = this.maxRadiusLength();
27076
27321
  const radius = this.root.get("radius") * maxRadius;
@@ -27135,7 +27380,7 @@ var RectangleModel = class extends ElementModel {
27135
27380
  }
27136
27381
  maxRadiusLength() {
27137
27382
  const pointsMatrix = new this.scope.Matrix(this.pointsMatrix);
27138
- const points = this.points;
27383
+ const points = this.drawPoints;
27139
27384
  const topLeft = new this.scope.Point(points[0], points[1]).transform(pointsMatrix);
27140
27385
  const topRight = new this.scope.Point(points[2], points[1]).transform(pointsMatrix);
27141
27386
  const bottomLeft = new this.scope.Point(points[0], points[3]).transform(pointsMatrix);
@@ -27160,7 +27405,7 @@ var RectangleModel = class extends ElementModel {
27160
27405
  name: "rect-radius",
27161
27406
  getPosition: () => {
27162
27407
  const matrix = new this.scope.Matrix(this.pointsMatrix);
27163
- const points = this.points;
27408
+ const points = this.drawPoints;
27164
27409
  const radius = this.root.get("radius") * this.maxRadiusLength();
27165
27410
  let c1 = new this.scope.Point(points[0], points[1]).transform(matrix);
27166
27411
  const c3 = new this.scope.Point(points[2], points[3]).transform(matrix);
@@ -27179,7 +27424,7 @@ var RectangleModel = class extends ElementModel {
27179
27424
  if (!this.item) {
27180
27425
  return;
27181
27426
  }
27182
- const points = this.points;
27427
+ const points = this.drawPoints;
27183
27428
  const pointsMatrix = new this.scope.Matrix(this.pointsMatrix);
27184
27429
  const maxRadius = Math.min(points[2] - points[0], points[3] - points[1]) / 2;
27185
27430
  const trPoint = point.transform(pointsMatrix.inverted());
@@ -27228,14 +27473,23 @@ function _toPrimitive13(t, r) {
27228
27473
  return ("string" === r ? String : Number)(t);
27229
27474
  }
27230
27475
  var EraserModel = class extends ElementModel {
27231
- constructor(root, scope, liveCursor) {
27232
- super(root, scope, liveCursor);
27476
+ get drawPoints() {
27477
+ if (this.localPoints.length > 0) {
27478
+ return this.localPoints;
27479
+ }
27480
+ return this.points;
27481
+ }
27482
+ constructor(root, scope, liveCursor, isPerformanceMode) {
27483
+ super(root, scope, liveCursor, isPerformanceMode);
27233
27484
  _defineProperty13(this, "item", null);
27234
27485
  _defineProperty13(this, "sliceBegin", 0);
27235
- if (!this.root.has("type")) {
27486
+ _defineProperty13(this, "clearLocalPointsWhenYPointsChange", false);
27487
+ _defineProperty13(this, "shouldUseLocalPoints", true);
27488
+ _defineProperty13(this, "localPointsPick", 4);
27489
+ if (this.root.doc && !this.root.has("type")) {
27236
27490
  this.root.set("type", "eraser");
27237
27491
  }
27238
- if (!this.root.has("points")) {
27492
+ if (this.root.doc && !this.root.has("points")) {
27239
27493
  this.root.set("points", new Y9.Array());
27240
27494
  }
27241
27495
  }
@@ -27286,7 +27540,7 @@ var EraserModel = class extends ElementModel {
27286
27540
  });
27287
27541
  }
27288
27542
  matrixedPoints() {
27289
- const currentPoints = (0, import_lodash5.chunk)(this.points, 2).slice(this.sliceBegin);
27543
+ const currentPoints = (0, import_lodash5.chunk)(this.drawPoints, 2).slice(this.sliceBegin);
27290
27544
  return currentPoints.map((_ref) => {
27291
27545
  let [x, y] = _ref;
27292
27546
  return new this.scope.Point(x, y);
@@ -27314,11 +27568,11 @@ var EraserModel = class extends ElementModel {
27314
27568
  this.item.fillColor = new this.scope.Color(this.strokeColor);
27315
27569
  this.onVectorUpdate();
27316
27570
  this.item.onFrame = () => {
27317
- if (!this.points) {
27571
+ if (!this.drawPoints) {
27318
27572
  return;
27319
27573
  }
27320
- if (this.points.length / 2 > 50) {
27321
- this.sliceBegin = this.points.length / 2 - 50;
27574
+ if (this.drawPoints.length / 2 > 50) {
27575
+ this.sliceBegin = this.drawPoints.length / 2 - 50;
27322
27576
  }
27323
27577
  };
27324
27578
  }
@@ -27353,6 +27607,7 @@ var EraserModel = class extends ElementModel {
27353
27607
  // src/model/renderable/LaserPointerModel.ts
27354
27608
  var Y10 = __toESM(require("yjs"), 1);
27355
27609
  var import_lodash6 = __toESM(require_lodash(), 1);
27610
+ var import_forge_room4 = require("@netless/forge-room");
27356
27611
  function _defineProperty14(e, r, t) {
27357
27612
  return (r = _toPropertyKey14(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: true, configurable: true, writable: true }) : e[r] = t, e;
27358
27613
  }
@@ -27371,24 +27626,18 @@ function _toPrimitive14(t, r) {
27371
27626
  return ("string" === r ? String : Number)(t);
27372
27627
  }
27373
27628
  var LaserPointerModel = class extends ElementModel {
27374
- constructor(clientId, root, scope, liveCursor, removeElement) {
27375
- super(root, scope, liveCursor);
27629
+ constructor(clientId, root, scope, liveCursor, removeElement, isPerformanceMode) {
27630
+ super(root, scope, liveCursor, isPerformanceMode);
27376
27631
  _defineProperty14(this, "item", null);
27377
27632
  _defineProperty14(this, "clientId", void 0);
27378
27633
  _defineProperty14(this, "sliceBegin", 0);
27379
27634
  _defineProperty14(this, "displayStrokeWidth", 8);
27380
27635
  _defineProperty14(this, "cachedPoints", null);
27381
- this.clientId = clientId;
27382
- if (!this.root.has("type")) {
27383
- this.root.set("type", "laser");
27384
- }
27385
- if (!this.root.has("points")) {
27386
- this.root.set("points", new Y10.Array());
27387
- }
27388
- if (!this.root.has("removed")) {
27389
- this.root.set("removed", false);
27390
- }
27391
- this.root.observe((event) => {
27636
+ _defineProperty14(this, "clearLocalPointsWhenYPointsChange", false);
27637
+ _defineProperty14(this, "shouldUseLocalPoints", false);
27638
+ _defineProperty14(this, "localPointsPick", 4);
27639
+ _defineProperty14(this, "removeElement", void 0);
27640
+ _defineProperty14(this, "handleLaserPropChange", (event) => {
27392
27641
  if (!this.item) {
27393
27642
  return;
27394
27643
  }
@@ -27406,13 +27655,31 @@ var LaserPointerModel = class extends ElementModel {
27406
27655
  this.onVectorUpdate();
27407
27656
  if (evt.count >= 30) {
27408
27657
  if (this.ownerId === this.clientId) {
27409
- removeElement(this.uuid);
27658
+ this.removeElement(this.uuid);
27410
27659
  }
27411
27660
  }
27412
27661
  };
27413
27662
  }
27414
27663
  }
27415
27664
  });
27665
+ this.clientId = clientId;
27666
+ this.removeElement = removeElement;
27667
+ if (this.root.doc && !this.root.has("type")) {
27668
+ this.root.set("type", "laser");
27669
+ }
27670
+ if (this.root.doc && !this.root.has("points")) {
27671
+ this.root.set("points", new Y10.Array());
27672
+ }
27673
+ if (this.root.doc && !this.root.has("removed")) {
27674
+ this.root.set("removed", false);
27675
+ }
27676
+ }
27677
+ subBindObserver() {
27678
+ (0, import_forge_room4.removeObserver)(this.root, this.handleLaserPropChange);
27679
+ this.root.observe(this.handleLaserPropChange);
27680
+ }
27681
+ subDispose() {
27682
+ (0, import_forge_room4.removeObserver)(this.root, this.handleLaserPropChange);
27416
27683
  }
27417
27684
  beginRemoveAnimate() {
27418
27685
  this.root.set("removed", true);
@@ -27465,6 +27732,7 @@ var LaserPointerModel = class extends ElementModel {
27465
27732
  matrixedPoints() {
27466
27733
  const matrix = new this.scope.Matrix(this.pointsMatrix);
27467
27734
  const points = this.cachedPoints || this.points;
27735
+ console.log("[][][] ,", this.points.length, this.cachedPoints?.length, this.localPoints.length);
27468
27736
  const groupPoints = (0, import_lodash6.chunk)(points, 2).slice(this.sliceBegin);
27469
27737
  return groupPoints.map((_ref) => {
27470
27738
  let [x, y] = _ref;
@@ -27507,8 +27775,6 @@ var LaserPointerModel = class extends ElementModel {
27507
27775
  onStyleKeyUpdate(_key) {
27508
27776
  return;
27509
27777
  }
27510
- subDispose() {
27511
- }
27512
27778
  liveCursorPoint() {
27513
27779
  const yArray = this.root.get(ElementModel.KEYS.points);
27514
27780
  if (yArray.length < 2) {
@@ -27521,7 +27787,7 @@ var LaserPointerModel = class extends ElementModel {
27521
27787
  };
27522
27788
 
27523
27789
  // src/WhitePermissions.ts
27524
- var import_forge_room3 = require("@netless/forge-room");
27790
+ var import_forge_room5 = require("@netless/forge-room");
27525
27791
  var WhiteboardPermissionFlag = function(WhiteboardPermissionFlag2) {
27526
27792
  WhiteboardPermissionFlag2[WhiteboardPermissionFlag2["none"] = 0] = "none";
27527
27793
  WhiteboardPermissionFlag2[WhiteboardPermissionFlag2["draw"] = 1] = "draw";
@@ -27534,7 +27800,7 @@ var WhiteboardPermissionFlag = function(WhiteboardPermissionFlag2) {
27534
27800
  WhiteboardPermissionFlag2[WhiteboardPermissionFlag2["all"] = WhiteboardPermissionFlag2.draw | WhiteboardPermissionFlag2.editSelf | WhiteboardPermissionFlag2.editOthers | WhiteboardPermissionFlag2.deleteSelf | WhiteboardPermissionFlag2.deleteOthers | WhiteboardPermissionFlag2.mainView | WhiteboardPermissionFlag2.setOthersView] = "all";
27535
27801
  return WhiteboardPermissionFlag2;
27536
27802
  }({});
27537
- var WhiteboardPermissions = class extends import_forge_room3.AbstractApplicationPermissions {
27803
+ var WhiteboardPermissions = class extends import_forge_room5.AbstractApplicationPermissions {
27538
27804
  /**
27539
27805
  * 解析权限列表组合
27540
27806
  * @param {number} value - 权限数字值
@@ -27566,13 +27832,22 @@ function _toPrimitive15(t, r) {
27566
27832
  return ("string" === r ? String : Number)(t);
27567
27833
  }
27568
27834
  var StraightLineModel = class extends ElementModel {
27569
- constructor(root, scope, liveCursor) {
27570
- super(root, scope, liveCursor);
27835
+ get drawPoints() {
27836
+ if (this.localPoints.length >= 4) {
27837
+ return this.localPoints;
27838
+ }
27839
+ return this.points;
27840
+ }
27841
+ constructor(root, scope, liveCursor, isPerformanceMode) {
27842
+ super(root, scope, liveCursor, isPerformanceMode);
27571
27843
  _defineProperty15(this, "item", null);
27572
- if (!this.root.has("type")) {
27844
+ _defineProperty15(this, "clearLocalPointsWhenYPointsChange", true);
27845
+ _defineProperty15(this, "shouldUseLocalPoints", true);
27846
+ _defineProperty15(this, "localPointsPick", 4);
27847
+ if (this.root.doc && !this.root.has("type")) {
27573
27848
  this.root.set("type", "line");
27574
27849
  }
27575
- if (!this.root.has("points")) {
27850
+ if (this.root.doc && !this.root.has("points")) {
27576
27851
  this.root.set("points", new Y11.Array());
27577
27852
  }
27578
27853
  }
@@ -27597,7 +27872,7 @@ var StraightLineModel = class extends ElementModel {
27597
27872
  }
27598
27873
  renderLine() {
27599
27874
  const matrix = new this.scope.Matrix(this.pointsMatrix);
27600
- const papperPoints = (0, import_lodash7.chunk)(this.points, 2).map((item) => {
27875
+ const papperPoints = (0, import_lodash7.chunk)(this.drawPoints, 2).map((item) => {
27601
27876
  return new this.scope.Point(item[0], item[1]).transform(matrix);
27602
27877
  });
27603
27878
  const path = new this.scope.Path();
@@ -27619,7 +27894,7 @@ var StraightLineModel = class extends ElementModel {
27619
27894
  name: "line-start",
27620
27895
  getPosition: () => {
27621
27896
  const matrix = new this.scope.Matrix(this.pointsMatrix);
27622
- const points = this.points;
27897
+ const points = this.drawPoints;
27623
27898
  const start = new this.scope.Point(points[0], points[1]);
27624
27899
  return this.scope.project.view.projectToView(start.transform(matrix));
27625
27900
  },
@@ -27629,14 +27904,15 @@ var StraightLineModel = class extends ElementModel {
27629
27904
  }
27630
27905
  const pointsMatrix = new this.scope.Matrix(this.pointsMatrix);
27631
27906
  const trPoint = point.transform(pointsMatrix.inverted());
27632
- this.setPoints([trPoint.x, trPoint.y, this.points[2], this.points[3]]);
27907
+ const oldPoints = this.drawPoints;
27908
+ this.setPoints([trPoint.x, trPoint.y, oldPoints[2], oldPoints[3]]);
27633
27909
  }
27634
27910
  });
27635
27911
  cfg.controlPoints.push({
27636
27912
  name: "line-end",
27637
27913
  getPosition: () => {
27638
27914
  const matrix = new this.scope.Matrix(this.pointsMatrix);
27639
- const points = this.points;
27915
+ const points = this.drawPoints;
27640
27916
  const end = new this.scope.Point(points[2], points[3]);
27641
27917
  return this.scope.project.view.projectToView(end.transform(matrix));
27642
27918
  },
@@ -27646,7 +27922,8 @@ var StraightLineModel = class extends ElementModel {
27646
27922
  }
27647
27923
  const pointsMatrix = new this.scope.Matrix(this.pointsMatrix);
27648
27924
  const trPoint = point.transform(pointsMatrix.inverted());
27649
- this.setPoints([this.points[0], this.points[1], trPoint.x, trPoint.y]);
27925
+ const oldPoints = this.drawPoints;
27926
+ this.setPoints([oldPoints[0], oldPoints[1], trPoint.x, trPoint.y]);
27650
27927
  }
27651
27928
  });
27652
27929
  return cfg;
@@ -27692,10 +27969,13 @@ var ImageModel = class extends ElementModel {
27692
27969
  get src() {
27693
27970
  return this.root.get("src");
27694
27971
  }
27695
- constructor(root, scope, imageSets, liveCursor) {
27696
- super(root, scope, liveCursor);
27972
+ constructor(root, scope, imageSets, liveCursor, isPerformanceMode) {
27973
+ super(root, scope, liveCursor, isPerformanceMode);
27697
27974
  _defineProperty16(this, "item", null);
27698
27975
  _defineProperty16(this, "imageSets", void 0);
27976
+ _defineProperty16(this, "clearLocalPointsWhenYPointsChange", true);
27977
+ _defineProperty16(this, "shouldUseLocalPoints", true);
27978
+ _defineProperty16(this, "localPointsPick", 4);
27699
27979
  this.imageSets = imageSets;
27700
27980
  if (!this.root.has("type")) {
27701
27981
  this.root.set("type", "image");
@@ -27714,6 +27994,7 @@ var ImageModel = class extends ElementModel {
27714
27994
  }
27715
27995
  if (!this.imageSets.querySelector(`[id='${this.uuid}']`)) {
27716
27996
  const img = document.createElement("img");
27997
+ img.crossOrigin = "anonymous";
27717
27998
  img.src = this.src;
27718
27999
  img.id = this.uuid;
27719
28000
  this.imageSets.appendChild(img);
@@ -27778,7 +28059,7 @@ var RenderableModel = class extends import_eventemitter3.default {
27778
28059
  get uuid() {
27779
28060
  return (0, import_uuid.v4)().replace(/-/g, "");
27780
28061
  }
27781
- constructor(layerId, shadowEmitter, elements, scope, toolbarModel, userManager, imageSets, liveCursor, hasPermission) {
28062
+ constructor(options) {
27782
28063
  super();
27783
28064
  _defineProperty17(this, "scope", void 0);
27784
28065
  _defineProperty17(this, "toolbarModel", void 0);
@@ -27791,6 +28072,7 @@ var RenderableModel = class extends import_eventemitter3.default {
27791
28072
  _defineProperty17(this, "shadowEmitter", void 0);
27792
28073
  _defineProperty17(this, "imageSets", void 0);
27793
28074
  _defineProperty17(this, "liveCursor", void 0);
28075
+ _defineProperty17(this, "isPerformanceMode", void 0);
27794
28076
  _defineProperty17(this, "onElementsChange", (event) => {
27795
28077
  for (const [key, value] of event.changes.keys.entries()) {
27796
28078
  if (value.action === "add") {
@@ -27809,15 +28091,16 @@ var RenderableModel = class extends import_eventemitter3.default {
27809
28091
  }
27810
28092
  }
27811
28093
  });
27812
- this.liveCursor = liveCursor;
27813
- this.imageSets = imageSets;
27814
- this.hasPermission = hasPermission;
27815
- this.shadowEmitter = shadowEmitter;
27816
- this.layerId = layerId;
27817
- this.userManager = userManager;
27818
- this.elements = elements;
27819
- this.scope = scope;
27820
- this.toolbarModel = toolbarModel;
28094
+ this.isPerformanceMode = options.isPerformanceMode;
28095
+ this.liveCursor = options.liveCursor;
28096
+ this.imageSets = options.imageSets;
28097
+ this.hasPermission = options.hasPermission;
28098
+ this.shadowEmitter = options.shadowEmitter;
28099
+ this.layerId = options.layerId;
28100
+ this.userManager = options.userManager;
28101
+ this.elements = options.elements;
28102
+ this.scope = options.scope;
28103
+ this.toolbarModel = options.toolbarModel;
27821
28104
  this.elementModels = /* @__PURE__ */ new Map();
27822
28105
  for (const key of this.elements.keys()) {
27823
28106
  const type = this.elements.get(key)?.get("type");
@@ -27848,33 +28131,43 @@ var RenderableModel = class extends import_eventemitter3.default {
27848
28131
  convertToModel(yMap) {
27849
28132
  const type = yMap.get("type");
27850
28133
  let model = null;
28134
+ const uuid = yMap.get(ElementModel.KEYS.uuid);
28135
+ if (uuid) {
28136
+ const existingModel = this.elementModels.get(uuid);
28137
+ if (existingModel) {
28138
+ existingModel.shadowEmitter = this.shadowEmitter;
28139
+ existingModel.bindObserver();
28140
+ return existingModel;
28141
+ }
28142
+ }
27851
28143
  if (type === "curve") {
27852
- model = new CurveModel(yMap, this.scope, this.liveCursor);
28144
+ model = new CurveModel(yMap, this.scope, this.liveCursor, this.isPerformanceMode);
27853
28145
  } else if (["ellipse"].indexOf(type) >= 0) {
27854
- model = new SegmentsModel(yMap, this.scope, type, this.liveCursor);
28146
+ model = new SegmentsModel(yMap, this.scope, type, this.liveCursor, this.isPerformanceMode);
27855
28147
  } else if (type === "selector") {
27856
- model = new SelectorModel(yMap, this.scope, this.liveCursor);
28148
+ model = new SelectorModel(yMap, this.scope, this.liveCursor, this.isPerformanceMode);
27857
28149
  } else if (type === "arrow") {
27858
- model = new LineModel(yMap, this.scope, this.liveCursor);
28150
+ model = new LineModel(yMap, this.scope, this.liveCursor, this.isPerformanceMode);
27859
28151
  } else if (type === "line") {
27860
- model = new StraightLineModel(yMap, this.scope, this.liveCursor);
28152
+ model = new StraightLineModel(yMap, this.scope, this.liveCursor, this.isPerformanceMode);
27861
28153
  } else if (type === "point-text") {
27862
- model = new PointTextModel(yMap, this.scope, this.liveCursor);
28154
+ model = new PointTextModel(yMap, this.scope, this.liveCursor, this.isPerformanceMode);
27863
28155
  } else if (type === "triangle") {
27864
- model = new TriangleModel(yMap, this.scope, this.liveCursor);
28156
+ model = new TriangleModel(yMap, this.scope, this.liveCursor, this.isPerformanceMode);
27865
28157
  } else if (type === "rectangle") {
27866
- model = new RectangleModel(yMap, this.scope, this.liveCursor);
28158
+ model = new RectangleModel(yMap, this.scope, this.liveCursor, this.isPerformanceMode);
27867
28159
  } else if (type === "eraser") {
27868
- model = new EraserModel(yMap, this.scope, this.liveCursor);
28160
+ model = new EraserModel(yMap, this.scope, this.liveCursor, this.isPerformanceMode);
27869
28161
  } else if (type === "laser") {
27870
- model = new LaserPointerModel(this.userManager.selfId, yMap, this.scope, this.liveCursor, (uuid) => {
27871
- this.removeElementItem(uuid);
27872
- });
28162
+ model = new LaserPointerModel(this.userManager.selfId, yMap, this.scope, this.liveCursor, (uuid2) => {
28163
+ this.removeElementItem(uuid2);
28164
+ }, this.isPerformanceMode);
27873
28165
  } else if (type === "image") {
27874
- model = new ImageModel(yMap, this.scope, this.imageSets, this.liveCursor);
28166
+ model = new ImageModel(yMap, this.scope, this.imageSets, this.liveCursor, this.isPerformanceMode);
27875
28167
  }
27876
28168
  if (model) {
27877
28169
  model.shadowEmitter = this.shadowEmitter;
28170
+ model.bindObserver();
27878
28171
  this.elementModels.set(model.uuid, model);
27879
28172
  }
27880
28173
  return model;
@@ -27888,7 +28181,7 @@ var RenderableModel = class extends import_eventemitter3.default {
27888
28181
  confirmPermission() {
27889
28182
  const hasPermission = this.hasPermission(WhiteboardPermissionFlag.draw);
27890
28183
  if (!hasPermission) {
27891
- (0, import_forge_room4.log)("[@netless/forge-whiteboard] no permission to draw", {}, "warn");
28184
+ (0, import_forge_room6.log)("[@netless/forge-whiteboard] no permission to draw", {}, "warn");
27892
28185
  }
27893
28186
  return hasPermission;
27894
28187
  }
@@ -27905,16 +28198,58 @@ var RenderableModel = class extends import_eventemitter3.default {
27905
28198
  yMap.set(ElementModel.KEYS.ownerId, this.userManager.selfId);
27906
28199
  this.elements.set(uuid, yMap);
27907
28200
  }, elementsUndoOrigin);
27908
- const model = new ImageModel(yMap, this.scope, this.imageSets, this.liveCursor);
28201
+ const model = new ImageModel(yMap, this.scope, this.imageSets, this.liveCursor, this.isPerformanceMode);
28202
+ model.bindObserver();
27909
28203
  model.root.set("src", src);
27910
- const initMatrix = new this.scope.Matrix();
28204
+ model.ownerId = this.userManager.selfId;
28205
+ this.fitImageToViewport(src, model);
28206
+ }
28207
+ fitImageToViewport(src, model) {
27911
28208
  const center = this.scope.project.view.center;
27912
- initMatrix.translate({
28209
+ const fallbackMatrix = new this.scope.Matrix();
28210
+ fallbackMatrix.translate({
27913
28211
  x: center.x,
27914
28212
  y: center.y
27915
28213
  });
27916
- model.appendPointsMatrix(initMatrix);
27917
- model.ownerId = this.userManager.selfId;
28214
+ this.setElementPointsMatrix(model, fallbackMatrix);
28215
+ const img = document.createElement("img");
28216
+ img.crossOrigin = "anonymous";
28217
+ img.onload = () => {
28218
+ const naturalWidth = img.naturalWidth || img.width;
28219
+ const naturalHeight = img.naturalHeight || img.height;
28220
+ if (naturalWidth <= 0 || naturalHeight <= 0) {
28221
+ return;
28222
+ }
28223
+ const viewportBounds = this.scope.project.view.bounds;
28224
+ const maxWidth = viewportBounds.width * 2 / 3;
28225
+ const maxHeight = viewportBounds.height * 2 / 3;
28226
+ const fitScale = Math.min(maxWidth / naturalWidth, maxHeight / naturalHeight, 1);
28227
+ const nextMatrix = new this.scope.Matrix();
28228
+ nextMatrix.translate({
28229
+ x: center.x,
28230
+ y: center.y
28231
+ });
28232
+ if (fitScale > 0 && Number.isFinite(fitScale)) {
28233
+ nextMatrix.scale(fitScale);
28234
+ }
28235
+ this.setElementPointsMatrix(model, nextMatrix);
28236
+ };
28237
+ img.onerror = () => {
28238
+ (0, import_forge_room6.log)("[@netless/forge-whiteboard] failed to preload image for viewport fitting", {
28239
+ src
28240
+ }, "warn");
28241
+ };
28242
+ img.src = src;
28243
+ }
28244
+ setElementPointsMatrix(model, matrix) {
28245
+ const values = [matrix.a, matrix.b, matrix.c, matrix.d, matrix.tx, matrix.ty];
28246
+ if (model.root.doc) {
28247
+ model.root.doc.transact(() => {
28248
+ model.root.set(ElementModel.KEYS.pointsMatrix, values);
28249
+ }, elementsUndoOrigin);
28250
+ } else {
28251
+ model.root.set(ElementModel.KEYS.pointsMatrix, values);
28252
+ }
27918
28253
  }
27919
28254
  createCurve() {
27920
28255
  let shadow = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : false;
@@ -27922,8 +28257,10 @@ var RenderableModel = class extends import_eventemitter3.default {
27922
28257
  return null;
27923
28258
  }
27924
28259
  const yMap = new Y12.Map();
28260
+ const uuid = this.uuid;
28261
+ const curveModel = new CurveModel(yMap, this.scope, this.liveCursor, this.isPerformanceMode);
28262
+ this.elementModels.set(uuid, curveModel);
27925
28263
  this.elements.doc?.transact(() => {
27926
- const uuid = this.uuid;
27927
28264
  yMap.set(ElementModel.KEYS.index, ++this.maxIndex);
27928
28265
  yMap.set(ElementModel.KEYS.uuid, uuid);
27929
28266
  yMap.set("type", "curve");
@@ -27936,7 +28273,7 @@ var RenderableModel = class extends import_eventemitter3.default {
27936
28273
  yMap.set(ElementModel.KEYS.ownerId, this.userManager.selfId);
27937
28274
  this.elements.set(uuid, yMap);
27938
28275
  }, elementsUndoOrigin);
27939
- const curveModel = new CurveModel(yMap, this.scope, this.liveCursor);
28276
+ curveModel.bindObserver();
27940
28277
  this.initElement(curveModel);
27941
28278
  return curveModel;
27942
28279
  }
@@ -27945,11 +28282,17 @@ var RenderableModel = class extends import_eventemitter3.default {
27945
28282
  return null;
27946
28283
  }
27947
28284
  const yMap = new Y12.Map();
28285
+ const uuid = this.uuid;
28286
+ const model = new LaserPointerModel(this.userManager.selfId, yMap, this.scope, this.liveCursor, (uuid2) => {
28287
+ this.removeElementItem(uuid2);
28288
+ }, this.isPerformanceMode);
28289
+ this.elementModels.set(uuid, model);
27948
28290
  this.elements.doc?.transact(() => {
27949
- const uuid = this.uuid;
27950
28291
  yMap.set(ElementModel.KEYS.index, ++this.maxIndex);
27951
28292
  yMap.set(ElementModel.KEYS.uuid, uuid);
27952
28293
  yMap.set("type", "laser");
28294
+ yMap.set(ElementModel.KEYS.points, new Y12.Array());
28295
+ yMap.set("removed", false);
27953
28296
  yMap.set(ElementModel.KEYS.shadow, "layer");
27954
28297
  yMap.set(ElementModel.KEYS.strokeWidth, 8);
27955
28298
  yMap.set(ElementModel.KEYS.strokeColor, "#F44336");
@@ -27957,9 +28300,8 @@ var RenderableModel = class extends import_eventemitter3.default {
27957
28300
  yMap.set(ElementModel.KEYS.ownerId, this.userManager.selfId);
27958
28301
  this.elements.set(uuid, yMap);
27959
28302
  }, elementsUndoOrigin);
27960
- const model = new LaserPointerModel(this.userManager.selfId, yMap, this.scope, this.liveCursor, (uuid) => {
27961
- this.removeElementItem(uuid);
27962
- });
28303
+ model.bindObserver();
28304
+ this.initElement(model);
27963
28305
  return model;
27964
28306
  }
27965
28307
  createEraser() {
@@ -27967,11 +28309,14 @@ var RenderableModel = class extends import_eventemitter3.default {
27967
28309
  return null;
27968
28310
  }
27969
28311
  const yMap = new Y12.Map();
28312
+ const uuid = this.uuid;
28313
+ const model = new EraserModel(yMap, this.scope, this.liveCursor, this.isPerformanceMode);
28314
+ this.elementModels.set(uuid, model);
27970
28315
  this.elements.doc?.transact(() => {
27971
- const uuid = this.uuid;
27972
28316
  yMap.set(ElementModel.KEYS.index, ++this.maxIndex);
27973
28317
  yMap.set(ElementModel.KEYS.uuid, uuid);
27974
28318
  yMap.set("type", "eraser");
28319
+ yMap.set(ElementModel.KEYS.points, new Y12.Array());
27975
28320
  yMap.set(ElementModel.KEYS.shadow, "layer");
27976
28321
  yMap.set(ElementModel.KEYS.strokeWidth, 4);
27977
28322
  yMap.set(ElementModel.KEYS.strokeColor, "#9E9E9E");
@@ -27979,7 +28324,7 @@ var RenderableModel = class extends import_eventemitter3.default {
27979
28324
  yMap.set(ElementModel.KEYS.ownerId, this.userManager.selfId);
27980
28325
  this.elements.set(uuid, yMap);
27981
28326
  }, elementsUndoOrigin);
27982
- const model = new EraserModel(yMap, this.scope, this.liveCursor);
28327
+ model.bindObserver();
27983
28328
  return model;
27984
28329
  }
27985
28330
  createTriangle(shadow) {
@@ -27987,45 +28332,54 @@ var RenderableModel = class extends import_eventemitter3.default {
27987
28332
  return null;
27988
28333
  }
27989
28334
  const yMap = new Y12.Map();
28335
+ const uuid = this.uuid;
28336
+ const triangleModel = new TriangleModel(yMap, this.scope, this.liveCursor, this.isPerformanceMode);
28337
+ this.elementModels.set(uuid, triangleModel);
27990
28338
  this.elements.doc?.transact(() => {
27991
- const uuid = this.uuid;
27992
28339
  yMap.set(ElementModel.KEYS.index, ++this.maxIndex);
27993
28340
  yMap.set(ElementModel.KEYS.uuid, uuid);
27994
28341
  yMap.set("type", "triangle");
27995
28342
  if (shadow) {
27996
28343
  yMap.set(ElementModel.KEYS.shadow, "layer");
27997
28344
  }
28345
+ yMap.set("points", new Y12.Array());
27998
28346
  yMap.set(ElementModel.KEYS.strokeWidth, this.toolbarModel.strokeWidth);
27999
28347
  yMap.set(ElementModel.KEYS.strokeColor, this.toolbarModel.strokeColor);
28000
28348
  yMap.set(ElementModel.KEYS.fillColor, this.toolbarModel.fillColor);
28001
28349
  yMap.set(ElementModel.KEYS.ownerId, this.userManager.selfId);
28002
28350
  this.elements.set(uuid, yMap);
28003
28351
  }, elementsUndoOrigin);
28004
- const triangle = new TriangleModel(yMap, this.scope, this.liveCursor);
28005
- this.initElement(triangle);
28006
- triangle.dashArray = this.toolbarModel.dashArray;
28007
- return triangle;
28352
+ triangleModel.bindObserver();
28353
+ this.initElement(triangleModel);
28354
+ triangleModel.dashArray = this.toolbarModel.dashArray;
28355
+ return triangleModel;
28008
28356
  }
28009
28357
  createRectangle(shadow) {
28010
28358
  if (!this.confirmPermission()) {
28011
28359
  return null;
28012
28360
  }
28013
28361
  const yMap = new Y12.Map();
28362
+ const uuid = this.uuid;
28363
+ const rect = new RectangleModel(yMap, this.scope, this.liveCursor, this.isPerformanceMode);
28364
+ this.elementModels.set(uuid, rect);
28014
28365
  this.elements.doc?.transact(() => {
28015
- const uuid = this.uuid;
28016
28366
  yMap.set(ElementModel.KEYS.index, ++this.maxIndex);
28017
28367
  yMap.set(ElementModel.KEYS.uuid, uuid);
28018
28368
  yMap.set("type", "rectangle");
28019
28369
  if (shadow) {
28020
28370
  yMap.set(ElementModel.KEYS.shadow, "layer");
28021
28371
  }
28372
+ const initPoints = new Y12.Array();
28373
+ initPoints.push([0, 0, 0, 0]);
28374
+ yMap.set("points", initPoints);
28375
+ yMap.set("radius", 0);
28022
28376
  yMap.set(ElementModel.KEYS.strokeWidth, this.toolbarModel.strokeWidth);
28023
28377
  yMap.set(ElementModel.KEYS.strokeColor, this.toolbarModel.strokeColor);
28024
28378
  yMap.set(ElementModel.KEYS.fillColor, this.toolbarModel.fillColor);
28025
28379
  yMap.set(ElementModel.KEYS.ownerId, this.userManager.selfId);
28026
28380
  this.elements.set(uuid, yMap);
28027
28381
  }, elementsUndoOrigin);
28028
- const rect = new RectangleModel(yMap, this.scope, this.liveCursor);
28382
+ rect.bindObserver();
28029
28383
  this.initElement(rect);
28030
28384
  rect.dashArray = this.toolbarModel.dashArray;
28031
28385
  return rect;
@@ -28035,21 +28389,24 @@ var RenderableModel = class extends import_eventemitter3.default {
28035
28389
  return null;
28036
28390
  }
28037
28391
  const yMap = new Y12.Map();
28392
+ const uuid = this.uuid;
28393
+ const segmentsModel = new SegmentsModel(yMap, this.scope, type, this.liveCursor, this.isPerformanceMode);
28394
+ this.elementModels.set(uuid, segmentsModel);
28038
28395
  this.elements.doc?.transact(() => {
28039
- const uuid = this.uuid;
28040
28396
  yMap.set(ElementModel.KEYS.index, ++this.maxIndex);
28041
28397
  yMap.set(ElementModel.KEYS.uuid, uuid);
28042
28398
  yMap.set("type", type);
28043
28399
  if (shadow) {
28044
28400
  yMap.set(ElementModel.KEYS.shadow, "layer");
28045
28401
  }
28402
+ yMap.set(ElementModel.KEYS.points, new Y12.Array());
28046
28403
  yMap.set(ElementModel.KEYS.strokeWidth, this.toolbarModel.strokeWidth);
28047
28404
  yMap.set(ElementModel.KEYS.strokeColor, this.toolbarModel.strokeColor);
28048
28405
  yMap.set(ElementModel.KEYS.fillColor, this.toolbarModel.fillColor);
28049
28406
  yMap.set(ElementModel.KEYS.ownerId, this.userManager.selfId);
28050
28407
  this.elements.set(uuid, yMap);
28051
28408
  }, elementsUndoOrigin);
28052
- const segmentsModel = new SegmentsModel(yMap, this.scope, type, this.liveCursor);
28409
+ segmentsModel.bindObserver();
28053
28410
  this.initElement(segmentsModel);
28054
28411
  segmentsModel.dashArray = this.toolbarModel.dashArray;
28055
28412
  return segmentsModel;
@@ -28060,16 +28417,21 @@ var RenderableModel = class extends import_eventemitter3.default {
28060
28417
  return null;
28061
28418
  }
28062
28419
  const yMap = new Y12.Map();
28420
+ const uuid = this.uuid;
28421
+ const selectorModel = new SelectorModel(yMap, this.scope, this.liveCursor, this.isPerformanceMode);
28422
+ this.elementModels.set(uuid, selectorModel);
28063
28423
  this.elements.doc?.transact(() => {
28064
- const uuid = this.uuid;
28065
28424
  yMap.set(ElementModel.KEYS.index, ++this.maxIndex);
28066
28425
  yMap.set(ElementModel.KEYS.uuid, uuid);
28067
28426
  yMap.set("type", "selector");
28427
+ const initPoints = new Y12.Array();
28428
+ initPoints.push([0, 0, 0, 0]);
28429
+ yMap.set(ElementModel.KEYS.points, initPoints);
28068
28430
  yMap.set(ElementModel.KEYS.shadow, "layer");
28069
28431
  yMap.set(ElementModel.KEYS.ownerId, this.userManager.selfId);
28070
28432
  this.elements.set(uuid, yMap);
28071
28433
  }, elementsUndoOrigin);
28072
- const selectorModel = new SelectorModel(yMap, this.scope, this.liveCursor);
28434
+ selectorModel.bindObserver();
28073
28435
  selectorModel.shadow = "layer";
28074
28436
  return selectorModel;
28075
28437
  }
@@ -28078,21 +28440,24 @@ var RenderableModel = class extends import_eventemitter3.default {
28078
28440
  return null;
28079
28441
  }
28080
28442
  const yMap = new Y12.Map();
28443
+ const uuid = this.uuid;
28444
+ const straightLineModel = new StraightLineModel(yMap, this.scope, this.liveCursor, this.isPerformanceMode);
28445
+ this.elementModels.set(uuid, straightLineModel);
28081
28446
  this.elements.doc?.transact(() => {
28082
- const uuid = this.uuid;
28083
28447
  yMap.set(ElementModel.KEYS.index, ++this.maxIndex);
28084
28448
  yMap.set(ElementModel.KEYS.uuid, uuid);
28085
28449
  yMap.set("type", "line");
28086
28450
  if (shadow) {
28087
28451
  yMap.set(ElementModel.KEYS.shadow, "layer");
28088
28452
  }
28453
+ yMap.set("points", new Y12.Array());
28089
28454
  yMap.set(ElementModel.KEYS.strokeWidth, this.toolbarModel.strokeWidth);
28090
28455
  yMap.set(ElementModel.KEYS.strokeColor, this.toolbarModel.strokeColor);
28091
28456
  yMap.set(ElementModel.KEYS.fillColor, this.toolbarModel.fillColor);
28092
28457
  yMap.set(ElementModel.KEYS.ownerId, this.userManager.selfId);
28093
28458
  this.elements.set(uuid, yMap);
28094
28459
  }, elementsUndoOrigin);
28095
- const straightLineModel = new StraightLineModel(yMap, this.scope, this.liveCursor);
28460
+ straightLineModel.bindObserver();
28096
28461
  this.initElement(straightLineModel);
28097
28462
  straightLineModel.dashArray = this.toolbarModel.dashArray;
28098
28463
  return straightLineModel;
@@ -28102,21 +28467,26 @@ var RenderableModel = class extends import_eventemitter3.default {
28102
28467
  return null;
28103
28468
  }
28104
28469
  const yMap = new Y12.Map();
28470
+ const uuid = this.uuid;
28471
+ const lineModel = new LineModel(yMap, this.scope, this.liveCursor, this.isPerformanceMode);
28472
+ this.elementModels.set(uuid, lineModel);
28105
28473
  this.elements.doc?.transact(() => {
28106
- const uuid = this.uuid;
28107
28474
  yMap.set(ElementModel.KEYS.index, ++this.maxIndex);
28108
28475
  yMap.set(ElementModel.KEYS.uuid, uuid);
28109
28476
  yMap.set("type", "arrow");
28110
28477
  if (shadow) {
28111
28478
  yMap.set(ElementModel.KEYS.shadow, "layer");
28112
28479
  }
28480
+ yMap.set("headArrow", "none");
28481
+ yMap.set("tailArrow", "normal");
28482
+ yMap.set(ElementModel.KEYS.points, new Y12.Array());
28113
28483
  yMap.set(ElementModel.KEYS.strokeWidth, this.toolbarModel.strokeWidth);
28114
28484
  yMap.set(ElementModel.KEYS.strokeColor, this.toolbarModel.strokeColor);
28115
28485
  yMap.set(ElementModel.KEYS.fillColor, this.toolbarModel.fillColor);
28116
28486
  yMap.set(ElementModel.KEYS.ownerId, this.userManager.selfId);
28117
28487
  this.elements.set(uuid, yMap);
28118
28488
  }, elementsUndoOrigin);
28119
- const lineModel = new LineModel(yMap, this.scope, this.liveCursor);
28489
+ lineModel.bindObserver();
28120
28490
  this.initElement(lineModel);
28121
28491
  lineModel.dashArray = this.toolbarModel.dashArray;
28122
28492
  return lineModel;
@@ -28126,22 +28496,24 @@ var RenderableModel = class extends import_eventemitter3.default {
28126
28496
  return null;
28127
28497
  }
28128
28498
  const yMap = new Y12.Map();
28499
+ const uuid = this.uuid;
28500
+ const pointTextModel = new PointTextModel(yMap, this.scope, this.liveCursor, this.isPerformanceMode);
28501
+ this.elementModels.set(uuid, pointTextModel);
28129
28502
  this.elements.doc?.transact(() => {
28130
- const uuid = this.uuid;
28131
28503
  yMap.set(ElementModel.KEYS.index, ++this.maxIndex);
28132
28504
  yMap.set(ElementModel.KEYS.uuid, uuid);
28133
28505
  yMap.set("type", "point-text");
28134
28506
  if (shadow) {
28135
28507
  yMap.set(ElementModel.KEYS.shadow, "layer");
28136
28508
  }
28509
+ yMap.set(ElementModel.KEYS.points, Y12.Array.from([x, y]));
28137
28510
  yMap.set(ElementModel.KEYS.strokeWidth, this.toolbarModel.strokeWidth);
28138
28511
  yMap.set(ElementModel.KEYS.strokeColor, this.toolbarModel.strokeColor);
28139
28512
  yMap.set(ElementModel.KEYS.fillColor, this.toolbarModel.fillColor);
28140
28513
  yMap.set(ElementModel.KEYS.ownerId, this.userManager.selfId);
28141
28514
  this.elements.set(uuid, yMap);
28142
28515
  }, elementsUndoOrigin);
28143
- const pointTextModel = new PointTextModel(yMap, this.scope, this.liveCursor);
28144
- pointTextModel.setPoints([x, y]);
28516
+ pointTextModel.bindObserver();
28145
28517
  pointTextModel.fontSize = this.toolbarModel.fontSize;
28146
28518
  pointTextModel.fontFamily = this.toolbarModel.fontFamily;
28147
28519
  this.initElement(pointTextModel);
@@ -28163,12 +28535,13 @@ var RenderableModel = class extends import_eventemitter3.default {
28163
28535
  });
28164
28536
  }
28165
28537
  dispose(clearElements) {
28166
- (0, import_forge_room4.removeObserver)(this.elements, this.onElementsChange);
28538
+ (0, import_forge_room6.removeObserver)(this.elements, this.onElementsChange);
28167
28539
  if (clearElements) {
28168
28540
  this.elements.clear();
28169
28541
  }
28170
28542
  Array.from(this.elementModels.values()).forEach((model) => {
28171
28543
  model.dispose();
28544
+ model.disposeObserver();
28172
28545
  });
28173
28546
  }
28174
28547
  };
@@ -28465,11 +28838,24 @@ var CurveTool = class extends WhiteboardTool {
28465
28838
  _defineProperty19(this, "elementModel", null);
28466
28839
  _defineProperty19(this, "recognizer", new Recognizer());
28467
28840
  _defineProperty19(this, "pointCount", 0);
28841
+ _defineProperty19(this, "pendingPoints", []);
28842
+ _defineProperty19(this, "flushRafId", 0);
28468
28843
  _defineProperty19(this, "showLiveCursor", true);
28469
- this.tool.minDistance = 5;
28844
+ _defineProperty19(this, "flushPendingPoints", () => {
28845
+ this.flushRafId = 0;
28846
+ if (this.elementModel && this.pendingPoints.length > 0) {
28847
+ this.elementModel.appendPoints(this.pendingPoints);
28848
+ this.pendingPoints = [];
28849
+ }
28850
+ });
28470
28851
  }
28471
28852
  onMouseDown(_event) {
28472
28853
  this.pointCount = 0;
28854
+ this.pendingPoints = [];
28855
+ if (this.flushRafId) {
28856
+ cancelAnimationFrame(this.flushRafId);
28857
+ this.flushRafId = 0;
28858
+ }
28473
28859
  if (this.elementModel) {
28474
28860
  this.elementModel.dispose();
28475
28861
  }
@@ -28484,27 +28870,36 @@ var CurveTool = class extends WhiteboardTool {
28484
28870
  if (this.pointCount > 1024) {
28485
28871
  return;
28486
28872
  }
28487
- const MIN_DISTANCE = 4;
28873
+ const MIN_DISTANCE = 2;
28488
28874
  if (this.elementModel) {
28489
- const len = this.elementModel.points.length;
28490
- let last = {
28491
- x: 0,
28492
- y: 0
28493
- };
28494
- if (len >= 2) {
28495
- last = {
28496
- x: this.elementModel.points[len - 2],
28497
- y: this.elementModel.points[len - 1]
28498
- };
28875
+ let lastX = 0;
28876
+ let lastY = 0;
28877
+ if (this.pendingPoints.length >= 2) {
28878
+ lastX = this.pendingPoints[this.pendingPoints.length - 2];
28879
+ lastY = this.pendingPoints[this.pendingPoints.length - 1];
28880
+ } else {
28881
+ const len = this.elementModel.points.length;
28882
+ if (len >= 2) {
28883
+ lastX = this.elementModel.points[len - 2];
28884
+ lastY = this.elementModel.points[len - 1];
28885
+ }
28499
28886
  }
28500
- const dist = Math.max(Math.abs(last.x - event.point.x), Math.abs(last.y - event.point.y));
28887
+ const dist = Math.max(Math.abs(lastX - event.point.x), Math.abs(lastY - event.point.y));
28501
28888
  if (dist >= MIN_DISTANCE) {
28502
28889
  this.pointCount += 1;
28503
- this.elementModel.appendPoints([Math.round(event.point.x), Math.round(event.point.y)]);
28890
+ this.pendingPoints.push(event.point.x, event.point.y);
28891
+ if (!this.flushRafId) {
28892
+ this.flushRafId = requestAnimationFrame(this.flushPendingPoints);
28893
+ }
28504
28894
  }
28505
28895
  }
28506
28896
  }
28507
28897
  onMouseUp(event) {
28898
+ if (this.flushRafId) {
28899
+ cancelAnimationFrame(this.flushRafId);
28900
+ this.flushRafId = 0;
28901
+ }
28902
+ this.flushPendingPoints();
28508
28903
  this.modelGetter().then((model) => {
28509
28904
  if (!model) {
28510
28905
  return;
@@ -28605,7 +29000,7 @@ var RectangleTool = class extends WhiteboardTool {
28605
29000
 
28606
29001
  // src/model/ToolbarModel.ts
28607
29002
  var import_eventemitter32 = __toESM(require("eventemitter3"), 1);
28608
- var import_forge_room5 = require("@netless/forge-room");
29003
+ var import_forge_room7 = require("@netless/forge-room");
28609
29004
  function _defineProperty21(e, r, t) {
28610
29005
  return (r = _toPropertyKey21(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: true, configurable: true, writable: true }) : e[r] = t, e;
28611
29006
  }
@@ -28702,7 +29097,7 @@ var ToolbarModel = class extends import_eventemitter32.default {
28702
29097
  });
28703
29098
  }
28704
29099
  dispose() {
28705
- (0, import_forge_room5.removeObserver)(this.root, this.handleRootUpdate);
29100
+ (0, import_forge_room7.removeObserver)(this.root, this.handleRootUpdate);
28706
29101
  this.removeAllListeners();
28707
29102
  }
28708
29103
  };
@@ -28801,7 +29196,7 @@ var SelectorTool = class extends WhiteboardTool {
28801
29196
  // src/model/SelectElementsModel.ts
28802
29197
  var Y13 = __toESM(require("yjs"), 1);
28803
29198
  var import_eventemitter33 = __toESM(require("eventemitter3"), 1);
28804
- var import_forge_room6 = require("@netless/forge-room");
29199
+ var import_forge_room8 = require("@netless/forge-room");
28805
29200
 
28806
29201
  // src/WhiteboardKeys.ts
28807
29202
  var WhiteboardKeys = {
@@ -28851,7 +29246,7 @@ var SelectElementsModel = class extends import_eventemitter33.default {
28851
29246
  }
28852
29247
  const cb = this.observers.get(user.id);
28853
29248
  if (cb) {
28854
- (0, import_forge_room6.removeDeepObserver)(this.requestUserMap(user.id), cb);
29249
+ (0, import_forge_room8.removeDeepObserver)(this.requestUserMap(user.id), cb);
28855
29250
  this.observers.delete(user.id);
28856
29251
  }
28857
29252
  });
@@ -28860,7 +29255,7 @@ var SelectElementsModel = class extends import_eventemitter33.default {
28860
29255
  this.handleUserSelectElementsChange(user.id, evts);
28861
29256
  };
28862
29257
  if (this.observers.has(user.id)) {
28863
- (0, import_forge_room6.removeDeepObserver)(this.requestUserMap(user.id), this.observers.get(user.id));
29258
+ (0, import_forge_room8.removeDeepObserver)(this.requestUserMap(user.id), this.observers.get(user.id));
28864
29259
  this.observers.delete(user.id);
28865
29260
  }
28866
29261
  this.requestUserMap(user.id).observeDeep(observer);
@@ -28883,7 +29278,7 @@ var SelectElementsModel = class extends import_eventemitter33.default {
28883
29278
  this.handleUserSelectElementsChange(userId, evts);
28884
29279
  };
28885
29280
  if (this.observers.has(userId)) {
28886
- (0, import_forge_room6.removeDeepObserver)(this.requestUserMap(userId), this.observers.get(userId));
29281
+ (0, import_forge_room8.removeDeepObserver)(this.requestUserMap(userId), this.observers.get(userId));
28887
29282
  }
28888
29283
  this.requestUserMap(userId).observeDeep(observer);
28889
29284
  this.observers.set(userId, observer);
@@ -28947,7 +29342,7 @@ var SelectElementsModel = class extends import_eventemitter33.default {
28947
29342
  }
28948
29343
  dispose() {
28949
29344
  for (const [key, value] of this.observers.entries()) {
28950
- (0, import_forge_room6.removeDeepObserver)(this.requestUserMap(key), value);
29345
+ (0, import_forge_room8.removeDeepObserver)(this.requestUserMap(key), value);
28951
29346
  }
28952
29347
  this.observers.clear();
28953
29348
  this.userManager.off("leave", this.handleUserLeave);
@@ -29636,6 +30031,7 @@ var Editor = class extends import_eventemitter35.default {
29636
30031
  this.shadowContainer.remove();
29637
30032
  this.shadowScope.project.activeLayer.addChild(this.shadowContainer);
29638
30033
  this.targets.forEach((model) => {
30034
+ console.log("[][][] translateShadow model", model.root._dEH);
29639
30035
  model.shadow = this.shadowContainer.data.uuid;
29640
30036
  });
29641
30037
  }
@@ -29862,7 +30258,7 @@ var Gesture = class extends import_eventemitter36.default {
29862
30258
  };
29863
30259
 
29864
30260
  // src/Camera.ts
29865
- var import_forge_room7 = require("@netless/forge-room");
30261
+ var import_forge_room9 = require("@netless/forge-room");
29866
30262
  function _defineProperty28(e, r, t) {
29867
30263
  return (r = _toPropertyKey28(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: true, configurable: true, writable: true }) : e[r] = t, e;
29868
30264
  }
@@ -29939,14 +30335,14 @@ var Camera = class extends import_eventemitter37.default {
29939
30335
  }
29940
30336
  const cb = this.observers.get(user.id);
29941
30337
  if (cb) {
29942
- (0, import_forge_room7.removeObserver)(this.requestUserMap(user.id), cb);
30338
+ (0, import_forge_room9.removeObserver)(this.requestUserMap(user.id), cb);
29943
30339
  }
29944
30340
  });
29945
30341
  _defineProperty28(this, "handleUserJoin", (user) => {
29946
30342
  if (this.observers.has(user.id)) {
29947
30343
  const cb = this.observers.get(user.id);
29948
30344
  if (cb) {
29949
- (0, import_forge_room7.removeObserver)(this.requestUserMap(user.id), cb);
30345
+ (0, import_forge_room9.removeObserver)(this.requestUserMap(user.id), cb);
29950
30346
  this.observers.delete(user.id);
29951
30347
  }
29952
30348
  }
@@ -30058,7 +30454,7 @@ var Camera = class extends import_eventemitter37.default {
30058
30454
  this.handleViewMatrixUpdate(userId, evt);
30059
30455
  };
30060
30456
  if (this.observers.has(userId)) {
30061
- (0, import_forge_room7.removeObserver)(this.requestUserMap(userId), observer);
30457
+ (0, import_forge_room9.removeObserver)(this.requestUserMap(userId), observer);
30062
30458
  }
30063
30459
  this.requestUserMap(userId).observe(observer);
30064
30460
  this.observers.set(userId, observer);
@@ -30255,10 +30651,10 @@ var Camera = class extends import_eventemitter37.default {
30255
30651
  Array.from(this.observers.keys()).forEach((userId) => {
30256
30652
  const cb = this.observers.get(userId);
30257
30653
  if (cb) {
30258
- (0, import_forge_room7.removeObserver)(this.requestUserMap(userId), cb);
30654
+ (0, import_forge_room9.removeObserver)(this.requestUserMap(userId), cb);
30259
30655
  }
30260
30656
  });
30261
- (0, import_forge_room7.removeObserver)(this.whiteboardAttrsMap, this.handleMainCameraChange);
30657
+ (0, import_forge_room9.removeObserver)(this.whiteboardAttrsMap, this.handleMainCameraChange);
30262
30658
  this.userManager.off("join", this.handleUserJoin);
30263
30659
  this.userManager.off("leave", this.handleUserLeave);
30264
30660
  this.gesture.removeAllListeners();
@@ -30429,6 +30825,8 @@ var Whiteboard = class extends import_eventemitter38.default {
30429
30825
  _defineProperty31(this, "enableCameraBoundaryHighlight", void 0);
30430
30826
  _defineProperty31(this, "getElementAttribute", void 0);
30431
30827
  _defineProperty31(this, "setElementAttribute", void 0);
30828
+ _defineProperty31(this, "setPerformanceMode", void 0);
30829
+ _defineProperty31(this, "isPerformanceMode", void 0);
30432
30830
  _defineProperty31(this, "removeElement", void 0);
30433
30831
  _defineProperty31(this, "getCurrentTool", void 0);
30434
30832
  _defineProperty31(this, "setCurrentTool", void 0);
@@ -30549,7 +30947,7 @@ var EraserTool = class extends WhiteboardTool {
30549
30947
  // src/model/TrashedElementsModel.ts
30550
30948
  var Y14 = __toESM(require("yjs"), 1);
30551
30949
  var import_eventemitter39 = __toESM(require("eventemitter3"), 1);
30552
- var import_forge_room8 = require("@netless/forge-room");
30950
+ var import_forge_room10 = require("@netless/forge-room");
30553
30951
  function _defineProperty33(e, r, t) {
30554
30952
  return (r = _toPropertyKey33(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: true, configurable: true, writable: true }) : e[r] = t, e;
30555
30953
  }
@@ -30586,14 +30984,14 @@ var TrashedElementsModel = class extends import_eventemitter39.default {
30586
30984
  }
30587
30985
  const cb = this.observers.get(user.id);
30588
30986
  if (cb) {
30589
- (0, import_forge_room8.removeDeepObserver)(this.requestUserMap(user.id), cb);
30987
+ (0, import_forge_room10.removeDeepObserver)(this.requestUserMap(user.id), cb);
30590
30988
  }
30591
30989
  });
30592
30990
  _defineProperty33(this, "handleUserJoin", (user) => {
30593
30991
  if (this.observers.has(user.id)) {
30594
30992
  const cb = this.observers.get(user.id);
30595
30993
  if (cb) {
30596
- (0, import_forge_room8.removeDeepObserver)(this.requestUserMap(user.id), cb);
30994
+ (0, import_forge_room10.removeDeepObserver)(this.requestUserMap(user.id), cb);
30597
30995
  this.observers.delete(user.id);
30598
30996
  }
30599
30997
  }
@@ -30601,7 +30999,7 @@ var TrashedElementsModel = class extends import_eventemitter39.default {
30601
30999
  this.handleUserTrashElementsChange(user.id, evts);
30602
31000
  };
30603
31001
  if (this.observers.has(user.id)) {
30604
- (0, import_forge_room8.removeDeepObserver)(this.requestUserMap(user.id), this.observers.get(user.id));
31002
+ (0, import_forge_room10.removeDeepObserver)(this.requestUserMap(user.id), this.observers.get(user.id));
30605
31003
  }
30606
31004
  this.requestUserMap(user.id).observeDeep(observer);
30607
31005
  this.observers.set(user.id, observer);
@@ -30615,7 +31013,7 @@ var TrashedElementsModel = class extends import_eventemitter39.default {
30615
31013
  this.handleUserTrashElementsChange(userId, evts);
30616
31014
  };
30617
31015
  if (this.observers.has(userId)) {
30618
- (0, import_forge_room8.removeDeepObserver)(this.requestUserMap(userId), userId);
31016
+ (0, import_forge_room10.removeDeepObserver)(this.requestUserMap(userId), userId);
30619
31017
  }
30620
31018
  this.requestUserMap(userId).observeDeep(observer);
30621
31019
  this.observers.set(userId, observer);
@@ -30677,7 +31075,7 @@ var TrashedElementsModel = class extends import_eventemitter39.default {
30677
31075
  }
30678
31076
  dispose() {
30679
31077
  for (const [key, value] of this.observers.entries()) {
30680
- (0, import_forge_room8.removeDeepObserver)(this.requestUserMap(key), value);
31078
+ (0, import_forge_room10.removeDeepObserver)(this.requestUserMap(key), value);
30681
31079
  }
30682
31080
  this.observers.clear();
30683
31081
  this.userManager.off("leave", this.handleUserLeave);
@@ -30727,9 +31125,24 @@ var LaserPointerTool = class extends WhiteboardTool {
30727
31125
  if (this.pointCount > 1024) {
30728
31126
  return;
30729
31127
  }
31128
+ const MIN_DISTANCE = 4;
30730
31129
  if (this.elementModel) {
30731
- this.pointCount += 1;
30732
- this.elementModel.appendPoints([event.point.x, event.point.y]);
31130
+ const len = this.elementModel.points.length;
31131
+ let last = {
31132
+ x: 0,
31133
+ y: 0
31134
+ };
31135
+ if (len >= 2) {
31136
+ last = {
31137
+ x: this.elementModel.points[len - 2],
31138
+ y: this.elementModel.points[len - 1]
31139
+ };
31140
+ }
31141
+ const dist = Math.max(Math.abs(last.x - event.point.x), Math.abs(last.y - event.point.y));
31142
+ if (dist >= MIN_DISTANCE) {
31143
+ this.pointCount += 1;
31144
+ this.elementModel.appendPoints([Math.round(event.point.x), Math.round(event.point.y)]);
31145
+ }
30733
31146
  }
30734
31147
  }
30735
31148
  onMouseUp(_event) {
@@ -30741,7 +31154,7 @@ var LaserPointerTool = class extends WhiteboardTool {
30741
31154
 
30742
31155
  // src/model/PageModel.ts
30743
31156
  var import_eventemitter310 = __toESM(require("eventemitter3"), 1);
30744
- var import_forge_room9 = require("@netless/forge-room");
31157
+ var import_forge_room11 = require("@netless/forge-room");
30745
31158
  function _defineProperty35(e, r, t) {
30746
31159
  return (r = _toPropertyKey35(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: true, configurable: true, writable: true }) : e[r] = t, e;
30747
31160
  }
@@ -30774,7 +31187,7 @@ var PageModel = class extends import_eventemitter310.default {
30774
31187
  }
30775
31188
  const cb = this.observers.get(user.id);
30776
31189
  if (cb) {
30777
- (0, import_forge_room9.removeObserver)(this.requestUserMap(user.id), cb);
31190
+ (0, import_forge_room11.removeObserver)(this.requestUserMap(user.id), cb);
30778
31191
  }
30779
31192
  });
30780
31193
  _defineProperty35(this, "handleUserJoin", (user) => {
@@ -30788,7 +31201,7 @@ var PageModel = class extends import_eventemitter310.default {
30788
31201
  if (cameraMode === "main") {
30789
31202
  const targetPage = this.whiteboardAttrsMap.get(WhiteboardKeys.currentPage);
30790
31203
  if (!this.pageMap.has(targetPage) && targetPage !== "_i_") {
30791
- (0, import_forge_room9.log)(`main page {${targetPage}} not found.`, {}, "error");
31204
+ (0, import_forge_room11.log)(`main page {${targetPage}} not found.`, {}, "error");
30792
31205
  return;
30793
31206
  }
30794
31207
  this.requestUserMap(this.userManager.selfId).set(WhiteboardKeys.currentPage, targetPage);
@@ -30835,7 +31248,7 @@ var PageModel = class extends import_eventemitter310.default {
30835
31248
  if (this.observers.has(userId)) {
30836
31249
  const cb = this.observers.get(userId);
30837
31250
  if (cb) {
30838
- (0, import_forge_room9.removeObserver)(this.requestUserMap(userId), cb);
31251
+ (0, import_forge_room11.removeObserver)(this.requestUserMap(userId), cb);
30839
31252
  this.observers.delete(userId);
30840
31253
  }
30841
31254
  }
@@ -30924,12 +31337,12 @@ var PageModel = class extends import_eventemitter310.default {
30924
31337
  dispose() {
30925
31338
  for (const entry of this.observers.entries()) {
30926
31339
  const [userId, observer] = entry;
30927
- (0, import_forge_room9.removeObserver)(this.requestUserMap(userId), observer);
31340
+ (0, import_forge_room11.removeObserver)(this.requestUserMap(userId), observer);
30928
31341
  }
30929
31342
  this.userManager.off("join", this.handleUserJoin);
30930
31343
  this.userManager.off("leave", this.handleUserLeave);
30931
- (0, import_forge_room9.removeObserver)(this.whiteboardAttrsMap, this.handleMainPageChange);
30932
- (0, import_forge_room9.removeObserver)(this.pageMap, this.handlePageMapChange);
31344
+ (0, import_forge_room11.removeObserver)(this.whiteboardAttrsMap, this.handleMainPageChange);
31345
+ (0, import_forge_room11.removeObserver)(this.pageMap, this.handlePageMapChange);
30933
31346
  }
30934
31347
  };
30935
31348
 
@@ -30944,8 +31357,8 @@ async function waitUntil(fn, timeout) {
30944
31357
 
30945
31358
  // src/IndexedNavigation.ts
30946
31359
  var import_eventemitter311 = __toESM(require("eventemitter3"), 1);
30947
- var import_forge_room10 = require("@netless/forge-room");
30948
- var import_forge_room11 = require("@netless/forge-room");
31360
+ var import_forge_room12 = require("@netless/forge-room");
31361
+ var import_forge_room13 = require("@netless/forge-room");
30949
31362
  function _defineProperty36(e, r, t) {
30950
31363
  return (r = _toPropertyKey36(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: true, configurable: true, writable: true }) : e[r] = t, e;
30951
31364
  }
@@ -30972,7 +31385,7 @@ var IndexedNavigation = class extends import_eventemitter311.default {
30972
31385
  return this.list[key] && this.list[key].prev === "";
30973
31386
  });
30974
31387
  if (!headId) {
30975
- (0, import_forge_room10.log)("indexed navigation confusion", {
31388
+ (0, import_forge_room12.log)("indexed navigation confusion", {
30976
31389
  list: JSON.stringify(this.list)
30977
31390
  }, "error");
30978
31391
  throw new Error("indexed navigation confusion");
@@ -31288,7 +31701,7 @@ var IndexedNavigation = class extends import_eventemitter311.default {
31288
31701
  }
31289
31702
  }
31290
31703
  dispose() {
31291
- (0, import_forge_room11.removeObserver)(this.indexedPageMap, this.handleIndexedPageMapUpdate);
31704
+ (0, import_forge_room13.removeObserver)(this.indexedPageMap, this.handleIndexedPageMapUpdate);
31292
31705
  this.pageModel.off("switchPage");
31293
31706
  this.pageModel.off("pagesChange");
31294
31707
  }
@@ -31509,7 +31922,7 @@ var SequenceExecutor = class {
31509
31922
  };
31510
31923
 
31511
31924
  // src/WhiteboardApplication.ts
31512
- var import_forge_room13 = require("@netless/forge-room");
31925
+ var import_forge_room15 = require("@netless/forge-room");
31513
31926
 
31514
31927
  // src/LiveCursor.ts
31515
31928
  function _defineProperty42(e, r, t) {
@@ -31564,9 +31977,19 @@ var LiveCursor = class {
31564
31977
  cursor.style.fontSize = "12px";
31565
31978
  cursor.style.padding = "2px 4px";
31566
31979
  cursor.style.borderRadius = "4px";
31567
- cursor.textContent = this.userManager.getUser(userId)?.nickName ?? userId;
31980
+ this.updateCursorLabel(userId, cursor);
31568
31981
  return cursor;
31569
31982
  }
31983
+ updateCursorLabel(userId, cursor) {
31984
+ const target = cursor ?? this.cursors.get(userId);
31985
+ if (!target) {
31986
+ return;
31987
+ }
31988
+ if (target.textContent && target.textContent !== userId) {
31989
+ return;
31990
+ }
31991
+ target.textContent = this.userManager.getUser(userId)?.nickName ?? userId;
31992
+ }
31570
31993
  isOnSamePage(userId) {
31571
31994
  const otherPage = this.requestUserMap(userId).get(WhiteboardKeys.currentPage);
31572
31995
  const selfPage = this.requestUserMap(this.userManager.selfId).get(WhiteboardKeys.currentPage);
@@ -31602,6 +32025,7 @@ var LiveCursor = class {
31602
32025
  }
31603
32026
  const cursor = this.cursors.get(userId);
31604
32027
  if (cursor) {
32028
+ this.updateCursorLabel(userId, cursor);
31605
32029
  const viewPoint = this.paperScope.project.view.projectToView(point);
31606
32030
  cursor.style.left = viewPoint.x + "px";
31607
32031
  cursor.style.top = viewPoint.y + "px";
@@ -31666,7 +32090,7 @@ var AsyncMap = class {
31666
32090
  if (!window.__forge_gl_wb_status__) {
31667
32091
  window.__forge_gl_wb_status__ = new AsyncMap();
31668
32092
  }
31669
- var WhiteboardApplication = class _WhiteboardApplication extends import_forge_room12.AbstractApplication {
32093
+ var WhiteboardApplication = class _WhiteboardApplication extends import_forge_room14.AbstractApplication {
31670
32094
  get undoManager() {
31671
32095
  const page = this.pageModel.getCurrentPage(this.userId);
31672
32096
  if (page) {
@@ -31717,6 +32141,7 @@ var WhiteboardApplication = class _WhiteboardApplication extends import_forge_ro
31717
32141
  _defineProperty43(this, "permissions", void 0);
31718
32142
  _defineProperty43(this, "inputType", "any");
31719
32143
  _defineProperty43(this, "isPenEvent", false);
32144
+ _defineProperty43(this, "activePenPointerId", null);
31720
32145
  _defineProperty43(this, "hasPenInput", null);
31721
32146
  _defineProperty43(this, "disableViewModelUpdate", false);
31722
32147
  _defineProperty43(this, "internalResizeObserver", true);
@@ -31812,7 +32237,7 @@ var WhiteboardApplication = class _WhiteboardApplication extends import_forge_ro
31812
32237
  }
31813
32238
  } else {
31814
32239
  console.warn(`[@netless/forge-whiteboard] page ${pageId} not found`);
31815
- (0, import_forge_room12.log)(`[@netless/forge-whiteboard] page ${pageId} not found`, {}, "warn");
32240
+ (0, import_forge_room14.log)(`[@netless/forge-whiteboard] page ${pageId} not found`, {}, "warn");
31816
32241
  }
31817
32242
  await waitUntil(() => this.undoManagers.has(pageId), 1e3);
31818
32243
  if (this.undoManagers.has(pageId)) {
@@ -31824,7 +32249,7 @@ var WhiteboardApplication = class _WhiteboardApplication extends import_forge_ro
31824
32249
  this.undoManagers.get(pageId).on("stack-item-popped", this.handleStackItemPopped);
31825
32250
  } else {
31826
32251
  console.warn(`[@netless/forge-whiteboard] undo manager for page ${pageId} not found`);
31827
- (0, import_forge_room12.log)(`[@netless/forge-whiteboard] undo manager for page ${pageId} not found`, {}, "warn");
32252
+ (0, import_forge_room14.log)(`[@netless/forge-whiteboard] undo manager for page ${pageId} not found`, {}, "warn");
31828
32253
  }
31829
32254
  this.emitter.emit("redoStackLength", this.undoManager?.redoStack.length ?? 0);
31830
32255
  this.emitter.emit("undoStackLength", this.undoManager?.undoStack.length ?? 0);
@@ -31833,6 +32258,9 @@ var WhiteboardApplication = class _WhiteboardApplication extends import_forge_ro
31833
32258
  _defineProperty43(this, "hasPermission", (flag) => {
31834
32259
  return this.permissions.hasPermission(flag, this.userId);
31835
32260
  });
32261
+ _defineProperty43(this, "isPerformanceMode", () => {
32262
+ return this.option.performance ?? false;
32263
+ });
31836
32264
  _defineProperty43(this, "handleStackItemAdded", () => {
31837
32265
  this.selectElementsModel.clearSelectElementForSelf();
31838
32266
  this.emitter.emit("redoStackLength", this.undoManager?.redoStack.length ?? 0);
@@ -31847,7 +32275,18 @@ var WhiteboardApplication = class _WhiteboardApplication extends import_forge_ro
31847
32275
  const id = ids[i];
31848
32276
  if (!this.layers.has(id)) {
31849
32277
  const elementsMap = this.getMap(`layer/${id}/elements`);
31850
- const renderableModel = new RenderableModel(id, this.shadowEmitter, elementsMap, this.paperScope, this.toolbarModel, this.userManager, this.imageSets, this.liveCursor, this.hasPermission);
32278
+ const renderableModel = new RenderableModel({
32279
+ layerId: id,
32280
+ shadowEmitter: this.shadowEmitter,
32281
+ elements: elementsMap,
32282
+ scope: this.paperScope,
32283
+ toolbarModel: this.toolbarModel,
32284
+ userManager: this.userManager,
32285
+ imageSets: this.imageSets,
32286
+ liveCursor: this.liveCursor,
32287
+ hasPermission: this.hasPermission,
32288
+ isPerformanceMode: this.isPerformanceMode
32289
+ });
31851
32290
  this.layers.set(id, renderableModel);
31852
32291
  }
31853
32292
  if (!this.undoManagers.has(id)) {
@@ -32031,11 +32470,34 @@ var WhiteboardApplication = class _WhiteboardApplication extends import_forge_ro
32031
32470
  this.imageSets.setAttribute("data-image-sets", "");
32032
32471
  this.rootElement.appendChild(this.imageSets);
32033
32472
  document.body.addEventListener("pointerdown", (evt) => {
32034
- this.isPenEvent = evt.pointerType === "pen";
32035
- if (evt.pointerType === "pen" && this.hasPenInput === null) {
32036
- this.hasPenInput = true;
32037
- this.inputType = "pen";
32038
- this.emitter.emit("inputTypeChange", this.inputType);
32473
+ if (evt.pointerType === "pen") {
32474
+ this.isPenEvent = true;
32475
+ this.activePenPointerId = evt.pointerId;
32476
+ if (this.hasPenInput === null) {
32477
+ this.hasPenInput = true;
32478
+ this.inputType = "pen";
32479
+ this.emitter.emit("inputTypeChange", this.inputType);
32480
+ }
32481
+ } else {
32482
+ if (this.activePenPointerId === null) {
32483
+ this.isPenEvent = false;
32484
+ }
32485
+ }
32486
+ }, {
32487
+ capture: true
32488
+ });
32489
+ document.body.addEventListener("pointerup", (evt) => {
32490
+ if (evt.pointerId === this.activePenPointerId) {
32491
+ this.activePenPointerId = null;
32492
+ this.isPenEvent = false;
32493
+ }
32494
+ }, {
32495
+ capture: true
32496
+ });
32497
+ document.body.addEventListener("pointercancel", (evt) => {
32498
+ if (evt.pointerId === this.activePenPointerId) {
32499
+ this.activePenPointerId = null;
32500
+ this.isPenEvent = false;
32039
32501
  }
32040
32502
  }, {
32041
32503
  capture: true
@@ -32091,7 +32553,7 @@ var WhiteboardApplication = class _WhiteboardApplication extends import_forge_ro
32091
32553
  this.emitter.setViewModeToFree = (userId) => {
32092
32554
  if (that.disableViewModelUpdate) {
32093
32555
  console.warn("Operation failed. Perspective mode switching is disabled in the current environment.");
32094
- (0, import_forge_room12.log)("Operation failed. Perspective mode switching is disabled in the current environment.", {}, "warn");
32556
+ (0, import_forge_room14.log)("Operation failed. Perspective mode switching is disabled in the current environment.", {}, "warn");
32095
32557
  return;
32096
32558
  }
32097
32559
  const targetId = userId ? this.hasPermission(WhiteboardPermissionFlag.setOthersView) ? userId : null : this.userId;
@@ -32102,7 +32564,7 @@ var WhiteboardApplication = class _WhiteboardApplication extends import_forge_ro
32102
32564
  this.emitter.setViewModeToFlow = (flowId, userId) => {
32103
32565
  if (that.disableViewModelUpdate) {
32104
32566
  console.warn("Operation failed. Perspective mode switching is disabled in the current environment.");
32105
- (0, import_forge_room12.log)("Operation failed. Perspective mode switching is disabled in the current environment.", {}, "warn");
32567
+ (0, import_forge_room14.log)("Operation failed. Perspective mode switching is disabled in the current environment.", {}, "warn");
32106
32568
  return;
32107
32569
  }
32108
32570
  const targetId = userId ? this.hasPermission(WhiteboardPermissionFlag.setOthersView) ? userId : null : this.userId;
@@ -32114,10 +32576,16 @@ var WhiteboardApplication = class _WhiteboardApplication extends import_forge_ro
32114
32576
  this.camera.resetViewMatrixToFlow(flowId);
32115
32577
  }
32116
32578
  };
32579
+ this.emitter.setPerformanceMode = (enabled) => {
32580
+ this.option.performance = enabled;
32581
+ };
32582
+ this.emitter.isPerformanceMode = () => {
32583
+ return this.isPerformanceMode();
32584
+ };
32117
32585
  this.emitter.setViewModeToMain = (userId) => {
32118
32586
  if (that.disableViewModelUpdate) {
32119
32587
  console.warn("Operation failed. Perspective mode switching is disabled in the current environment.");
32120
- (0, import_forge_room12.log)("Operation failed. Perspective mode switching is disabled in the current environment.", {}, "warn");
32588
+ (0, import_forge_room14.log)("Operation failed. Perspective mode switching is disabled in the current environment.", {}, "warn");
32121
32589
  return;
32122
32590
  }
32123
32591
  const targetId = userId ? this.hasPermission(WhiteboardPermissionFlag.setOthersView) ? userId : null : this.userId;
@@ -32131,7 +32599,7 @@ var WhiteboardApplication = class _WhiteboardApplication extends import_forge_ro
32131
32599
  };
32132
32600
  this.emitter.insertImage = (src, pageId) => {
32133
32601
  if (!/https/.test(src)) {
32134
- (0, import_forge_room12.log)("[@netless/forge-whiteboard] invalid image url, src needs to be in the HTTPS protocol.", {
32602
+ (0, import_forge_room14.log)("[@netless/forge-whiteboard] invalid image url, src needs to be in the HTTPS protocol.", {
32135
32603
  src
32136
32604
  }, "warn");
32137
32605
  return;
@@ -32141,14 +32609,14 @@ var WhiteboardApplication = class _WhiteboardApplication extends import_forge_ro
32141
32609
  targetPageId = this.pageModel.getCurrentPage(this.userManager.selfId);
32142
32610
  }
32143
32611
  if (!targetPageId) {
32144
- (0, import_forge_room12.log)("[@netless/forge-whiteboard] page not found", {}, "warn");
32612
+ (0, import_forge_room14.log)("[@netless/forge-whiteboard] page not found", {}, "warn");
32145
32613
  return;
32146
32614
  }
32147
32615
  this.layers.get(targetPageId)?.createImage(src);
32148
32616
  };
32149
32617
  this.emitter.removeElement = (pageId, elementId) => {
32150
32618
  if (!this.layers.has(pageId)) {
32151
- (0, import_forge_room12.log)("[@netless/forge-whiteboard] page not found", {}, "warn");
32619
+ (0, import_forge_room14.log)("[@netless/forge-whiteboard] page not found", {}, "warn");
32152
32620
  return;
32153
32621
  }
32154
32622
  this.layers.get(pageId)?.removeElementItem(elementId);
@@ -32168,7 +32636,18 @@ var WhiteboardApplication = class _WhiteboardApplication extends import_forge_ro
32168
32636
  const source = this.getMap(`layer/${sourceId}/elements`);
32169
32637
  const target = this.getMap(`layer/${targetId}/elements`);
32170
32638
  if (!this.layers.has(targetId)) {
32171
- this.layers.set(targetId, new RenderableModel(targetId, this.shadowEmitter, target, this.paperScope, this.toolbarModel, this.userManager, this.imageSets, this.liveCursor, this.hasPermission));
32639
+ this.layers.set(targetId, new RenderableModel({
32640
+ layerId: targetId,
32641
+ shadowEmitter: this.shadowEmitter,
32642
+ elements: target,
32643
+ scope: this.paperScope,
32644
+ toolbarModel: this.toolbarModel,
32645
+ userManager: this.userManager,
32646
+ imageSets: this.imageSets,
32647
+ liveCursor: this.liveCursor,
32648
+ hasPermission: this.hasPermission,
32649
+ isPerformanceMode: this.isPerformanceMode
32650
+ }));
32172
32651
  }
32173
32652
  if (!this.undoManagers.has(targetId)) {
32174
32653
  const undoManager = new Y15.UndoManager(target, {
@@ -32237,15 +32716,15 @@ var WhiteboardApplication = class _WhiteboardApplication extends import_forge_ro
32237
32716
  this.liveCursor.showLiveCursor = value;
32238
32717
  };
32239
32718
  this.emitter.updateViewport = (width, height) => {
32240
- (0, import_forge_room12.log)(`call updateViewport with width: ${width}, height: ${height}`);
32719
+ (0, import_forge_room14.log)(`call updateViewport with width: ${width}, height: ${height}`);
32241
32720
  this.updateOptionSize(width, height);
32242
32721
  };
32243
32722
  this.emitter.__setMainCanvasVisible = (visible) => {
32244
- (0, import_forge_room12.log)(`call __setMainCanvasVisible with visible: ${visible}`);
32723
+ (0, import_forge_room14.log)(`call __setMainCanvasVisible with visible: ${visible}`);
32245
32724
  this.canvasElement.style.opacity = visible ? "1" : "0";
32246
32725
  };
32247
32726
  this.emitter.on("error", (errorCode, errorMessage) => {
32248
- (0, import_forge_room12.log)("WhiteboardApplicationError", {
32727
+ (0, import_forge_room14.log)("WhiteboardApplicationError", {
32249
32728
  errorCode,
32250
32729
  errorMessage
32251
32730
  });
@@ -32255,7 +32734,7 @@ var WhiteboardApplication = class _WhiteboardApplication extends import_forge_ro
32255
32734
  return that.delayTranslateOut;
32256
32735
  },
32257
32736
  set(value) {
32258
- (0, import_forge_room12.log)(`call __delayTranslateOut with value: ${value}`);
32737
+ (0, import_forge_room14.log)(`call __delayTranslateOut with value: ${value}`);
32259
32738
  that.delayTranslateOut = value;
32260
32739
  }
32261
32740
  });
@@ -32358,7 +32837,7 @@ var WhiteboardApplication = class _WhiteboardApplication extends import_forge_ro
32358
32837
  }
32359
32838
  async initialize(option) {
32360
32839
  _WhiteboardApplication.instanceCount.set(this.appId, (_WhiteboardApplication.instanceCount.get(this.appId) ?? 0) + 1);
32361
- (0, import_forge_room12.log)(`whiteboard ${this.appId} initialize. instance count: ${_WhiteboardApplication.instanceCount.get(this.appId) ?? 0}`, {}, "info");
32840
+ (0, import_forge_room14.log)(`whiteboard ${this.appId} initialize. instance count: ${_WhiteboardApplication.instanceCount.get(this.appId) ?? 0}`, {}, "info");
32362
32841
  this.appDoc.transact(() => {
32363
32842
  this.permissions = new WhiteboardPermissions(this.writableManager, this.userManager, (userId) => {
32364
32843
  return this.userMap(userId);
@@ -32403,6 +32882,11 @@ var WhiteboardApplication = class _WhiteboardApplication extends import_forge_ro
32403
32882
  this.editors.forEach((editor) => {
32404
32883
  editor.updateBounds();
32405
32884
  });
32885
+ const area = this.paperScope.project.view.size.width * this.paperScope.project.view.size.height;
32886
+ const minDistance = Math.ceil(area / 4e5);
32887
+ Object.keys(this.tools).forEach((key) => {
32888
+ this.tools[key].tool.minDistance = minDistance;
32889
+ });
32406
32890
  });
32407
32891
  this.camera.on("userPageChange", (userId, pageId) => {
32408
32892
  this.emitter.emit("activePageChange", userId, pageId);
@@ -32464,7 +32948,7 @@ var WhiteboardApplication = class _WhiteboardApplication extends import_forge_ro
32464
32948
  this.paperScope.tool = this.tools[this.toolbarModel.currentTool].tool;
32465
32949
  } else {
32466
32950
  this.paperScope.tool = this.tools["curve"].tool;
32467
- (0, import_forge_room12.log)(`${this.toolbarModel.currentTool} not supported, backup to curve`);
32951
+ (0, import_forge_room14.log)(`${this.toolbarModel.currentTool} not supported, backup to curve`);
32468
32952
  }
32469
32953
  this.selectElementsModel.on("elementsChange", this.handleElementsSelect);
32470
32954
  this.trashedElementsModel.on("elementsChange", this.handleElementsTrash);
@@ -32671,9 +33155,14 @@ var WhiteboardApplication = class _WhiteboardApplication extends import_forge_ro
32671
33155
  this.snapshotScope.view.matrix.scale(scale, this.paperScope.project.view.bounds.topLeft);
32672
33156
  this.snapshotScope.view.viewSize = this.paperScope.project.view.viewSize.clone().multiply(scale);
32673
33157
  }
32674
- return new Promise((resolve) => {
33158
+ return new Promise((resolve, reject) => {
32675
33159
  setTimeout(() => {
32676
- resolve(this.snapshotScope.view.element.toDataURL("image/png"));
33160
+ try {
33161
+ const res = this.snapshotScope.view.element.toDataURL("image/png");
33162
+ resolve(res);
33163
+ } catch (error) {
33164
+ reject(error);
33165
+ }
32677
33166
  }, 32);
32678
33167
  });
32679
33168
  }
@@ -32751,8 +33240,8 @@ var WhiteboardApplication = class _WhiteboardApplication extends import_forge_ro
32751
33240
  this.toolbarModel.dispose();
32752
33241
  this.emitter.indexedNavigation.dispose();
32753
33242
  this.permissions.dispose();
32754
- (0, import_forge_room13.removeObserver)(this.userMap(this.userId), this.handleSyncedWhiteboardStatusChange);
32755
- (0, import_forge_room12.log)(`whiteboard ${this.appId} disposed. instance count: ${_WhiteboardApplication.instanceCount.get(this.appId) ?? 0}`, {}, "info");
33243
+ (0, import_forge_room15.removeObserver)(this.userMap(this.userId), this.handleSyncedWhiteboardStatusChange);
33244
+ (0, import_forge_room14.log)(`whiteboard ${this.appId} disposed. instance count: ${_WhiteboardApplication.instanceCount.get(this.appId) ?? 0}`, {}, "info");
32756
33245
  }
32757
33246
  };
32758
33247
  _defineProperty43(WhiteboardApplication, "instanceCount", /* @__PURE__ */ new Map());