@difizen/libro-core 1.0.0 → 1.0.2

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 (42) hide show
  1. package/es/cell/libro-cell-service.d.ts +2 -0
  2. package/es/cell/libro-cell-service.d.ts.map +1 -1
  3. package/es/cell/libro-cell-service.js +9 -2
  4. package/es/cell/libro-cell-view.d.ts +2 -0
  5. package/es/cell/libro-cell-view.d.ts.map +1 -1
  6. package/es/cell/libro-cell-view.js +26 -0
  7. package/es/cell/libro-edit-cell-view.d.ts.map +1 -1
  8. package/es/cell/libro-edit-cell-view.js +22 -0
  9. package/es/command/libro-command-contribution.d.ts +4 -0
  10. package/es/command/libro-command-contribution.d.ts.map +1 -1
  11. package/es/command/libro-command-contribution.js +40 -26
  12. package/es/index.less +1 -1
  13. package/es/libro-protocol.d.ts +5 -2
  14. package/es/libro-protocol.d.ts.map +1 -1
  15. package/es/libro-protocol.js +0 -1
  16. package/es/libro-service.d.ts +2 -0
  17. package/es/libro-service.d.ts.map +1 -1
  18. package/es/libro-service.js +37 -21
  19. package/es/libro-setting.d.ts +1 -0
  20. package/es/libro-setting.d.ts.map +1 -1
  21. package/es/libro-setting.js +10 -0
  22. package/es/libro-view-tracker.d.ts +44 -1
  23. package/es/libro-view-tracker.d.ts.map +1 -1
  24. package/es/libro-view-tracker.js +117 -8
  25. package/es/libro-view.d.ts +3 -0
  26. package/es/libro-view.d.ts.map +1 -1
  27. package/es/libro-view.js +80 -23
  28. package/es/utils/index.d.ts +13 -0
  29. package/es/utils/index.d.ts.map +1 -1
  30. package/es/utils/index.js +125 -1
  31. package/package.json +5 -5
  32. package/src/cell/libro-cell-service.ts +2 -0
  33. package/src/cell/libro-cell-view.tsx +36 -0
  34. package/src/cell/libro-edit-cell-view.tsx +25 -0
  35. package/src/command/libro-command-contribution.ts +37 -23
  36. package/src/index.less +1 -1
  37. package/src/libro-protocol.ts +6 -3
  38. package/src/libro-service.ts +10 -3
  39. package/src/libro-setting.ts +11 -0
  40. package/src/libro-view-tracker.ts +105 -2
  41. package/src/libro-view.tsx +63 -3
  42. package/src/utils/index.ts +142 -0
package/es/libro-view.js CHANGED
@@ -1,5 +1,5 @@
1
1
  function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
2
- var _dec, _dec2, _dec3, _dec4, _dec5, _dec6, _dec7, _dec8, _dec9, _dec10, _dec11, _dec12, _class, _class2, _descriptor, _descriptor2, _descriptor3, _descriptor4, _descriptor5, _descriptor6, _descriptor7, _descriptor8, _descriptor9, _descriptor10;
2
+ var _dec, _dec2, _dec3, _dec4, _dec5, _dec6, _dec7, _dec8, _dec9, _dec10, _dec11, _dec12, _dec13, _class, _class2, _descriptor, _descriptor2, _descriptor3, _descriptor4, _descriptor5, _descriptor6, _descriptor7, _descriptor8, _descriptor9, _descriptor10, _descriptor11;
3
3
  function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
4
4
  function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
5
5
  function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
@@ -33,7 +33,8 @@ function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
33
33
  import { ToTopOutlined } from '@ant-design/icons';
34
34
  import { concatMultilineString, copy2clipboard, readFromClipboard } from '@difizen/libro-common';
35
35
  import { equals, useInject, inject, transient, BaseView, Slot, view, ViewInstance, ViewManager, ViewOption, Deferred, Disposable, DisposableCollection, Emitter, getOrigin, prop, watch, ConfigurationService, useConfigurationValue } from '@difizen/libro-common/app';
36
- import { FloatButton, Button, Spin } from 'antd';
36
+ import { l10n } from '@difizen/libro-common/l10n';
37
+ import { FloatButton, Button, Spin, message } from 'antd';
37
38
  import { forwardRef, memo, useCallback, useEffect, useRef } from 'react';
38
39
  import { v4 } from 'uuid';
39
40
  import { CellService, EditorCellView, ExecutableCellModel, ExecutableCellView } from "./cell/index.js";
@@ -45,8 +46,9 @@ import { LibroModel } from "./libro-model.js";
45
46
  import { NotebookService, notebookViewFactoryId } from "./libro-protocol.js";
46
47
  import { LibroService } from "./libro-service.js";
47
48
  import { AutoInsertWhenNoCell, EnterEditModeWhenAddCell, HeaderToolbarVisible, RightContentFixed } from "./libro-setting.js";
49
+ import { LibroViewTracker } from "./libro-view-tracker.js";
48
50
  import { LibroSlotManager, LibroSlotView } from "./slot/index.js";
49
- import { useSize } from "./utils/index.js";
51
+ import { useFrameMonitor, useSize } from "./utils/index.js";
50
52
  import { VirtualizedManagerHelper } from "./virtualized-manager-helper.js";
51
53
  import "./index.less";
52
54
  import { jsx as _jsx } from "react/jsx-runtime";
@@ -66,6 +68,17 @@ export var LibroContentComponent = /*#__PURE__*/memo(function LibroContentCompon
66
68
  var _useConfigurationValu3 = useConfigurationValue(RightContentFixed),
67
69
  _useConfigurationValu4 = _slicedToArray(_useConfigurationValu3, 1),
68
70
  rightContentFixed = _useConfigurationValu4[0];
71
+ useFrameMonitor(libroViewContentRef, instance.libroViewTracker.isEnabledSpmReporter, function (payload) {
72
+ var fpsTracker = instance.libroViewTracker.getOrCreateTrackers({
73
+ type: 'fps'
74
+ });
75
+ fpsTracker['avgFPS'] = payload.summary.avgFPS;
76
+ fpsTracker['maxFrameTime'] = payload.summary.maxFrameTime;
77
+ fpsTracker['totalDropped'] = payload.summary.totalDropped;
78
+ fpsTracker['extra'] = payload.frames;
79
+ fpsTracker['cells'] = instance.model.cells.length;
80
+ instance.libroViewTracker.tracker(fpsTracker);
81
+ });
69
82
  var handleScroll = useCallback(function () {
70
83
  var _instance$container, _instance$activeCell, _instance$activeCell2, _instance$activeCell3, _activeOutput$outputs, _instance$activeCell4, _libroViewTopRef$curr;
71
84
  instance.cellScrollEmitter.fire();
@@ -207,7 +220,7 @@ export var LibroRender = /*#__PURE__*/forwardRef(function LibroRender(props, ref
207
220
  children: /*#__PURE__*/_jsx(LibroContentComponent, {})
208
221
  });
209
222
  });
210
- export var LibroView = (_dec = transient(), _dec2 = view(notebookViewFactoryId), _dec3 = prop(), _dec4 = inject(CellService), _dec5 = inject(LibroService), _dec6 = inject(LibroSlotManager), _dec7 = inject(LibroContextKey), _dec8 = inject(ViewManager), _dec9 = inject(ConfigurationService), _dec10 = prop(), _dec11 = prop(), _dec12 = prop(), _dec(_class = _dec2(_class = (_class2 = /*#__PURE__*/function (_BaseView) {
223
+ export var LibroView = (_dec = transient(), _dec2 = view(notebookViewFactoryId), _dec3 = prop(), _dec4 = inject(CellService), _dec5 = inject(LibroService), _dec6 = inject(LibroSlotManager), _dec7 = inject(LibroContextKey), _dec8 = inject(LibroViewTracker), _dec9 = inject(ViewManager), _dec10 = inject(ConfigurationService), _dec11 = prop(), _dec12 = prop(), _dec13 = prop(), _dec(_class = _dec2(_class = (_class2 = /*#__PURE__*/function (_BaseView) {
211
224
  _inherits(LibroView, _BaseView);
212
225
  var _super = _createSuper(LibroView);
213
226
  function LibroView(_options, collapseServiceFactory, notebookService, virtualizedManagerHelper) {
@@ -233,17 +246,19 @@ export var LibroView = (_dec = transient(), _dec2 = view(notebookViewFactoryId),
233
246
  _initializerDefineProperty(_this, "libroService", _descriptor3, _assertThisInitialized(_this));
234
247
  _initializerDefineProperty(_this, "libroSlotManager", _descriptor4, _assertThisInitialized(_this));
235
248
  _initializerDefineProperty(_this, "contextKey", _descriptor5, _assertThisInitialized(_this));
236
- _initializerDefineProperty(_this, "viewManager", _descriptor6, _assertThisInitialized(_this));
237
- _initializerDefineProperty(_this, "configurationService", _descriptor7, _assertThisInitialized(_this));
249
+ _initializerDefineProperty(_this, "libroViewTracker", _descriptor6, _assertThisInitialized(_this));
250
+ _initializerDefineProperty(_this, "viewManager", _descriptor7, _assertThisInitialized(_this));
251
+ _initializerDefineProperty(_this, "configurationService", _descriptor8, _assertThisInitialized(_this));
238
252
  _this.virtualizedManager = void 0;
239
253
  _this.virtualizedManagerHelper = void 0;
240
254
  _this.notebookService = void 0;
241
255
  _this.collapseService = void 0;
242
256
  _this.isDragging = false;
243
257
  _this.clipboard = void 0;
244
- _initializerDefineProperty(_this, "collapserVisible", _descriptor8, _assertThisInitialized(_this));
245
- _initializerDefineProperty(_this, "outputsScroll", _descriptor9, _assertThisInitialized(_this));
246
- _initializerDefineProperty(_this, "saving", _descriptor10, _assertThisInitialized(_this));
258
+ _initializerDefineProperty(_this, "collapserVisible", _descriptor9, _assertThisInitialized(_this));
259
+ _initializerDefineProperty(_this, "outputsScroll", _descriptor10, _assertThisInitialized(_this));
260
+ _initializerDefineProperty(_this, "saving", _descriptor11, _assertThisInitialized(_this));
261
+ _this.options = void 0;
247
262
  _this.onSaveEmitter = new Emitter();
248
263
  _this.onCellContentChangedEmitter = new Emitter();
249
264
  _this.runCellEmitter = new Emitter();
@@ -253,7 +268,19 @@ export var LibroView = (_dec = transient(), _dec2 = view(notebookViewFactoryId),
253
268
  _this.onViewMount = function () {
254
269
  _this.libroService.active = _assertThisInitialized(_this);
255
270
  _this.libroSlotManager.setup(_assertThisInitialized(_this));
256
-
271
+ if (_this.libroViewTracker.isEnabledSpmReporter) {
272
+ _this.libroViewTracker.getOrCreateTrackers({
273
+ id: _this.options.modelId || _this.options.id
274
+ });
275
+ }
276
+ if (_this.model.cells.length > 30 || (_this.options['fileSize'] || 0) / (1024 * 1024) >= 5) {
277
+ message.warning( /*#__PURE__*/_jsxs("div", {
278
+ children: [l10n.t('即将打开的文件(内容过大 / cell 过多),可能会导致操作卡顿,请耐心等待~'), /*#__PURE__*/_jsx(Button, {
279
+ type: "link",
280
+ children: l10n.t('我知道了')
281
+ })]
282
+ }));
283
+ }
257
284
  // this.libroService.libroPerformanceStatistics.setRenderEnd(new Date());
258
285
 
259
286
  // console.log(
@@ -320,16 +347,24 @@ export var LibroView = (_dec = transient(), _dec2 = view(notebookViewFactoryId),
320
347
  };
321
348
  _this.addCell = /*#__PURE__*/function () {
322
349
  var _ref3 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee3(option, position) {
323
- var cellView;
350
+ var id, libroTracker, cellView;
324
351
  return _regeneratorRuntime().wrap(function _callee3$(_context3) {
325
352
  while (1) switch (_context3.prev = _context3.next) {
326
353
  case 0:
327
- _context3.next = 2;
354
+ if (_this.libroViewTracker.isEnabledSpmReporter && option.id) {
355
+ id = option.id + _this.id;
356
+ libroTracker = _this.libroViewTracker.getOrCreateTrackers({
357
+ id: id + 'add'
358
+ });
359
+ libroTracker['extra'].cellsCount = _this.model.cells.length;
360
+ libroTracker['extra'].cellOperation = 'add';
361
+ }
362
+ _context3.next = 3;
328
363
  return _this.getCellViewByOption(option);
329
- case 2:
364
+ case 3:
330
365
  cellView = _context3.sent;
331
366
  _this.model.addCell(cellView, position);
332
- case 4:
367
+ case 5:
333
368
  case "end":
334
369
  return _context3.stop();
335
370
  }
@@ -341,16 +376,24 @@ export var LibroView = (_dec = transient(), _dec2 = view(notebookViewFactoryId),
341
376
  }();
342
377
  _this.addCellAbove = /*#__PURE__*/function () {
343
378
  var _ref4 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee4(option, position) {
344
- var cellView;
379
+ var id, libroTracker, cellView;
345
380
  return _regeneratorRuntime().wrap(function _callee4$(_context4) {
346
381
  while (1) switch (_context4.prev = _context4.next) {
347
382
  case 0:
348
- _context4.next = 2;
383
+ if (_this.libroViewTracker.isEnabledSpmReporter && option.id) {
384
+ id = option.id + _this.id;
385
+ libroTracker = _this.libroViewTracker.getOrCreateTrackers({
386
+ id: id + 'add'
387
+ });
388
+ libroTracker['extra'].cellsCount = _this.model.cells.length;
389
+ libroTracker['extra'].cellOperation = 'add';
390
+ }
391
+ _context4.next = 3;
349
392
  return _this.getCellViewByOption(option);
350
- case 2:
393
+ case 3:
351
394
  cellView = _context4.sent;
352
395
  _this.model.addCell(cellView, position, 'above');
353
- case 4:
396
+ case 5:
354
397
  case "end":
355
398
  return _context4.stop();
356
399
  }
@@ -371,6 +414,14 @@ export var LibroView = (_dec = transient(), _dec2 = view(notebookViewFactoryId),
371
414
  return -1;
372
415
  };
373
416
  _this.deleteCell = function (cell) {
417
+ if (_this.libroViewTracker.isEnabledSpmReporter && cell.model.id) {
418
+ var id = cell.model.id + _this.id;
419
+ var libroTracker = _this.libroViewTracker.getOrCreateTrackers({
420
+ id: id + 'delete'
421
+ });
422
+ libroTracker['extra'].cellsCount = _this.model.cells.length;
423
+ libroTracker['extra'].cellOperation = 'delete';
424
+ }
374
425
  var deleteIndex = _this.model.getCells().findIndex(function (item) {
375
426
  return equals(item, cell);
376
427
  });
@@ -1665,6 +1716,7 @@ export var LibroView = (_dec = transient(), _dec2 = view(notebookViewFactoryId),
1665
1716
  if (_options.id) {
1666
1717
  _this.id = _options.id;
1667
1718
  }
1719
+ _this.options = _options;
1668
1720
  _this.notebookService = notebookService;
1669
1721
  _this.model = _this.notebookService.getOrCreateModel(_options);
1670
1722
  _this.collapseService = collapseServiceFactory({
@@ -2052,31 +2104,36 @@ export var LibroView = (_dec = transient(), _dec2 = view(notebookViewFactoryId),
2052
2104
  enumerable: true,
2053
2105
  writable: true,
2054
2106
  initializer: null
2055
- }), _descriptor6 = _applyDecoratedDescriptor(_class2.prototype, "viewManager", [_dec8], {
2107
+ }), _descriptor6 = _applyDecoratedDescriptor(_class2.prototype, "libroViewTracker", [_dec8], {
2108
+ configurable: true,
2109
+ enumerable: true,
2110
+ writable: true,
2111
+ initializer: null
2112
+ }), _descriptor7 = _applyDecoratedDescriptor(_class2.prototype, "viewManager", [_dec9], {
2056
2113
  configurable: true,
2057
2114
  enumerable: true,
2058
2115
  writable: true,
2059
2116
  initializer: null
2060
- }), _descriptor7 = _applyDecoratedDescriptor(_class2.prototype, "configurationService", [_dec9], {
2117
+ }), _descriptor8 = _applyDecoratedDescriptor(_class2.prototype, "configurationService", [_dec10], {
2061
2118
  configurable: true,
2062
2119
  enumerable: true,
2063
2120
  writable: true,
2064
2121
  initializer: null
2065
- }), _descriptor8 = _applyDecoratedDescriptor(_class2.prototype, "collapserVisible", [_dec10], {
2122
+ }), _descriptor9 = _applyDecoratedDescriptor(_class2.prototype, "collapserVisible", [_dec11], {
2066
2123
  configurable: true,
2067
2124
  enumerable: true,
2068
2125
  writable: true,
2069
2126
  initializer: function initializer() {
2070
2127
  return false;
2071
2128
  }
2072
- }), _descriptor9 = _applyDecoratedDescriptor(_class2.prototype, "outputsScroll", [_dec11], {
2129
+ }), _descriptor10 = _applyDecoratedDescriptor(_class2.prototype, "outputsScroll", [_dec12], {
2073
2130
  configurable: true,
2074
2131
  enumerable: true,
2075
2132
  writable: true,
2076
2133
  initializer: function initializer() {
2077
2134
  return false;
2078
2135
  }
2079
- }), _descriptor10 = _applyDecoratedDescriptor(_class2.prototype, "saving", [_dec12], {
2136
+ }), _descriptor11 = _applyDecoratedDescriptor(_class2.prototype, "saving", [_dec13], {
2080
2137
  configurable: true,
2081
2138
  enumerable: true,
2082
2139
  writable: true,
@@ -4,5 +4,18 @@ type Size = {
4
4
  height: number;
5
5
  };
6
6
  export declare function useSize(ref: RefObject<HTMLDivElement>): Size | undefined;
7
+ interface FrameMetrics {
8
+ timestamp: number;
9
+ fps: number;
10
+ frameTime: number;
11
+ droppedFrames: number;
12
+ }
13
+ export declare const useFrameMonitor: (scrollContainerRef: React.RefObject<HTMLElement>, isEnabledSpmReporter: boolean, onReport?: ((payload: {
14
+ frames: FrameMetrics[];
15
+ summary: any;
16
+ }) => void) | undefined) => {
17
+ frameData: import("react").MutableRefObject<FrameMetrics[]>;
18
+ reportFrames: () => void;
19
+ };
7
20
  export {};
8
21
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAsBvC,KAAK,IAAI,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAC9C,wBAAgB,OAAO,CAAC,GAAG,EAAE,SAAS,CAAC,cAAc,CAAC,GAAG,IAAI,GAAG,SAAS,CAuBxE"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAuBvC,KAAK,IAAI,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAC9C,wBAAgB,OAAO,CAAC,GAAG,EAAE,SAAS,CAAC,cAAc,CAAC,GAAG,IAAI,GAAG,SAAS,CAuBxE;AAED,UAAU,YAAY;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,eAAO,MAAM,eAAe,uBACN,eAAe,CAAC,WAAW,CAAC,wBAC1B,OAAO,wBACR;IAAE,QAAQ,YAAY,EAAE,CAAC;IAAC,OAAO,EAAE,GAAG,CAAA;CAAE,KAAK,IAAI;;;CAiIvE,CAAC"}
package/es/utils/index.js CHANGED
@@ -1,3 +1,7 @@
1
+ function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
2
+ function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
3
+ function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }
4
+ function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
1
5
  function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
2
6
  function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
3
7
  function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
@@ -5,6 +9,7 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
5
9
  function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
6
10
  function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
7
11
  import { useUnmount } from '@difizen/libro-common/app';
12
+ import { useEffect } from 'react';
8
13
  import { useCallback, useLayoutEffect, useRef, useState } from 'react';
9
14
  function useRafState(initialState) {
10
15
  var ref = useRef(0);
@@ -50,4 +55,123 @@ export function useSize(ref) {
50
55
  };
51
56
  }, [ref, setSize]);
52
57
  return size;
53
- }
58
+ }
59
+ export var useFrameMonitor = function useFrameMonitor(scrollContainerRef, isEnabledSpmReporter, onReport) {
60
+ var frameData = useRef([]);
61
+ var lastFrameTime = useRef(performance.now());
62
+ var frameCount = useRef(0);
63
+ var lastScrollPos = useRef(0);
64
+ var rafId = useRef();
65
+ var isMonitoring = useRef(false);
66
+ // const reportTimeout = useRef<NodeJS.Timeout>();
67
+ var intervalId = useRef();
68
+ var scrollDebounceTimer = useRef();
69
+ var stopFrameCapture = useCallback(function () {
70
+ if (rafId.current) {
71
+ cancelAnimationFrame(rafId.current);
72
+ }
73
+ if (intervalId.current) {
74
+ clearInterval(intervalId.current);
75
+ }
76
+ isMonitoring.current = false;
77
+ frameCount.current = 0;
78
+ lastFrameTime.current = performance.now();
79
+ }, []);
80
+ var startFrameCapture = useCallback(function () {
81
+ if (isMonitoring.current) {
82
+ return;
83
+ }
84
+ var calculateFPS = function calculateFPS() {
85
+ if (!isMonitoring.current) {
86
+ return;
87
+ }
88
+ var now = performance.now();
89
+ var delta = now - lastFrameTime.current;
90
+ frameData.current.push({
91
+ timestamp: now,
92
+ fps: Math.round(frameCount.current * 1000 / delta),
93
+ frameTime: delta / frameCount.current,
94
+ droppedFrames: Math.max(0, Math.floor(delta / 16.67) - frameCount.current)
95
+ });
96
+ lastFrameTime.current = now;
97
+ frameCount.current = 0;
98
+ };
99
+ var loop = function loop() {
100
+ if (isMonitoring.current) {
101
+ frameCount.current++;
102
+ rafId.current = requestAnimationFrame(loop);
103
+ }
104
+ };
105
+ isMonitoring.current = true;
106
+ frameCount.current = 0;
107
+ lastFrameTime.current = performance.now();
108
+ if (intervalId.current) {
109
+ clearInterval(intervalId.current);
110
+ }
111
+ intervalId.current = setInterval(calculateFPS, 1500); // 每秒生成一个数据点
112
+ rafId.current = requestAnimationFrame(loop);
113
+ }, []);
114
+ var reportFrames = useCallback(function () {
115
+ if (frameData.current.length === 0) {
116
+ return;
117
+ }
118
+ var send = function send() {
119
+ var payload = {
120
+ frames: frameData.current,
121
+ summary: {
122
+ avgFPS: frameData.current.reduce(function (a, b) {
123
+ return a + b.fps;
124
+ }, 0) / frameData.current.length,
125
+ maxFrameTime: Math.max.apply(Math, _toConsumableArray(frameData.current.map(function (f) {
126
+ return f.frameTime;
127
+ }))),
128
+ totalDropped: frameData.current.reduce(function (a, b) {
129
+ return a + b.droppedFrames;
130
+ }, 0)
131
+ }
132
+ };
133
+ if (onReport) {
134
+ onReport(payload); // 触发外部回调
135
+ }
136
+ frameData.current = [];
137
+ };
138
+ requestIdleCallback(send, {
139
+ timeout: 1000
140
+ }) || setTimeout(send, 0);
141
+ }, [onReport]); // 添加 onReport 依赖
142
+
143
+ useEffect(function () {
144
+ if (!isEnabledSpmReporter) {
145
+ return;
146
+ }
147
+ var container = scrollContainerRef.current || window;
148
+ var handleScroll = function handleScroll() {
149
+ // const currentScroll =
150
+ // (container as Window).scrollY || (container as HTMLElement).scrollTop;
151
+ var currentScroll = container instanceof Window ? container.scrollY : container.scrollTop;
152
+ var scrollDelta = Math.abs(currentScroll - lastScrollPos.current);
153
+ if (scrollDelta > 10) {
154
+ if (!isMonitoring.current) {
155
+ startFrameCapture();
156
+ }
157
+ clearTimeout(scrollDebounceTimer.current);
158
+ scrollDebounceTimer.current = setTimeout(function () {
159
+ stopFrameCapture();
160
+ reportFrames();
161
+ }, 2000);
162
+ }
163
+ lastScrollPos.current = currentScroll;
164
+ };
165
+ container.addEventListener('scroll', handleScroll, {
166
+ passive: true
167
+ });
168
+ return function () {
169
+ container.removeEventListener('scroll', handleScroll);
170
+ stopFrameCapture();
171
+ };
172
+ }, [scrollContainerRef, startFrameCapture, stopFrameCapture, reportFrames, isEnabledSpmReporter]);
173
+ return {
174
+ frameData: frameData,
175
+ reportFrames: reportFrames
176
+ };
177
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@difizen/libro-core",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "",
5
5
  "keywords": [
6
6
  "libro",
@@ -34,10 +34,10 @@
34
34
  ],
35
35
  "dependencies": {
36
36
  "@ant-design/icons": "^5.1.0",
37
- "@difizen/libro-code-editor": "^1.0.0",
38
- "@difizen/libro-common": "^1.0.0",
39
- "@difizen/libro-shared-model": "^1.0.0",
40
- "@difizen/libro-virtualized": "^1.0.0",
37
+ "@difizen/libro-code-editor": "^1.0.2",
38
+ "@difizen/libro-common": "^1.0.2",
39
+ "@difizen/libro-shared-model": "^1.0.2",
40
+ "@difizen/libro-virtualized": "^1.0.2",
41
41
  "classnames": "^2.3.2",
42
42
  "dayjs": "^1.11.10",
43
43
  "dnd-core": "^16.0.1",
@@ -5,6 +5,7 @@ import { contrib, inject, singleton } from '@difizen/libro-common/app';
5
5
 
6
6
  import type { CellView, CellModel, CellOptions } from '../libro-protocol.js';
7
7
  import { LibroService } from '../libro-service.js';
8
+ import { LibroViewTracker } from '../libro-view-tracker.js';
8
9
 
9
10
  import type { CellMeta } from './libro-cell-protocol.js';
10
11
  import {
@@ -24,6 +25,7 @@ export class LibroCellService implements CellService, ApplicationContribution {
24
25
  protected cellTypeToModelContribution: Map<string, CellModelContribution> = new Map();
25
26
  protected readonly viewManager: ViewManager;
26
27
  protected modelCache: Map<string, Map<string, CellModel>> = new Map();
28
+ @inject(LibroViewTracker) libroViewTracker: LibroViewTracker;
27
29
 
28
30
  libroService: LibroService;
29
31
  constructor(
@@ -12,6 +12,7 @@ import type { CellView, NotebookView } from '../libro-protocol.js';
12
12
 
13
13
  import { CellService } from './libro-cell-protocol.js';
14
14
  import type { LibroCell } from './libro-cell-protocol.js';
15
+ import type { LibroCellService } from './libro-cell-service.js';
15
16
  import { ExecutableCellModel } from './libro-executable-cell-model.js';
16
17
 
17
18
  export const LibroCellComponent = React.forwardRef(function LibroCellComponent() {
@@ -83,6 +84,41 @@ export class LibroCellView extends BaseView implements CellView {
83
84
  this.cellWatch();
84
85
  }
85
86
 
87
+ override onViewMount(): void {
88
+ const id = this.options.id + this.parent.id + 'add';
89
+ if (
90
+ (this.cellService as LibroCellService).libroViewTracker.isEnabledSpmReporter &&
91
+ this.options.id &&
92
+ (this.cellService as LibroCellService).libroViewTracker.hasTracker(id)
93
+ ) {
94
+ const cellTracker = (
95
+ this.cellService as LibroCellService
96
+ ).libroViewTracker.getOrCreateTrackers({
97
+ id,
98
+ });
99
+ cellTracker['endTime'] = Date.now();
100
+ cellTracker['extra'].cellType = this.model.type;
101
+ (this.cellService as LibroCellService).libroViewTracker.tracker(cellTracker);
102
+ }
103
+ }
104
+
105
+ override onViewUnmount(): void {
106
+ const id = this.model.id + this.parent.id + 'delete';
107
+ if (
108
+ (this.cellService as LibroCellService).libroViewTracker.isEnabledSpmReporter &&
109
+ (this.cellService as LibroCellService).libroViewTracker.hasTracker(id)
110
+ ) {
111
+ const cellTracker = (
112
+ this.cellService as LibroCellService
113
+ ).libroViewTracker.getOrCreateTrackers({
114
+ id,
115
+ });
116
+ cellTracker['endTime'] = Date.now();
117
+ cellTracker['extra'].cellType = this.model.type;
118
+ (this.cellService as LibroCellService).libroViewTracker.tracker(cellTracker);
119
+ }
120
+ }
121
+
86
122
  cellWatch() {
87
123
  this.toDispose.push(
88
124
  watch(this.model, 'value', () => {
@@ -127,6 +127,30 @@ export abstract class LibroEditorCellView
127
127
  if (e.status === 'ready') {
128
128
  this.editor = this.editorView!.editor;
129
129
  this.afterEditorReady();
130
+ if (this.parent.libroViewTracker.isEnabledSpmReporter) {
131
+ if (
132
+ this.parent.libroViewTracker.hasTracker(
133
+ this.parent.model.options['modelId'] || this.parent.model.options['id'],
134
+ )
135
+ ) {
136
+ const libroTracker = this.parent.libroViewTracker.getOrCreateTrackers({
137
+ id:
138
+ this.parent.model.options['modelId'] || this.parent.model.options['id'],
139
+ });
140
+ libroTracker['endTime'] = Date.now();
141
+ libroTracker['extra'].cellsCount = this.parent.model.cells.length;
142
+ this.parent.libroViewTracker.tracker(libroTracker);
143
+ }
144
+ const id = this.options.id + this.parent.id + 'add';
145
+ if (this.options.id && this.parent.libroViewTracker.hasTracker(id)) {
146
+ const cellTracker = this.parent.libroViewTracker.getOrCreateTrackers({
147
+ id,
148
+ });
149
+ cellTracker['endTime'] = Date.now();
150
+ cellTracker['extra'].cellType = this.model.type;
151
+ this.parent.libroViewTracker.tracker(cellTracker);
152
+ }
153
+ }
130
154
  } else if (e.status === 'disposed') {
131
155
  this.toDisposeOnEditor.dispose();
132
156
  }
@@ -144,6 +168,7 @@ export abstract class LibroEditorCellView
144
168
  };
145
169
 
146
170
  override onViewMount() {
171
+ super.onViewMount();
147
172
  this.createEditor();
148
173
  //选中cell时才focus
149
174
  if (this.parent.model.active?.id === this.id) {
@@ -9,13 +9,19 @@ import {
9
9
  import { equals } from '@difizen/libro-common/app';
10
10
  import { v4 } from 'uuid';
11
11
 
12
- import { LibroCellView, ExecutableCellModel, EditorCellView } from '../cell/index.js';
12
+ import {
13
+ LibroCellView,
14
+ ExecutableCellModel,
15
+ EditorCellView,
16
+ LibroCellService,
17
+ } from '../cell/index.js';
13
18
  import type { LibroEditorCellView } from '../cell/index.js';
14
19
  import { LibroContextKey } from '../libro-context-key.js';
15
20
  import type { LibroModel } from '../libro-model.js';
16
21
  import type { CellView, NotebookView } from '../libro-protocol.js';
17
22
  import { LibroToolbarArea } from '../libro-protocol.js';
18
23
  import { LibroService } from '../libro-service.js';
24
+ import { LibroViewTracker } from '../libro-view-tracker.js';
19
25
  import { LibroView } from '../libro-view.js';
20
26
  import { SettingsModal } from '../settings/settings-modal.js';
21
27
  import { RestartClearOutputModal } from '../toolbar/restart-clear-outputs-modal.js';
@@ -30,7 +36,9 @@ export class LibroCommandContribution implements CommandContribution {
30
36
  @inject(ModalService) protected readonly modalService: ModalService;
31
37
  @inject(LibroCommandRegister) protected readonly libroCommand: LibroCommandRegister;
32
38
  @inject(LibroService) protected readonly libroService: LibroService;
39
+ @inject(LibroCellService) protected readonly cellService: LibroCellService;
33
40
  @inject(LibroContextKey) protected readonly libroContextKey: LibroContextKey;
41
+ @inject(LibroViewTracker) protected libroViewTracker: LibroViewTracker;
34
42
 
35
43
  registerCommands(command: CommandRegistry): void {
36
44
  this.libroCommand.registerLibroCommand(command, NotebookCommands['EnterEditMode'], {
@@ -250,23 +258,31 @@ export class LibroCommandContribution implements CommandContribution {
250
258
  if (!libro || !(libro instanceof LibroView)) {
251
259
  return;
252
260
  }
253
- if (!cell || !(cell instanceof LibroCellView)) {
254
- libro.addCell(
255
- { id: v4(), cell: { cell_type: 'code', source: '', metadata: {} } },
256
- 0,
257
- );
258
- } else {
259
- const cellIndex = libro.model.cells.findIndex((item) => equals(item, cell));
260
- libro.addCell(
261
- {
262
- id: v4(),
263
- cell: { cell_type: cell.model.type, source: '', metadata: {} },
264
- },
265
- cellIndex + 1,
266
- );
261
+ const createNewCell = (cellType: string) => ({
262
+ id: v4(),
263
+ cell: { cell_type: cellType, source: '', metadata: {} },
264
+ });
265
+
266
+ const newCell =
267
+ !cell || !(cell instanceof LibroCellView)
268
+ ? createNewCell('code')
269
+ : createNewCell(cell.model.type);
270
+
271
+ const insertIndex =
272
+ !cell || !(cell instanceof LibroCellView)
273
+ ? 0
274
+ : libro.model.cells.findIndex((item) => equals(item, cell)) + 1;
275
+
276
+ libro.addCell(newCell, insertIndex);
277
+ if (this.libroViewTracker.isEnabledSpmReporter) {
278
+ const id = newCell.id + libro.id;
279
+ const libroTracker = this.libroViewTracker.getOrCreateTrackers({
280
+ id,
281
+ });
282
+ libroTracker['extra'].cellsCount = libro.model.cells.length;
283
+ libroTracker['extra'].cellOperation = 'add';
267
284
  }
268
285
  },
269
- // isVisible: () => false,
270
286
  isVisible: (cell, libro, path) => {
271
287
  if (!libro || !(libro instanceof LibroView)) {
272
288
  return false;
@@ -296,13 +312,11 @@ export class LibroCommandContribution implements CommandContribution {
296
312
  }
297
313
  const cellIndex = libro.model.cells.findIndex((item) => equals(item, cell));
298
314
  if (cellIndex > -1) {
299
- libro.addCellAbove(
300
- {
301
- id: v4(),
302
- cell: { cell_type: cell.model.type, source: '', metadata: {} },
303
- },
304
- cellIndex,
305
- );
315
+ const cellOptions = {
316
+ id: v4(),
317
+ cell: { cell_type: cell.model.type, source: '', metadata: {} },
318
+ };
319
+ libro.addCellAbove(cellOptions, cellIndex);
306
320
  }
307
321
  },
308
322
  isEnabled: (cell, libro) => {
package/src/index.less CHANGED
@@ -89,7 +89,7 @@
89
89
  border-bottom: 1px solid var(--mana-libro-toptoolbar-border-color);
90
90
 
91
91
  .libro-header-left {
92
- width: 240px;
92
+ width: 300px;
93
93
  flex-shrink: 0;
94
94
 
95
95
  .mana-toolbar {
@@ -39,9 +39,6 @@ export interface NotebookOption extends Options {
39
39
  [key: string]: any;
40
40
  }
41
41
 
42
- export const PerformaceStatisticOption = Symbol('PerformaceStatisticOption');
43
- export type PerformaceStatisticOption = Options;
44
-
45
42
  export const ModelFactory = Symbol('ModelFactory');
46
43
  export type ModelFactory<T = NotebookOption> = (options: T) => NotebookModel;
47
44
 
@@ -58,6 +55,12 @@ export type Options = {
58
55
  [key: string]: any;
59
56
  };
60
57
 
58
+ export interface ITracker {
59
+ id: string;
60
+ [key: string]: any;
61
+ log: () => Record<string, any>;
62
+ }
63
+
61
64
  export interface ScrollParams {
62
65
  cellIndex: number;
63
66
  cellOffset?: number;