@tldraw/editor 5.4.0-next.ef99ab47e5ce → 5.5.0-canary.078a77321dc3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist-cjs/index.d.ts +119 -49
- package/dist-cjs/index.js +4 -1
- package/dist-cjs/index.js.map +2 -2
- package/dist-cjs/lib/TldrawEditor.js +7 -2
- package/dist-cjs/lib/TldrawEditor.js.map +2 -2
- package/dist-cjs/lib/components/MenuClickCapture.js +6 -8
- package/dist-cjs/lib/components/MenuClickCapture.js.map +2 -2
- package/dist-cjs/lib/components/default-components/CanvasOverlays.js +1 -3
- package/dist-cjs/lib/components/default-components/CanvasOverlays.js.map +2 -2
- package/dist-cjs/lib/components/default-components/DefaultErrorFallback.js +1 -1
- package/dist-cjs/lib/components/default-components/DefaultErrorFallback.js.map +1 -1
- package/dist-cjs/lib/config/TLUserPreferences.js +6 -2
- package/dist-cjs/lib/config/TLUserPreferences.js.map +2 -2
- package/dist-cjs/lib/config/createTLStore.js +1 -1
- package/dist-cjs/lib/config/createTLStore.js.map +2 -2
- package/dist-cjs/lib/constants.js +2 -0
- package/dist-cjs/lib/constants.js.map +2 -2
- package/dist-cjs/lib/editor/Editor.js +190 -300
- package/dist-cjs/lib/editor/Editor.js.map +2 -2
- package/dist-cjs/lib/editor/derivations/shapeIdsInCurrentPage.js +7 -3
- package/dist-cjs/lib/editor/derivations/shapeIdsInCurrentPage.js.map +2 -2
- package/dist-cjs/lib/editor/managers/ClickManager/ClickManager.js +3 -3
- package/dist-cjs/lib/editor/managers/ClickManager/ClickManager.js.map +2 -2
- package/dist-cjs/lib/editor/managers/CollaboratorsManager/CollaboratorsManager.js +8 -8
- package/dist-cjs/lib/editor/managers/CollaboratorsManager/CollaboratorsManager.js.map +2 -2
- package/dist-cjs/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.js +10 -6
- package/dist-cjs/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.js.map +2 -2
- package/dist-cjs/lib/editor/managers/FontManager/FontManager.js +2 -1
- package/dist-cjs/lib/editor/managers/FontManager/FontManager.js.map +2 -2
- package/dist-cjs/lib/editor/managers/InputsManager/InputsManager.js +79 -6
- package/dist-cjs/lib/editor/managers/InputsManager/InputsManager.js.map +2 -2
- package/dist-cjs/lib/editor/managers/ScribbleManager/ScribbleManager.js +7 -0
- package/dist-cjs/lib/editor/managers/ScribbleManager/ScribbleManager.js.map +2 -2
- package/dist-cjs/lib/editor/managers/SnapManager/BoundsSnaps.js +0 -2
- package/dist-cjs/lib/editor/managers/SnapManager/BoundsSnaps.js.map +2 -2
- package/dist-cjs/lib/editor/managers/TextManager/TextManager.js +1 -2
- package/dist-cjs/lib/editor/managers/TextManager/TextManager.js.map +2 -2
- package/dist-cjs/lib/editor/managers/ThemeManager/ThemeManager.js +7 -3
- package/dist-cjs/lib/editor/managers/ThemeManager/ThemeManager.js.map +2 -2
- package/dist-cjs/lib/editor/managers/TickManager/TickManager.js +6 -3
- package/dist-cjs/lib/editor/managers/TickManager/TickManager.js.map +2 -2
- package/dist-cjs/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.js +12 -1
- package/dist-cjs/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.js.map +2 -2
- package/dist-cjs/lib/editor/overlays/OverlayManager.js +3 -7
- package/dist-cjs/lib/editor/overlays/OverlayManager.js.map +2 -2
- package/dist-cjs/lib/editor/overlays/strokeShapeIndicators.js +0 -1
- package/dist-cjs/lib/editor/overlays/strokeShapeIndicators.js.map +2 -2
- package/dist-cjs/lib/editor/shapes/BaseFrameLikeShapeUtil.js +3 -1
- package/dist-cjs/lib/editor/shapes/BaseFrameLikeShapeUtil.js.map +2 -2
- package/dist-cjs/lib/editor/shapes/shared/getPerfectDashProps.js +1 -0
- package/dist-cjs/lib/editor/shapes/shared/getPerfectDashProps.js.map +2 -2
- package/dist-cjs/lib/editor/tools/BaseBoxShapeTool/children/Pointing.js +1 -1
- package/dist-cjs/lib/editor/tools/BaseBoxShapeTool/children/Pointing.js.map +2 -2
- package/dist-cjs/lib/editor/tools/StateNode.js +3 -2
- package/dist-cjs/lib/editor/tools/StateNode.js.map +2 -2
- package/dist-cjs/lib/globals/editors.js +57 -0
- package/dist-cjs/lib/globals/editors.js.map +7 -0
- package/dist-cjs/lib/globals/menus.js +9 -4
- package/dist-cjs/lib/globals/menus.js.map +2 -2
- package/dist-cjs/lib/hooks/useCanvasEvents.js +2 -0
- package/dist-cjs/lib/hooks/useCanvasEvents.js.map +2 -2
- package/dist-cjs/lib/hooks/useDocumentEvents.js +39 -9
- package/dist-cjs/lib/hooks/useDocumentEvents.js.map +2 -2
- package/dist-cjs/lib/hooks/useLocalStore.js +10 -6
- package/dist-cjs/lib/hooks/useLocalStore.js.map +2 -2
- package/dist-cjs/lib/hooks/usePassThroughWheelEvents.js +1 -0
- package/dist-cjs/lib/hooks/usePassThroughWheelEvents.js.map +2 -2
- package/dist-cjs/lib/hooks/usePeerIds.js +2 -1
- package/dist-cjs/lib/hooks/usePeerIds.js.map +2 -2
- package/dist-cjs/lib/license/LicenseManager.js +9 -2
- package/dist-cjs/lib/license/LicenseManager.js.map +2 -2
- package/dist-cjs/lib/license/LicenseProvider.js +16 -3
- package/dist-cjs/lib/license/LicenseProvider.js.map +2 -2
- package/dist-cjs/lib/license/useLicenseManagerState.js +5 -4
- package/dist-cjs/lib/license/useLicenseManagerState.js.map +2 -2
- package/dist-cjs/lib/primitives/Box.js +2 -1
- package/dist-cjs/lib/primitives/Box.js.map +2 -2
- package/dist-cjs/lib/primitives/Vec.js +4 -3
- package/dist-cjs/lib/primitives/Vec.js.map +2 -2
- package/dist-cjs/lib/primitives/geometry/Arc2d.js +1 -1
- package/dist-cjs/lib/primitives/geometry/Arc2d.js.map +2 -2
- package/dist-cjs/lib/primitives/geometry/CubicBezier2d.js +1 -1
- package/dist-cjs/lib/primitives/geometry/CubicBezier2d.js.map +2 -2
- package/dist-cjs/lib/primitives/geometry/Edge2d.js +1 -1
- package/dist-cjs/lib/primitives/geometry/Edge2d.js.map +2 -2
- package/dist-cjs/lib/primitives/geometry/Group2d.js +71 -26
- package/dist-cjs/lib/primitives/geometry/Group2d.js.map +2 -2
- package/dist-cjs/lib/primitives/geometry/Point2d.js +1 -1
- package/dist-cjs/lib/primitives/geometry/Point2d.js.map +2 -2
- package/dist-cjs/lib/primitives/utils.js +2 -1
- package/dist-cjs/lib/primitives/utils.js.map +2 -2
- package/dist-cjs/lib/utils/deepLinks.js +5 -1
- package/dist-cjs/lib/utils/deepLinks.js.map +2 -2
- package/dist-cjs/lib/utils/normalizeWheel.js +2 -0
- package/dist-cjs/lib/utils/normalizeWheel.js.map +2 -2
- package/dist-cjs/lib/utils/rotation.js +1 -9
- package/dist-cjs/lib/utils/rotation.js.map +2 -2
- package/dist-cjs/lib/utils/sync/TLLocalSyncClient.js +17 -0
- package/dist-cjs/lib/utils/sync/TLLocalSyncClient.js.map +2 -2
- package/dist-cjs/lib/utils/sync/alerts.js +1 -1
- package/dist-cjs/lib/utils/sync/alerts.js.map +1 -1
- package/dist-cjs/version.js +3 -3
- package/dist-cjs/version.js.map +1 -1
- package/dist-esm/index.d.mts +119 -49
- package/dist-esm/index.mjs +9 -2
- package/dist-esm/index.mjs.map +2 -2
- package/dist-esm/lib/TldrawEditor.mjs +9 -4
- package/dist-esm/lib/TldrawEditor.mjs.map +2 -2
- package/dist-esm/lib/components/MenuClickCapture.mjs +6 -8
- package/dist-esm/lib/components/MenuClickCapture.mjs.map +2 -2
- package/dist-esm/lib/components/default-components/CanvasOverlays.mjs +1 -3
- package/dist-esm/lib/components/default-components/CanvasOverlays.mjs.map +2 -2
- package/dist-esm/lib/components/default-components/DefaultErrorFallback.mjs +1 -1
- package/dist-esm/lib/components/default-components/DefaultErrorFallback.mjs.map +1 -1
- package/dist-esm/lib/config/TLUserPreferences.mjs +6 -2
- package/dist-esm/lib/config/TLUserPreferences.mjs.map +2 -2
- package/dist-esm/lib/config/createTLStore.mjs +1 -1
- package/dist-esm/lib/config/createTLStore.mjs.map +2 -2
- package/dist-esm/lib/constants.mjs +2 -0
- package/dist-esm/lib/constants.mjs.map +2 -2
- package/dist-esm/lib/editor/Editor.mjs +199 -301
- package/dist-esm/lib/editor/Editor.mjs.map +2 -2
- package/dist-esm/lib/editor/derivations/shapeIdsInCurrentPage.mjs +7 -3
- package/dist-esm/lib/editor/derivations/shapeIdsInCurrentPage.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/ClickManager/ClickManager.mjs +3 -3
- package/dist-esm/lib/editor/managers/ClickManager/ClickManager.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/CollaboratorsManager/CollaboratorsManager.mjs +9 -9
- package/dist-esm/lib/editor/managers/CollaboratorsManager/CollaboratorsManager.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.mjs +10 -6
- package/dist-esm/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/FontManager/FontManager.mjs +2 -1
- package/dist-esm/lib/editor/managers/FontManager/FontManager.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/InputsManager/InputsManager.mjs +81 -8
- package/dist-esm/lib/editor/managers/InputsManager/InputsManager.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/ScribbleManager/ScribbleManager.mjs +7 -0
- package/dist-esm/lib/editor/managers/ScribbleManager/ScribbleManager.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/SnapManager/BoundsSnaps.mjs +0 -2
- package/dist-esm/lib/editor/managers/SnapManager/BoundsSnaps.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/TextManager/TextManager.mjs +2 -3
- package/dist-esm/lib/editor/managers/TextManager/TextManager.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/ThemeManager/ThemeManager.mjs +7 -3
- package/dist-esm/lib/editor/managers/ThemeManager/ThemeManager.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/TickManager/TickManager.mjs +6 -3
- package/dist-esm/lib/editor/managers/TickManager/TickManager.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.mjs +12 -1
- package/dist-esm/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.mjs.map +2 -2
- package/dist-esm/lib/editor/overlays/OverlayManager.mjs +3 -7
- package/dist-esm/lib/editor/overlays/OverlayManager.mjs.map +2 -2
- package/dist-esm/lib/editor/overlays/strokeShapeIndicators.mjs +0 -1
- package/dist-esm/lib/editor/overlays/strokeShapeIndicators.mjs.map +2 -2
- package/dist-esm/lib/editor/shapes/BaseFrameLikeShapeUtil.mjs +3 -1
- package/dist-esm/lib/editor/shapes/BaseFrameLikeShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/editor/shapes/shared/getPerfectDashProps.mjs +1 -0
- package/dist-esm/lib/editor/shapes/shared/getPerfectDashProps.mjs.map +2 -2
- package/dist-esm/lib/editor/tools/BaseBoxShapeTool/children/Pointing.mjs +1 -1
- package/dist-esm/lib/editor/tools/BaseBoxShapeTool/children/Pointing.mjs.map +2 -2
- package/dist-esm/lib/editor/tools/StateNode.mjs +3 -2
- package/dist-esm/lib/editor/tools/StateNode.mjs.map +2 -2
- package/dist-esm/lib/globals/editors.mjs +37 -0
- package/dist-esm/lib/globals/editors.mjs.map +7 -0
- package/dist-esm/lib/globals/menus.mjs +9 -4
- package/dist-esm/lib/globals/menus.mjs.map +2 -2
- package/dist-esm/lib/hooks/useCanvasEvents.mjs +2 -0
- package/dist-esm/lib/hooks/useCanvasEvents.mjs.map +2 -2
- package/dist-esm/lib/hooks/useDocumentEvents.mjs +40 -10
- package/dist-esm/lib/hooks/useDocumentEvents.mjs.map +2 -2
- package/dist-esm/lib/hooks/useLocalStore.mjs +11 -7
- package/dist-esm/lib/hooks/useLocalStore.mjs.map +2 -2
- package/dist-esm/lib/hooks/usePassThroughWheelEvents.mjs +1 -0
- package/dist-esm/lib/hooks/usePassThroughWheelEvents.mjs.map +2 -2
- package/dist-esm/lib/hooks/usePeerIds.mjs +2 -1
- package/dist-esm/lib/hooks/usePeerIds.mjs.map +2 -2
- package/dist-esm/lib/license/LicenseManager.mjs +9 -2
- package/dist-esm/lib/license/LicenseManager.mjs.map +2 -2
- package/dist-esm/lib/license/LicenseProvider.mjs +16 -3
- package/dist-esm/lib/license/LicenseProvider.mjs.map +2 -2
- package/dist-esm/lib/license/useLicenseManagerState.mjs +5 -4
- package/dist-esm/lib/license/useLicenseManagerState.mjs.map +2 -2
- package/dist-esm/lib/primitives/Box.mjs +2 -1
- package/dist-esm/lib/primitives/Box.mjs.map +2 -2
- package/dist-esm/lib/primitives/Vec.mjs +4 -3
- package/dist-esm/lib/primitives/Vec.mjs.map +2 -2
- package/dist-esm/lib/primitives/geometry/Arc2d.mjs +1 -1
- package/dist-esm/lib/primitives/geometry/Arc2d.mjs.map +2 -2
- package/dist-esm/lib/primitives/geometry/CubicBezier2d.mjs +1 -1
- package/dist-esm/lib/primitives/geometry/CubicBezier2d.mjs.map +2 -2
- package/dist-esm/lib/primitives/geometry/Edge2d.mjs +1 -1
- package/dist-esm/lib/primitives/geometry/Edge2d.mjs.map +2 -2
- package/dist-esm/lib/primitives/geometry/Group2d.mjs +75 -27
- package/dist-esm/lib/primitives/geometry/Group2d.mjs.map +2 -2
- package/dist-esm/lib/primitives/geometry/Point2d.mjs +1 -1
- package/dist-esm/lib/primitives/geometry/Point2d.mjs.map +2 -2
- package/dist-esm/lib/primitives/utils.mjs +2 -1
- package/dist-esm/lib/primitives/utils.mjs.map +2 -2
- package/dist-esm/lib/utils/deepLinks.mjs +5 -1
- package/dist-esm/lib/utils/deepLinks.mjs.map +2 -2
- package/dist-esm/lib/utils/normalizeWheel.mjs +2 -0
- package/dist-esm/lib/utils/normalizeWheel.mjs.map +2 -2
- package/dist-esm/lib/utils/rotation.mjs +1 -9
- package/dist-esm/lib/utils/rotation.mjs.map +2 -2
- package/dist-esm/lib/utils/sync/TLLocalSyncClient.mjs +17 -0
- package/dist-esm/lib/utils/sync/TLLocalSyncClient.mjs.map +2 -2
- package/dist-esm/lib/utils/sync/alerts.mjs +1 -1
- package/dist-esm/lib/utils/sync/alerts.mjs.map +1 -1
- package/dist-esm/version.mjs +3 -3
- package/dist-esm/version.mjs.map +1 -1
- package/package.json +13 -7
- package/src/index.ts +6 -1
- package/src/lib/TldrawEditor.tsx +16 -4
- package/src/lib/components/MenuClickCapture.tsx +19 -18
- package/src/lib/components/default-components/CanvasOverlays.tsx +1 -3
- package/src/lib/components/default-components/DefaultErrorFallback.tsx +1 -1
- package/src/lib/config/TLUserPreferences.test.ts +18 -1
- package/src/lib/config/TLUserPreferences.ts +8 -4
- package/src/lib/config/createTLStore.ts +1 -1
- package/src/lib/constants.ts +8 -0
- package/src/lib/editor/Editor.ts +285 -392
- package/src/lib/editor/derivations/shapeIdsInCurrentPage.ts +7 -3
- package/src/lib/editor/managers/ClickManager/ClickManager.ts +5 -3
- package/src/lib/editor/managers/CollaboratorsManager/CollaboratorsManager.ts +9 -9
- package/src/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.test.ts +35 -4
- package/src/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.ts +13 -7
- package/src/lib/editor/managers/FontManager/FontManager.ts +2 -1
- package/src/lib/editor/managers/InputsManager/InputsManager.test.ts +199 -3
- package/src/lib/editor/managers/InputsManager/InputsManager.ts +128 -9
- package/src/lib/editor/managers/ScribbleManager/ScribbleManager.ts +12 -1
- package/src/lib/editor/managers/SnapManager/BoundsSnaps.ts +0 -2
- package/src/lib/editor/managers/TextManager/TextManager.ts +2 -6
- package/src/lib/editor/managers/ThemeManager/ThemeManager.test.ts +53 -0
- package/src/lib/editor/managers/ThemeManager/ThemeManager.ts +9 -3
- package/src/lib/editor/managers/TickManager/TickManager.test.ts +13 -0
- package/src/lib/editor/managers/TickManager/TickManager.ts +9 -3
- package/src/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.test.ts +64 -3
- package/src/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.ts +18 -1
- package/src/lib/editor/overlays/OverlayManager.ts +3 -7
- package/src/lib/editor/overlays/strokeShapeIndicators.ts +0 -1
- package/src/lib/editor/shapes/BaseFrameLikeShapeUtil.tsx +5 -1
- package/src/lib/editor/shapes/shared/getPerfectDashProps.ts +3 -0
- package/src/lib/editor/tools/BaseBoxShapeTool/children/Pointing.ts +4 -1
- package/src/lib/editor/tools/StateNode.test.ts +64 -0
- package/src/lib/editor/tools/StateNode.ts +12 -2
- package/src/lib/globals/editors.test.ts +76 -0
- package/src/lib/globals/editors.ts +53 -0
- package/src/lib/globals/menus.test.ts +33 -0
- package/src/lib/globals/menus.ts +11 -4
- package/src/lib/hooks/useCanvasEvents.ts +2 -0
- package/src/lib/hooks/useDocumentEvents.ts +60 -16
- package/src/lib/hooks/useLocalStore.ts +16 -8
- package/src/lib/hooks/usePassThroughWheelEvents.ts +3 -0
- package/src/lib/hooks/usePeerIds.ts +2 -1
- package/src/lib/license/LicenseManager.test.ts +160 -0
- package/src/lib/license/LicenseManager.ts +13 -4
- package/src/lib/license/LicenseProvider.tsx +24 -3
- package/src/lib/license/useLicenseManagerState.ts +8 -6
- package/src/lib/primitives/Box.test.ts +9 -1
- package/src/lib/primitives/Box.ts +3 -1
- package/src/lib/primitives/Vec.test.ts +10 -0
- package/src/lib/primitives/Vec.ts +4 -4
- package/src/lib/primitives/geometry/Arc2d.test.ts +235 -3
- package/src/lib/primitives/geometry/Arc2d.ts +1 -1
- package/src/lib/primitives/geometry/CubicBezier2d.test.ts +186 -3
- package/src/lib/primitives/geometry/CubicBezier2d.ts +1 -1
- package/src/lib/primitives/geometry/CubicSpline2d.test.ts +160 -3
- package/src/lib/primitives/geometry/Edge2d.test.ts +21 -3
- package/src/lib/primitives/geometry/Edge2d.ts +1 -1
- package/src/lib/primitives/geometry/Ellipse2d.test.ts +243 -3
- package/src/lib/primitives/geometry/Geometry2d.test.ts +553 -1
- package/src/lib/primitives/geometry/Group2d.test.ts +419 -3
- package/src/lib/primitives/geometry/Group2d.ts +81 -34
- package/src/lib/primitives/geometry/Point2d.test.ts +14 -3
- package/src/lib/primitives/geometry/Point2d.ts +1 -1
- package/src/lib/primitives/geometry/Polyline2d.test.ts +207 -0
- package/src/lib/primitives/geometry/Stadium2d.test.ts +191 -3
- package/src/lib/primitives/utils.test.ts +10 -1
- package/src/lib/primitives/utils.ts +4 -1
- package/src/lib/test/useCanvasEvents.test.tsx +74 -0
- package/src/lib/test/useDocumentEvents.test.tsx +107 -0
- package/src/lib/test/usePassThroughWheelEvents.test.tsx +25 -2
- package/src/lib/utils/deepLinks.test.ts +15 -0
- package/src/lib/utils/deepLinks.ts +7 -1
- package/src/lib/utils/normalizeWheel.test.ts +39 -0
- package/src/lib/utils/normalizeWheel.ts +6 -0
- package/src/lib/utils/rotation.ts +4 -12
- package/src/lib/utils/sync/TLLocalSyncClient.test.ts +56 -0
- package/src/lib/utils/sync/TLLocalSyncClient.ts +24 -0
- package/src/lib/utils/sync/alerts.ts +1 -1
- package/src/version.ts +3 -3
- package/src/lib/primitives/geometry/Polyline.test.ts +0 -5
|
@@ -38,9 +38,13 @@ function deriveShapeIdsInCurrentPage(store, getCurrentPageId) {
|
|
|
38
38
|
function fromScratch() {
|
|
39
39
|
const currentPageId = getCurrentPageId();
|
|
40
40
|
lastPageId = currentPageId;
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
41
|
+
const result = /* @__PURE__ */ new Set();
|
|
42
|
+
for (const id of shapesIndex.get()) {
|
|
43
|
+
if (isShapeInPage(store, currentPageId, store.get(id))) {
|
|
44
|
+
result.add(id);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return result;
|
|
44
48
|
}
|
|
45
49
|
return (0, import_state.computed)("_shapeIdsInCurrentPage", (prevValue, lastComputedEpoch) => {
|
|
46
50
|
if ((0, import_state.isUninitialized)(prevValue)) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/lib/editor/derivations/shapeIdsInCurrentPage.ts"],
|
|
4
|
-
"sourcesContent": ["import { computed, isUninitialized, RESET_VALUE, withDiff } from '@tldraw/state'\nimport { IncrementalSetConstructor } from '@tldraw/store'\nimport {\n\tisPageId,\n\tisShape,\n\tisShapeId,\n\tTLPageId,\n\tTLShape,\n\tTLShapeId,\n\tTLStore,\n} from '@tldraw/tlschema'\n\n/**\n * Get whether a shape is in the current page.\n *\n * @param store - The tldraw store.\n * @param pageId - The id of the page to check.\n * @param shape - The the shape to check.\n */\nconst isShapeInPage = (store: TLStore, pageId: TLPageId, shape: TLShape): boolean => {\n\twhile (!isPageId(shape.parentId)) {\n\t\tconst parent = store.get(shape.parentId)\n\t\tif (!parent) return false\n\t\tshape = parent\n\t}\n\n\treturn shape.parentId === pageId\n}\n\n/**\n * A derivation that returns a list of shape ids in the current page.\n *\n * @param store - The tldraw store.\n * @param getCurrentPageId - A function that returns the current page id.\n */\nexport function deriveShapeIdsInCurrentPage(store: TLStore, getCurrentPageId: () => TLPageId) {\n\tconst shapesIndex = store.query.ids('shape')\n\tlet lastPageId: null | TLPageId = null\n\tfunction fromScratch() {\n\t\tconst currentPageId = getCurrentPageId()\n\t\tlastPageId = currentPageId\n\t\
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAAiE;AACjE,mBAA0C;AAC1C,sBAQO;AASP,MAAM,gBAAgB,CAAC,OAAgB,QAAkB,UAA4B;AACpF,SAAO,KAAC,0BAAS,MAAM,QAAQ,GAAG;AACjC,UAAM,SAAS,MAAM,IAAI,MAAM,QAAQ;AACvC,QAAI,CAAC,OAAQ,QAAO;AACpB,YAAQ;AAAA,EACT;AAEA,SAAO,MAAM,aAAa;AAC3B;AAQO,SAAS,4BAA4B,OAAgB,kBAAkC;AAC7F,QAAM,cAAc,MAAM,MAAM,IAAI,OAAO;AAC3C,MAAI,aAA8B;AAClC,WAAS,cAAc;AACtB,UAAM,gBAAgB,iBAAiB;AACvC,iBAAa;AACb,
|
|
4
|
+
"sourcesContent": ["import { computed, isUninitialized, RESET_VALUE, withDiff } from '@tldraw/state'\nimport { IncrementalSetConstructor } from '@tldraw/store'\nimport {\n\tisPageId,\n\tisShape,\n\tisShapeId,\n\tTLPageId,\n\tTLShape,\n\tTLShapeId,\n\tTLStore,\n} from '@tldraw/tlschema'\n\n/**\n * Get whether a shape is in the current page.\n *\n * @param store - The tldraw store.\n * @param pageId - The id of the page to check.\n * @param shape - The the shape to check.\n */\nconst isShapeInPage = (store: TLStore, pageId: TLPageId, shape: TLShape): boolean => {\n\twhile (!isPageId(shape.parentId)) {\n\t\tconst parent = store.get(shape.parentId)\n\t\tif (!parent) return false\n\t\tshape = parent\n\t}\n\n\treturn shape.parentId === pageId\n}\n\n/**\n * A derivation that returns a list of shape ids in the current page.\n *\n * @param store - The tldraw store.\n * @param getCurrentPageId - A function that returns the current page id.\n */\nexport function deriveShapeIdsInCurrentPage(store: TLStore, getCurrentPageId: () => TLPageId) {\n\tconst shapesIndex = store.query.ids('shape')\n\tlet lastPageId: null | TLPageId = null\n\tfunction fromScratch() {\n\t\tconst currentPageId = getCurrentPageId()\n\t\tlastPageId = currentPageId\n\t\tconst result = new Set<TLShapeId>()\n\t\tfor (const id of shapesIndex.get()) {\n\t\t\tif (isShapeInPage(store, currentPageId, store.get(id)!)) {\n\t\t\t\tresult.add(id)\n\t\t\t}\n\t\t}\n\t\treturn result\n\t}\n\treturn computed<Set<TLShapeId>>('_shapeIdsInCurrentPage', (prevValue, lastComputedEpoch) => {\n\t\tif (isUninitialized(prevValue)) {\n\t\t\treturn fromScratch()\n\t\t}\n\n\t\tconst currentPageId = getCurrentPageId()\n\n\t\tif (currentPageId !== lastPageId) {\n\t\t\treturn fromScratch()\n\t\t}\n\n\t\tconst diff = store.history.getDiffSince(lastComputedEpoch)\n\n\t\tif (diff === RESET_VALUE) {\n\t\t\treturn fromScratch()\n\t\t}\n\n\t\tconst builder = new IncrementalSetConstructor<TLShapeId>(\n\t\t\tprevValue\n\t\t) as IncrementalSetConstructor<TLShapeId>\n\n\t\tfor (const changes of diff) {\n\t\t\tfor (const record of Object.values(changes.added)) {\n\t\t\t\tif (isShape(record) && isShapeInPage(store, currentPageId, record)) {\n\t\t\t\t\tbuilder.add(record.id)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor (const [_from, to] of Object.values(changes.updated)) {\n\t\t\t\tif (isShape(to)) {\n\t\t\t\t\tif (isShapeInPage(store, currentPageId, to)) {\n\t\t\t\t\t\tbuilder.add(to.id)\n\t\t\t\t\t} else {\n\t\t\t\t\t\tbuilder.remove(to.id)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor (const id of Object.keys(changes.removed)) {\n\t\t\t\tif (isShapeId(id)) {\n\t\t\t\t\tbuilder.remove(id)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tconst result = builder.get()\n\t\tif (!result) {\n\t\t\treturn prevValue\n\t\t}\n\n\t\treturn withDiff(result.value, result.diff)\n\t})\n}\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAAiE;AACjE,mBAA0C;AAC1C,sBAQO;AASP,MAAM,gBAAgB,CAAC,OAAgB,QAAkB,UAA4B;AACpF,SAAO,KAAC,0BAAS,MAAM,QAAQ,GAAG;AACjC,UAAM,SAAS,MAAM,IAAI,MAAM,QAAQ;AACvC,QAAI,CAAC,OAAQ,QAAO;AACpB,YAAQ;AAAA,EACT;AAEA,SAAO,MAAM,aAAa;AAC3B;AAQO,SAAS,4BAA4B,OAAgB,kBAAkC;AAC7F,QAAM,cAAc,MAAM,MAAM,IAAI,OAAO;AAC3C,MAAI,aAA8B;AAClC,WAAS,cAAc;AACtB,UAAM,gBAAgB,iBAAiB;AACvC,iBAAa;AACb,UAAM,SAAS,oBAAI,IAAe;AAClC,eAAW,MAAM,YAAY,IAAI,GAAG;AACnC,UAAI,cAAc,OAAO,eAAe,MAAM,IAAI,EAAE,CAAE,GAAG;AACxD,eAAO,IAAI,EAAE;AAAA,MACd;AAAA,IACD;AACA,WAAO;AAAA,EACR;AACA,aAAO,uBAAyB,0BAA0B,CAAC,WAAW,sBAAsB;AAC3F,YAAI,8BAAgB,SAAS,GAAG;AAC/B,aAAO,YAAY;AAAA,IACpB;AAEA,UAAM,gBAAgB,iBAAiB;AAEvC,QAAI,kBAAkB,YAAY;AACjC,aAAO,YAAY;AAAA,IACpB;AAEA,UAAM,OAAO,MAAM,QAAQ,aAAa,iBAAiB;AAEzD,QAAI,SAAS,0BAAa;AACzB,aAAO,YAAY;AAAA,IACpB;AAEA,UAAM,UAAU,IAAI;AAAA,MACnB;AAAA,IACD;AAEA,eAAW,WAAW,MAAM;AAC3B,iBAAW,UAAU,OAAO,OAAO,QAAQ,KAAK,GAAG;AAClD,gBAAI,yBAAQ,MAAM,KAAK,cAAc,OAAO,eAAe,MAAM,GAAG;AACnE,kBAAQ,IAAI,OAAO,EAAE;AAAA,QACtB;AAAA,MACD;AAEA,iBAAW,CAAC,OAAO,EAAE,KAAK,OAAO,OAAO,QAAQ,OAAO,GAAG;AACzD,gBAAI,yBAAQ,EAAE,GAAG;AAChB,cAAI,cAAc,OAAO,eAAe,EAAE,GAAG;AAC5C,oBAAQ,IAAI,GAAG,EAAE;AAAA,UAClB,OAAO;AACN,oBAAQ,OAAO,GAAG,EAAE;AAAA,UACrB;AAAA,QACD;AAAA,MACD;AAEA,iBAAW,MAAM,OAAO,KAAK,QAAQ,OAAO,GAAG;AAC9C,gBAAI,2BAAU,EAAE,GAAG;AAClB,kBAAQ,OAAO,EAAE;AAAA,QAClB;AAAA,MACD;AAAA,IACD;AAEA,UAAM,SAAS,QAAQ,IAAI;AAC3B,QAAI,CAAC,QAAQ;AACZ,aAAO;AAAA,IACR;AAEA,eAAO,uBAAS,OAAO,OAAO,OAAO,IAAI;AAAA,EAC1C,CAAC;AACF;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -97,7 +97,7 @@ class ClickManager {
|
|
|
97
97
|
switch (this._clickState) {
|
|
98
98
|
case "pendingDouble": {
|
|
99
99
|
this._clickState = "pendingOverflow";
|
|
100
|
-
this.
|
|
100
|
+
this._getClickTimeout(this._clickState);
|
|
101
101
|
return {
|
|
102
102
|
...info,
|
|
103
103
|
type: "click",
|
|
@@ -116,7 +116,7 @@ class ClickManager {
|
|
|
116
116
|
default: {
|
|
117
117
|
}
|
|
118
118
|
}
|
|
119
|
-
this.
|
|
119
|
+
this._getClickTimeout(this._clickState);
|
|
120
120
|
return info;
|
|
121
121
|
}
|
|
122
122
|
case "pointer_up": {
|
|
@@ -138,7 +138,7 @@ class ClickManager {
|
|
|
138
138
|
return info;
|
|
139
139
|
}
|
|
140
140
|
case "pointer_move": {
|
|
141
|
-
if (this._clickState !== "idle" && this._clickScreenPoint && import_Vec.Vec.Dist2(this._clickScreenPoint,
|
|
141
|
+
if (this._clickState !== "idle" && this._clickScreenPoint && import_Vec.Vec.Dist2(this._clickScreenPoint, info.point) > (this.editor.getInstanceState().isCoarsePointer ? this.editor.options.coarseDragDistanceSquared : this.editor.options.dragDistanceSquared)) {
|
|
142
142
|
this.cancelDoubleClickTimeout();
|
|
143
143
|
}
|
|
144
144
|
return info;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../src/lib/editor/managers/ClickManager/ClickManager.ts"],
|
|
4
|
-
"sourcesContent": ["import { bind, uniqueId } from '@tldraw/utils'\nimport { Vec } from '../../../primitives/Vec'\nimport type { Editor } from '../../Editor'\nimport { TLClickEventInfo, TLPointerEventInfo } from '../../types/event-types'\n\n/** @public */\nexport type TLClickState = 'idle' | 'pendingDouble' | 'pendingOverflow' | 'overflow'\n\nconst MAX_CLICK_DISTANCE = 40\n\n/** @public */\nexport class ClickManager {\n\tconstructor(public editor: Editor) {}\n\n\tprivate _clickId = ''\n\n\tprivate _clickTimeout?: any\n\n\tprivate _clickScreenPoint?: Vec\n\n\tprivate _previousScreenPoint?: Vec\n\n\tprivate _isPressingWhilePending = false\n\n\t@bind\n\t_getClickTimeout(state: TLClickState, id = uniqueId()) {\n\t\tthis._clickId = id\n\t\tclearTimeout(this._clickTimeout)\n\t\tthis._clickTimeout = this.editor.timers.setTimeout(\n\t\t\t() => {\n\t\t\t\tif (this._clickState === state && this._clickId === id) {\n\t\t\t\t\tswitch (this._clickState) {\n\t\t\t\t\t\tcase 'pendingOverflow': {\n\t\t\t\t\t\t\tthis.editor.dispatch({\n\t\t\t\t\t\t\t\t...this.lastPointerInfo,\n\t\t\t\t\t\t\t\ttype: 'click',\n\t\t\t\t\t\t\t\tname: 'double_click',\n\t\t\t\t\t\t\t\tphase: this._isPressingWhilePending ? 'settle-down' : 'settle-up',\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\t}\n\t\t\t\t\t\tdefault: {\n\t\t\t\t\t\t\t// noop\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tthis._clickState = 'idle'\n\t\t\t\t}\n\t\t\t},\n\t\t\tstate === 'idle' || state === 'pendingDouble'\n\t\t\t\t? this.editor.options.doubleClickDurationMs\n\t\t\t\t: this.editor.options.multiClickDurationMs\n\t\t)\n\t}\n\n\t/**\n\t * The current click state.\n\t *\n\t * @internal\n\t */\n\tprivate _clickState?: TLClickState = 'idle'\n\n\t/**\n\t * The current click state.\n\t *\n\t * @public\n\t */\n\t// eslint-disable-next-line tldraw/no-setter-getter\n\tget clickState() {\n\t\treturn this._clickState\n\t}\n\n\tlastPointerInfo = {} as TLPointerEventInfo\n\n\thandlePointerEvent(info: TLPointerEventInfo): TLPointerEventInfo | TLClickEventInfo {\n\t\tswitch (info.name) {\n\t\t\tcase 'pointer_down': {\n\t\t\t\tif (!this._clickState) return info\n\t\t\t\tthis._clickScreenPoint = Vec.From(info.point)\n\n\t\t\t\tthis._isPressingWhilePending = true\n\n\t\t\t\tif (\n\t\t\t\t\tthis._previousScreenPoint &&\n\t\t\t\t\tVec.Dist2(this._previousScreenPoint, this._clickScreenPoint) > MAX_CLICK_DISTANCE ** 2\n\t\t\t\t) {\n\t\t\t\t\tthis._clickState = 'idle'\n\t\t\t\t}\n\n\t\t\t\tthis._previousScreenPoint = this._clickScreenPoint\n\n\t\t\t\tthis.lastPointerInfo = info\n\n\t\t\t\tswitch (this._clickState) {\n\t\t\t\t\tcase 'pendingDouble': {\n\t\t\t\t\t\tthis._clickState = 'pendingOverflow'\n\t\t\t\t\t\tthis.
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAA+B;AAC/B,iBAAoB;AAOpB,MAAM,qBAAqB;AAGpB,MAAM,aAAa;AAAA,EACzB,YAAmB,QAAgB;AAAhB;AAAA,EAAiB;AAAA,EAAjB;AAAA,EAEX,WAAW;AAAA,EAEX;AAAA,EAEA;AAAA,EAEA;AAAA,EAEA,0BAA0B;AAAA,EAGlC,iBAAiB,OAAqB,SAAK,uBAAS,GAAG;AACtD,SAAK,WAAW;AAChB,iBAAa,KAAK,aAAa;AAC/B,SAAK,gBAAgB,KAAK,OAAO,OAAO;AAAA,MACvC,MAAM;AACL,YAAI,KAAK,gBAAgB,SAAS,KAAK,aAAa,IAAI;AACvD,kBAAQ,KAAK,aAAa;AAAA,YACzB,KAAK,mBAAmB;AACvB,mBAAK,OAAO,SAAS;AAAA,gBACpB,GAAG,KAAK;AAAA,gBACR,MAAM;AAAA,gBACN,MAAM;AAAA,gBACN,OAAO,KAAK,0BAA0B,gBAAgB;AAAA,cACvD,CAAC;AACD;AAAA,YACD;AAAA,YACA,SAAS;AAAA,YAET;AAAA,UACD;AAEA,eAAK,cAAc;AAAA,QACpB;AAAA,MACD;AAAA,MACA,UAAU,UAAU,UAAU,kBAC3B,KAAK,OAAO,QAAQ,wBACpB,KAAK,OAAO,QAAQ;AAAA,IACxB;AAAA,EACD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,cAA6B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQrC,IAAI,aAAa;AAChB,WAAO,KAAK;AAAA,EACb;AAAA,EAEA,kBAAkB,CAAC;AAAA,EAEnB,mBAAmB,MAAiE;AACnF,YAAQ,KAAK,MAAM;AAAA,MAClB,KAAK,gBAAgB;AACpB,YAAI,CAAC,KAAK,YAAa,QAAO;AAC9B,aAAK,oBAAoB,eAAI,KAAK,KAAK,KAAK;AAE5C,aAAK,0BAA0B;AAE/B,YACC,KAAK,wBACL,eAAI,MAAM,KAAK,sBAAsB,KAAK,iBAAiB,IAAI,sBAAsB,GACpF;AACD,eAAK,cAAc;AAAA,QACpB;AAEA,aAAK,uBAAuB,KAAK;AAEjC,aAAK,kBAAkB;AAEvB,gBAAQ,KAAK,aAAa;AAAA,UACzB,KAAK,iBAAiB;AACrB,iBAAK,cAAc;AACnB,iBAAK,
|
|
4
|
+
"sourcesContent": ["import { bind, uniqueId } from '@tldraw/utils'\nimport { Vec } from '../../../primitives/Vec'\nimport type { Editor } from '../../Editor'\nimport { TLClickEventInfo, TLPointerEventInfo } from '../../types/event-types'\n\n/** @public */\nexport type TLClickState = 'idle' | 'pendingDouble' | 'pendingOverflow' | 'overflow'\n\nconst MAX_CLICK_DISTANCE = 40\n\n/** @public */\nexport class ClickManager {\n\tconstructor(public editor: Editor) {}\n\n\tprivate _clickId = ''\n\n\tprivate _clickTimeout?: any\n\n\tprivate _clickScreenPoint?: Vec\n\n\tprivate _previousScreenPoint?: Vec\n\n\tprivate _isPressingWhilePending = false\n\n\t@bind\n\t_getClickTimeout(state: TLClickState, id = uniqueId()) {\n\t\tthis._clickId = id\n\t\tclearTimeout(this._clickTimeout)\n\t\tthis._clickTimeout = this.editor.timers.setTimeout(\n\t\t\t() => {\n\t\t\t\tif (this._clickState === state && this._clickId === id) {\n\t\t\t\t\tswitch (this._clickState) {\n\t\t\t\t\t\tcase 'pendingOverflow': {\n\t\t\t\t\t\t\tthis.editor.dispatch({\n\t\t\t\t\t\t\t\t...this.lastPointerInfo,\n\t\t\t\t\t\t\t\ttype: 'click',\n\t\t\t\t\t\t\t\tname: 'double_click',\n\t\t\t\t\t\t\t\tphase: this._isPressingWhilePending ? 'settle-down' : 'settle-up',\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\t}\n\t\t\t\t\t\tdefault: {\n\t\t\t\t\t\t\t// noop\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tthis._clickState = 'idle'\n\t\t\t\t}\n\t\t\t},\n\t\t\tstate === 'idle' || state === 'pendingDouble'\n\t\t\t\t? this.editor.options.doubleClickDurationMs\n\t\t\t\t: this.editor.options.multiClickDurationMs\n\t\t)\n\t}\n\n\t/**\n\t * The current click state.\n\t *\n\t * @internal\n\t */\n\tprivate _clickState?: TLClickState = 'idle'\n\n\t/**\n\t * The current click state.\n\t *\n\t * @public\n\t */\n\t// eslint-disable-next-line tldraw/no-setter-getter\n\tget clickState() {\n\t\treturn this._clickState\n\t}\n\n\tlastPointerInfo = {} as TLPointerEventInfo\n\n\thandlePointerEvent(info: TLPointerEventInfo): TLPointerEventInfo | TLClickEventInfo {\n\t\tswitch (info.name) {\n\t\t\tcase 'pointer_down': {\n\t\t\t\tif (!this._clickState) return info\n\t\t\t\tthis._clickScreenPoint = Vec.From(info.point)\n\n\t\t\t\tthis._isPressingWhilePending = true\n\n\t\t\t\tif (\n\t\t\t\t\tthis._previousScreenPoint &&\n\t\t\t\t\tVec.Dist2(this._previousScreenPoint, this._clickScreenPoint) > MAX_CLICK_DISTANCE ** 2\n\t\t\t\t) {\n\t\t\t\t\tthis._clickState = 'idle'\n\t\t\t\t}\n\n\t\t\t\tthis._previousScreenPoint = this._clickScreenPoint\n\n\t\t\t\tthis.lastPointerInfo = info\n\n\t\t\t\tswitch (this._clickState) {\n\t\t\t\t\tcase 'pendingDouble': {\n\t\t\t\t\t\tthis._clickState = 'pendingOverflow'\n\t\t\t\t\t\tthis._getClickTimeout(this._clickState)\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t...info,\n\t\t\t\t\t\t\ttype: 'click',\n\t\t\t\t\t\t\tname: 'double_click',\n\t\t\t\t\t\t\tphase: 'down',\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tcase 'idle': {\n\t\t\t\t\t\tthis._clickState = 'pendingDouble'\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t\tcase 'pendingOverflow': {\n\t\t\t\t\t\tthis._clickState = 'overflow'\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t\tdefault: {\n\t\t\t\t\t\t// overflow\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tthis._getClickTimeout(this._clickState)\n\t\t\t\treturn info\n\t\t\t}\n\t\t\tcase 'pointer_up': {\n\t\t\t\tif (!this._clickState) return info\n\n\t\t\t\tthis._clickScreenPoint = Vec.From(info.point)\n\n\t\t\t\tthis._isPressingWhilePending = false\n\n\t\t\t\tswitch (this._clickState) {\n\t\t\t\t\tcase 'pendingOverflow': {\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t...this.lastPointerInfo,\n\t\t\t\t\t\t\ttype: 'click',\n\t\t\t\t\t\t\tname: 'double_click',\n\t\t\t\t\t\t\tphase: 'up',\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tdefault: {\n\t\t\t\t\t\t// idle, pendingDouble, overflow\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn info\n\t\t\t}\n\t\t\tcase 'pointer_move': {\n\t\t\t\t// Compare in client coordinates like _clickScreenPoint; the container-relative\n\t\t\t\t// inputs screen point would add the container offset and cancel on any movement.\n\t\t\t\tif (\n\t\t\t\t\tthis._clickState !== 'idle' &&\n\t\t\t\t\tthis._clickScreenPoint &&\n\t\t\t\t\tVec.Dist2(this._clickScreenPoint, info.point) >\n\t\t\t\t\t\t(this.editor.getInstanceState().isCoarsePointer\n\t\t\t\t\t\t\t? this.editor.options.coarseDragDistanceSquared\n\t\t\t\t\t\t\t: this.editor.options.dragDistanceSquared)\n\t\t\t\t) {\n\t\t\t\t\tthis.cancelDoubleClickTimeout()\n\t\t\t\t}\n\t\t\t\treturn info\n\t\t\t}\n\t\t}\n\t\treturn info\n\t}\n\n\t/**\n\t * Cancel the double click timeout.\n\t *\n\t * @internal\n\t */\n\t@bind\n\tcancelDoubleClickTimeout() {\n\t\tthis._clickTimeout = clearTimeout(this._clickTimeout)\n\t\tthis._clickState = 'idle'\n\t\t// when a double click is cancelled, we are no longer pending any further\n\t\t// clicks, so we set this to false even if the user is still pressing\n\t\tthis._isPressingWhilePending = false\n\t}\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -57,14 +57,14 @@ class CollaboratorsManager {
|
|
|
57
57
|
getCollaborators() {
|
|
58
58
|
const allPresenceRecords = this._getCollaboratorsQuery().get();
|
|
59
59
|
if (!allPresenceRecords.length) return import_state.EMPTY_ARRAY;
|
|
60
|
-
const
|
|
61
|
-
|
|
62
|
-
const
|
|
63
|
-
|
|
64
|
-
(
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
60
|
+
const latestByUserId = /* @__PURE__ */ new Map();
|
|
61
|
+
for (const presence of allPresenceRecords) {
|
|
62
|
+
const latest = latestByUserId.get(presence.userId);
|
|
63
|
+
if (!latest || (presence.lastActivityTimestamp ?? 0) > (latest.lastActivityTimestamp ?? 0)) {
|
|
64
|
+
latestByUserId.set(presence.userId, presence);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return [...latestByUserId.keys()].sort().map((id) => latestByUserId.get(id));
|
|
68
68
|
}
|
|
69
69
|
getCollaboratorsOnCurrentPage() {
|
|
70
70
|
const currentPageId = this.editor.getCurrentPageId();
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../src/lib/editor/managers/CollaboratorsManager/CollaboratorsManager.ts"],
|
|
4
|
-
"sourcesContent": ["import { EMPTY_ARRAY, atom, computed } from '@tldraw/state'\nimport type { TLInstancePresence } from '@tldraw/tlschema'\nimport { areArraysShallowEqual
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAA4C;AAE5C,
|
|
4
|
+
"sourcesContent": ["import { EMPTY_ARRAY, atom, computed } from '@tldraw/state'\nimport type { TLInstancePresence } from '@tldraw/tlschema'\nimport { areArraysShallowEqual } from '@tldraw/utils'\nimport type { Editor } from '../../Editor'\n\n/**\n * Tracks remote peers and exposes the collaborator-related queries used by the\n * editor and its overlays. Encapsulates the visibility clock that periodically\n * re-evaluates which collaborators should be visible based on activity.\n *\n * Accessed via {@link Editor.collaborators}.\n *\n * @public\n */\nexport class CollaboratorsManager {\n\tconstructor(private readonly editor: Editor) {}\n\n\tprivate _visibilityClockStarted = false\n\n\tprivate _startVisibilityClock() {\n\t\tif (this._visibilityClockStarted) return\n\t\tthis._visibilityClockStarted = true\n\n\t\t// Editor disposes `editor.timers` on its own teardown, so the interval is\n\t\t// automatically cleared when the editor is disposed.\n\t\tthis.editor.timers.setInterval(() => {\n\t\t\tthis._visibilityClock.set(Date.now())\n\t\t}, this.editor.options.collaboratorCheckIntervalMs)\n\t}\n\n\t/**\n\t * Drives reactive re-evaluation of {@link CollaboratorsManager.getVisibleCollaborators}.\n\t * Ticked on a fixed interval so callers don't need to manage their own activity timers.\n\t */\n\tprivate readonly _visibilityClock = atom('collaboratorVisibilityClock', Date.now())\n\n\t@computed\n\tprivate _getCollaboratorsQuery() {\n\t\treturn this.editor.store.query.records('instance_presence', () => ({\n\t\t\tuserId: { neq: this.editor.user.getRecordId() },\n\t\t}))\n\t}\n\n\t// These queries all derive fresh arrays with map/filter, so they compare results with\n\t// shallow (element-identity) equality: a presence update that leaves a derived list's\n\t// elements unchanged \u2014 e.g. a peer moving on another page \u2014 keeps the previous array's\n\t// identity and doesn't invalidate downstream subscribers such as the cursor layer.\n\n\t/**\n\t * Returns a list of presence records for all peer collaborators.\n\t * This will return the latest presence record for each connected user.\n\t */\n\t@computed({ isEqual: areArraysShallowEqual })\n\tgetCollaborators(): TLInstancePresence[] {\n\t\tconst allPresenceRecords = this._getCollaboratorsQuery().get()\n\t\tif (!allPresenceRecords.length) return EMPTY_ARRAY\n\t\tconst latestByUserId = new Map<string, TLInstancePresence>()\n\t\tfor (const presence of allPresenceRecords) {\n\t\t\tconst latest = latestByUserId.get(presence.userId)\n\t\t\tif (!latest || (presence.lastActivityTimestamp ?? 0) > (latest.lastActivityTimestamp ?? 0)) {\n\t\t\t\tlatestByUserId.set(presence.userId, presence)\n\t\t\t}\n\t\t}\n\t\treturn [...latestByUserId.keys()].sort().map((id) => latestByUserId.get(id)!)\n\t}\n\n\t/**\n\t * Returns a list of presence records for all peer collaborators on the current page.\n\t * This will return the latest presence record for each connected user.\n\t */\n\t@computed({ isEqual: areArraysShallowEqual })\n\tgetCollaboratorsOnCurrentPage(): TLInstancePresence[] {\n\t\tconst currentPageId = this.editor.getCurrentPageId()\n\t\treturn this.getCollaborators().filter((c) => c.currentPageId === currentPageId)\n\t}\n\n\t/**\n\t * Returns a list of presence records for peer collaborators who should currently be\n\t * shown in the UI. Filters {@link CollaboratorsManager.getCollaborators} by activity\n\t * state (active / idle / inactive) and visibility rules such as following and\n\t * highlighted users. Re-evaluates on the visibility clock, so callers don't need to\n\t * drive their own activity timer.\n\t */\n\t@computed({ isEqual: areArraysShallowEqual })\n\tgetVisibleCollaborators(): TLInstancePresence[] {\n\t\tconst { editor } = this\n\t\tconst { collaboratorInactiveTimeoutMs, collaboratorIdleTimeoutMs } = editor.options\n\n\t\tthis._startVisibilityClock()\n\t\tthis._visibilityClock.get()\n\t\tconst now = Date.now()\n\t\tconst collaborators = this.getCollaborators()\n\t\tif (!collaborators.length) return EMPTY_ARRAY\n\n\t\tconst { followingUserId, highlightedUserIds } = this.editor.getInstanceState()\n\t\tconst currentUserId = this.editor.user.getRecordId()\n\n\t\treturn collaborators.filter((presence) => {\n\t\t\tconst { lastActivityTimestamp, userId, chatMessage } = presence\n\n\t\t\t// Treat a missing or zero `lastActivityTimestamp` as \"active right now\"\n\t\t\t// (elapsed = 0) so newly-joined peers aren't immediately classified as\n\t\t\t// idle/inactive. The broadcast default for peers who haven't moved their\n\t\t\t// pointer yet is `0` (e.g. someone on a touch device who joins and just\n\t\t\t// watches), so a plain `?? now` would leave them hidden. See issue #9017.\n\t\t\tconst elapsed = lastActivityTimestamp ? Math.max(0, now - lastActivityTimestamp) : 0\n\n\t\t\tif (elapsed > collaboratorInactiveTimeoutMs) {\n\t\t\t\t// Inactive: If they're inactive, only show if we're following them or they're highlighted\n\t\t\t\treturn followingUserId === userId || highlightedUserIds.includes(userId)\n\t\t\t}\n\n\t\t\tif (elapsed > collaboratorIdleTimeoutMs) {\n\t\t\t\t// Idle: If they're idle and following us, hide them unless they have a chat message or are highlighted\n\t\t\t\tif (presence.followingUserId === currentUserId) {\n\t\t\t\t\treturn !!(chatMessage || highlightedUserIds.includes(userId))\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Active\n\t\t\treturn true\n\t\t})\n\t}\n\n\t/**\n\t * Returns a list of presence records for peer collaborators who should currently be\n\t * shown in the UI, filtered to those on the current page.\n\t */\n\t@computed({ isEqual: areArraysShallowEqual })\n\tgetVisibleCollaboratorsOnCurrentPage(): TLInstancePresence[] {\n\t\tconst currentPageId = this.editor.getCurrentPageId()\n\t\treturn this.getVisibleCollaborators().filter((c) => c.currentPageId === currentPageId)\n\t}\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -21,6 +21,7 @@ __export(EdgeScrollManager_exports, {
|
|
|
21
21
|
EdgeScrollManager: () => EdgeScrollManager
|
|
22
22
|
});
|
|
23
23
|
module.exports = __toCommonJS(EdgeScrollManager_exports);
|
|
24
|
+
var import_constants = require("../../../constants");
|
|
24
25
|
var import_easings = require("../../../primitives/easings");
|
|
25
26
|
var import_Vec = require("../../../primitives/Vec");
|
|
26
27
|
const EDGE_SCROLL_SMALL_SCREEN_THRESHOLD_PX = 1e3;
|
|
@@ -63,10 +64,13 @@ class EdgeScrollManager {
|
|
|
63
64
|
this._edgeScrollDuration / (editor.options.edgeScrollDelay + editor.options.edgeScrollEaseDuration)
|
|
64
65
|
)
|
|
65
66
|
) : 1;
|
|
66
|
-
this.moveCameraWhenCloseToEdge(
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
67
|
+
this.moveCameraWhenCloseToEdge(
|
|
68
|
+
{
|
|
69
|
+
x: edgeScrollProximityFactor.x * eased,
|
|
70
|
+
y: edgeScrollProximityFactor.y * eased
|
|
71
|
+
},
|
|
72
|
+
elapsed
|
|
73
|
+
);
|
|
70
74
|
}
|
|
71
75
|
}
|
|
72
76
|
}
|
|
@@ -113,14 +117,14 @@ class EdgeScrollManager {
|
|
|
113
117
|
* Moves the camera when the mouse is close to the edge of the screen.
|
|
114
118
|
* @public
|
|
115
119
|
*/
|
|
116
|
-
moveCameraWhenCloseToEdge(proximityFactor) {
|
|
120
|
+
moveCameraWhenCloseToEdge(proximityFactor, elapsed) {
|
|
117
121
|
if (proximityFactor.x === 0 && proximityFactor.y === 0) return;
|
|
118
122
|
const { editor } = this;
|
|
119
123
|
const screenBounds = editor.getViewportScreenBounds();
|
|
120
124
|
const screenSizeFactorX = screenBounds.w < EDGE_SCROLL_SMALL_SCREEN_THRESHOLD_PX ? EDGE_SCROLL_SMALL_SCREEN_SPEED_FACTOR : 1;
|
|
121
125
|
const screenSizeFactorY = screenBounds.h < EDGE_SCROLL_SMALL_SCREEN_THRESHOLD_PX ? EDGE_SCROLL_SMALL_SCREEN_SPEED_FACTOR : 1;
|
|
122
126
|
const zoomLevel = editor.getZoomLevel();
|
|
123
|
-
const pxSpeed = editor.user.getEdgeScrollSpeed() * editor.options.edgeScrollSpeed;
|
|
127
|
+
const pxSpeed = editor.user.getEdgeScrollSpeed() * editor.options.edgeScrollSpeed * (elapsed / import_constants.FRAME_MS_60HZ);
|
|
124
128
|
const scrollDeltaX = pxSpeed * proximityFactor.x * screenSizeFactorX / zoomLevel;
|
|
125
129
|
const scrollDeltaY = pxSpeed * proximityFactor.y * screenSizeFactorY / zoomLevel;
|
|
126
130
|
const { x, y, z } = editor.getCamera();
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../src/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.ts"],
|
|
4
|
-
"sourcesContent": ["import { EASINGS } from '../../../primitives/easings'\nimport { Vec } from '../../../primitives/Vec'\nimport type { Editor } from '../../Editor'\n\n// Tuned for touch/small-screen feel; adjust together with coarsePointerWidth.\nconst EDGE_SCROLL_SMALL_SCREEN_THRESHOLD_PX = 1000\nconst EDGE_SCROLL_SMALL_SCREEN_SPEED_FACTOR = 0.612\n\n/** @public */\nexport class EdgeScrollManager {\n\tconstructor(public editor: Editor) {}\n\n\tprivate _isEdgeScrolling = false\n\tprivate _edgeScrollDuration = -1\n\n\tgetIsEdgeScrolling() {\n\t\treturn this._isEdgeScrolling\n\t}\n\n\t/**\n\t * Update the camera position when the mouse is close to the edge of the screen.\n\t * Run this on every tick when in a state where edge scrolling is enabled.\n\t *\n\t * @public\n\t */\n\tupdateEdgeScrolling(elapsed: number) {\n\t\tconst { editor } = this\n\n\t\tif (editor.getCameraOptions().isLocked) return\n\n\t\tconst edgeScrollProximityFactor = this.getEdgeScroll()\n\t\tif (edgeScrollProximityFactor.x === 0 && edgeScrollProximityFactor.y === 0) {\n\t\t\tif (this._isEdgeScrolling) {\n\t\t\t\tthis._isEdgeScrolling = false\n\t\t\t\tthis._edgeScrollDuration = 0\n\t\t\t}\n\t\t} else {\n\t\t\tif (!this._isEdgeScrolling) {\n\t\t\t\tthis._isEdgeScrolling = true\n\t\t\t\tthis._edgeScrollDuration = 0\n\t\t\t}\n\t\t\tthis._edgeScrollDuration += elapsed\n\t\t\tif (this._edgeScrollDuration > editor.options.edgeScrollDelay) {\n\t\t\t\tconst eased =\n\t\t\t\t\teditor.options.edgeScrollEaseDuration > 0\n\t\t\t\t\t\t? EASINGS.easeInCubic(\n\t\t\t\t\t\t\t\tMath.min(\n\t\t\t\t\t\t\t\t\t1,\n\t\t\t\t\t\t\t\t\tthis._edgeScrollDuration /\n\t\t\t\t\t\t\t\t\t\t(editor.options.edgeScrollDelay + editor.options.edgeScrollEaseDuration)\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t: 1\n\t\t\t\tthis.moveCameraWhenCloseToEdge({\n\t\t\t\t\tx: edgeScrollProximityFactor.x * eased,\n\t\t\t\t\ty: edgeScrollProximityFactor.y * eased,\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Helper function to get the scroll proximity factor for a given position.\n\t * @param position - The mouse position on the axis.\n\t * @param dimension - The component dimension on the axis.\n\t * @param isCoarse - Whether the pointer is coarse.\n\t * @param insetStart - Whether the pointer is inset at the start of the axis.\n\t * @param insetEnd - Whether the pointer is inset at the end of the axis.\n\t * @internal\n\t */\n\tprivate getEdgeProximityFactors(\n\t\tposition: number,\n\t\tdimension: number,\n\t\tisCoarse: boolean,\n\t\tinsetStart: boolean,\n\t\tinsetEnd: boolean\n\t) {\n\t\tconst { editor } = this\n\t\tconst dist = editor.options.edgeScrollDistance\n\t\tconst pw = isCoarse ? editor.options.coarsePointerWidth : 0 // pointer width\n\t\tconst pMin = position - pw\n\t\tconst pMax = position + pw\n\t\tconst min = insetStart ? 0 : dist\n\t\tconst max = insetEnd ? dimension : dimension - dist\n\t\tif (pMin < min) {\n\t\t\treturn Math.min(1, (min - pMin) / dist)\n\t\t} else if (pMax > max) {\n\t\t\treturn -Math.min(1, (pMax - max) / dist)\n\t\t}\n\t\treturn 0\n\t}\n\n\tprivate getEdgeScroll() {\n\t\tconst { editor } = this\n\t\tconst { x, y } = editor.inputs.getCurrentScreenPoint()\n\t\tconst screenBounds = editor.getViewportScreenBounds()\n\n\t\tconst {\n\t\t\tisCoarsePointer,\n\t\t\tinsets: [t, r, b, l],\n\t\t} = editor.getInstanceState()\n\t\tconst proximityFactorX = this.getEdgeProximityFactors(x, screenBounds.w, isCoarsePointer, l, r)\n\t\tconst proximityFactorY = this.getEdgeProximityFactors(y, screenBounds.h, isCoarsePointer, t, b)\n\n\t\treturn {\n\t\t\tx: proximityFactorX,\n\t\t\ty: proximityFactorY,\n\t\t}\n\t}\n\n\t/**\n\t * Moves the camera when the mouse is close to the edge of the screen.\n\t * @public\n\t */\n\tprivate moveCameraWhenCloseToEdge(proximityFactor: { x: number; y: number }) {\n\t\tif (proximityFactor.x === 0 && proximityFactor.y === 0) return\n\t\tconst { editor } = this\n\n\t\tconst screenBounds = editor.getViewportScreenBounds()\n\n\t\t// Determines how much the speed is affected by the screen size\n\t\tconst screenSizeFactorX =\n\t\t\tscreenBounds.w < EDGE_SCROLL_SMALL_SCREEN_THRESHOLD_PX\n\t\t\t\t? EDGE_SCROLL_SMALL_SCREEN_SPEED_FACTOR\n\t\t\t\t: 1\n\t\tconst screenSizeFactorY =\n\t\t\tscreenBounds.h < EDGE_SCROLL_SMALL_SCREEN_THRESHOLD_PX\n\t\t\t\t? EDGE_SCROLL_SMALL_SCREEN_SPEED_FACTOR\n\t\t\t\t: 1\n\n\t\t// Determines the base speed of the scroll\n\t\tconst zoomLevel = editor.getZoomLevel()\n\t\tconst pxSpeed
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAAwB;AACxB,iBAAoB;AAIpB,MAAM,wCAAwC;AAC9C,MAAM,wCAAwC;AAGvC,MAAM,kBAAkB;AAAA,EAC9B,YAAmB,QAAgB;AAAhB;AAAA,EAAiB;AAAA,EAAjB;AAAA,EAEX,mBAAmB;AAAA,EACnB,sBAAsB;AAAA,EAE9B,qBAAqB;AACpB,WAAO,KAAK;AAAA,EACb;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,oBAAoB,SAAiB;AACpC,UAAM,EAAE,OAAO,IAAI;AAEnB,QAAI,OAAO,iBAAiB,EAAE,SAAU;AAExC,UAAM,4BAA4B,KAAK,cAAc;AACrD,QAAI,0BAA0B,MAAM,KAAK,0BAA0B,MAAM,GAAG;AAC3E,UAAI,KAAK,kBAAkB;AAC1B,aAAK,mBAAmB;AACxB,aAAK,sBAAsB;AAAA,MAC5B;AAAA,IACD,OAAO;AACN,UAAI,CAAC,KAAK,kBAAkB;AAC3B,aAAK,mBAAmB;AACxB,aAAK,sBAAsB;AAAA,MAC5B;AACA,WAAK,uBAAuB;AAC5B,UAAI,KAAK,sBAAsB,OAAO,QAAQ,iBAAiB;AAC9D,cAAM,QACL,OAAO,QAAQ,yBAAyB,IACrC,uBAAQ;AAAA,UACR,KAAK;AAAA,YACJ;AAAA,YACA,KAAK,uBACH,OAAO,QAAQ,kBAAkB,OAAO,QAAQ;AAAA,UACnD;AAAA,QACD,IACC;AACJ,aAAK,
|
|
4
|
+
"sourcesContent": ["import { FRAME_MS_60HZ } from '../../../constants'\nimport { EASINGS } from '../../../primitives/easings'\nimport { Vec } from '../../../primitives/Vec'\nimport type { Editor } from '../../Editor'\n\n// Tuned for touch/small-screen feel; adjust together with coarsePointerWidth.\nconst EDGE_SCROLL_SMALL_SCREEN_THRESHOLD_PX = 1000\nconst EDGE_SCROLL_SMALL_SCREEN_SPEED_FACTOR = 0.612\n\n/** @public */\nexport class EdgeScrollManager {\n\tconstructor(public editor: Editor) {}\n\n\tprivate _isEdgeScrolling = false\n\tprivate _edgeScrollDuration = -1\n\n\tgetIsEdgeScrolling() {\n\t\treturn this._isEdgeScrolling\n\t}\n\n\t/**\n\t * Update the camera position when the mouse is close to the edge of the screen.\n\t * Run this on every tick when in a state where edge scrolling is enabled.\n\t *\n\t * @public\n\t */\n\tupdateEdgeScrolling(elapsed: number) {\n\t\tconst { editor } = this\n\n\t\tif (editor.getCameraOptions().isLocked) return\n\n\t\tconst edgeScrollProximityFactor = this.getEdgeScroll()\n\t\tif (edgeScrollProximityFactor.x === 0 && edgeScrollProximityFactor.y === 0) {\n\t\t\tif (this._isEdgeScrolling) {\n\t\t\t\tthis._isEdgeScrolling = false\n\t\t\t\tthis._edgeScrollDuration = 0\n\t\t\t}\n\t\t} else {\n\t\t\tif (!this._isEdgeScrolling) {\n\t\t\t\tthis._isEdgeScrolling = true\n\t\t\t\tthis._edgeScrollDuration = 0\n\t\t\t}\n\t\t\tthis._edgeScrollDuration += elapsed\n\t\t\tif (this._edgeScrollDuration > editor.options.edgeScrollDelay) {\n\t\t\t\tconst eased =\n\t\t\t\t\teditor.options.edgeScrollEaseDuration > 0\n\t\t\t\t\t\t? EASINGS.easeInCubic(\n\t\t\t\t\t\t\t\tMath.min(\n\t\t\t\t\t\t\t\t\t1,\n\t\t\t\t\t\t\t\t\tthis._edgeScrollDuration /\n\t\t\t\t\t\t\t\t\t\t(editor.options.edgeScrollDelay + editor.options.edgeScrollEaseDuration)\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t: 1\n\t\t\t\tthis.moveCameraWhenCloseToEdge(\n\t\t\t\t\t{\n\t\t\t\t\t\tx: edgeScrollProximityFactor.x * eased,\n\t\t\t\t\t\ty: edgeScrollProximityFactor.y * eased,\n\t\t\t\t\t},\n\t\t\t\t\telapsed\n\t\t\t\t)\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Helper function to get the scroll proximity factor for a given position.\n\t * @param position - The mouse position on the axis.\n\t * @param dimension - The component dimension on the axis.\n\t * @param isCoarse - Whether the pointer is coarse.\n\t * @param insetStart - Whether the pointer is inset at the start of the axis.\n\t * @param insetEnd - Whether the pointer is inset at the end of the axis.\n\t * @internal\n\t */\n\tprivate getEdgeProximityFactors(\n\t\tposition: number,\n\t\tdimension: number,\n\t\tisCoarse: boolean,\n\t\tinsetStart: boolean,\n\t\tinsetEnd: boolean\n\t) {\n\t\tconst { editor } = this\n\t\tconst dist = editor.options.edgeScrollDistance\n\t\tconst pw = isCoarse ? editor.options.coarsePointerWidth : 0 // pointer width\n\t\tconst pMin = position - pw\n\t\tconst pMax = position + pw\n\t\tconst min = insetStart ? 0 : dist\n\t\tconst max = insetEnd ? dimension : dimension - dist\n\t\tif (pMin < min) {\n\t\t\treturn Math.min(1, (min - pMin) / dist)\n\t\t} else if (pMax > max) {\n\t\t\treturn -Math.min(1, (pMax - max) / dist)\n\t\t}\n\t\treturn 0\n\t}\n\n\tprivate getEdgeScroll() {\n\t\tconst { editor } = this\n\t\tconst { x, y } = editor.inputs.getCurrentScreenPoint()\n\t\tconst screenBounds = editor.getViewportScreenBounds()\n\n\t\tconst {\n\t\t\tisCoarsePointer,\n\t\t\tinsets: [t, r, b, l],\n\t\t} = editor.getInstanceState()\n\t\tconst proximityFactorX = this.getEdgeProximityFactors(x, screenBounds.w, isCoarsePointer, l, r)\n\t\tconst proximityFactorY = this.getEdgeProximityFactors(y, screenBounds.h, isCoarsePointer, t, b)\n\n\t\treturn {\n\t\t\tx: proximityFactorX,\n\t\t\ty: proximityFactorY,\n\t\t}\n\t}\n\n\t/**\n\t * Moves the camera when the mouse is close to the edge of the screen.\n\t * @public\n\t */\n\tprivate moveCameraWhenCloseToEdge(proximityFactor: { x: number; y: number }, elapsed: number) {\n\t\tif (proximityFactor.x === 0 && proximityFactor.y === 0) return\n\t\tconst { editor } = this\n\n\t\tconst screenBounds = editor.getViewportScreenBounds()\n\n\t\t// Determines how much the speed is affected by the screen size\n\t\tconst screenSizeFactorX =\n\t\t\tscreenBounds.w < EDGE_SCROLL_SMALL_SCREEN_THRESHOLD_PX\n\t\t\t\t? EDGE_SCROLL_SMALL_SCREEN_SPEED_FACTOR\n\t\t\t\t: 1\n\t\tconst screenSizeFactorY =\n\t\t\tscreenBounds.h < EDGE_SCROLL_SMALL_SCREEN_THRESHOLD_PX\n\t\t\t\t? EDGE_SCROLL_SMALL_SCREEN_SPEED_FACTOR\n\t\t\t\t: 1\n\n\t\t// Determines the base speed of the scroll. edgeScrollSpeed is px per 60 Hz frame, so scale\n\t\t// by elapsed time or a 120 Hz display scrolls twice as fast.\n\t\tconst zoomLevel = editor.getZoomLevel()\n\t\tconst pxSpeed =\n\t\t\teditor.user.getEdgeScrollSpeed() * editor.options.edgeScrollSpeed * (elapsed / FRAME_MS_60HZ)\n\t\tconst scrollDeltaX = (pxSpeed * proximityFactor.x * screenSizeFactorX) / zoomLevel\n\t\tconst scrollDeltaY = (pxSpeed * proximityFactor.y * screenSizeFactorY) / zoomLevel\n\n\t\t// update the camera\n\t\tconst { x, y, z } = editor.getCamera()\n\t\teditor.setCamera(new Vec(x + scrollDeltaX, y + scrollDeltaY, z))\n\t}\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -25,6 +25,7 @@ module.exports = __toCommonJS(FontManager_exports);
|
|
|
25
25
|
var import_state = require("@tldraw/state");
|
|
26
26
|
var import_store = require("@tldraw/store");
|
|
27
27
|
var import_utils = require("@tldraw/utils");
|
|
28
|
+
var import_areShapesContentEqual = require("../../../utils/areShapesContentEqual");
|
|
28
29
|
const EMPTY_SHAPE_FONT_FACES_CACHE = { get: () => void 0 };
|
|
29
30
|
const EMPTY_SHAPE_FONT_LOAD_STATE_CACHE = { get: () => void 0 };
|
|
30
31
|
class FontManager {
|
|
@@ -39,7 +40,7 @@ class FontManager {
|
|
|
39
40
|
},
|
|
40
41
|
{
|
|
41
42
|
areResultsEqual: import_utils.areArraysShallowEqual,
|
|
42
|
-
areRecordsEqual:
|
|
43
|
+
areRecordsEqual: import_areShapesContentEqual.areShapesContentEqual
|
|
43
44
|
}
|
|
44
45
|
);
|
|
45
46
|
this.shapeFontLoadStateCache = editor.store.createCache(
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../src/lib/editor/managers/FontManager/FontManager.ts"],
|
|
4
|
-
"sourcesContent": ["import { computed, EMPTY_ARRAY, transact } from '@tldraw/state'\nimport { AtomMap } from '@tldraw/store'\nimport { TLFontFace, TLShape, TLShapeId } from '@tldraw/tlschema'\nimport {\n\tareArraysShallowEqual,\n\tcompact,\n\tFileHelpers,\n\tmapObjectMapValues,\n\tobjectMapEntries,\n} from '@tldraw/utils'\nimport type { Editor } from '../../Editor'\n\ninterface FontState {\n\treadonly state: 'loading' | 'ready' | 'error'\n\treadonly instance: FontFace\n\treadonly loadingPromise: Promise<void>\n}\n\ninterface ShapeFontFacesCache {\n\tget(id: TLShapeId): TLFontFace[] | undefined\n}\n\ninterface ShapeFontLoadStateCache {\n\tget(id: TLShapeId): (FontState | null)[] | undefined\n}\n\nconst EMPTY_SHAPE_FONT_FACES_CACHE: ShapeFontFacesCache = { get: () => undefined }\nconst EMPTY_SHAPE_FONT_LOAD_STATE_CACHE: ShapeFontLoadStateCache = { get: () => undefined }\n\n/** @public */\nexport class FontManager {\n\tconstructor(\n\t\tprivate readonly editor: Editor,\n\t\tprivate readonly assetUrls?: { [key: string]: string | undefined }\n\t) {\n\t\tthis.shapeFontFacesCache = editor.store.createComputedCache(\n\t\t\t'shape font faces',\n\t\t\t(shape: TLShape) => {\n\t\t\t\tconst shapeUtil = this.editor.getShapeUtil(shape)\n\t\t\t\treturn shapeUtil.getFontFaces(shape)\n\t\t\t},\n\t\t\t{\n\t\t\t\tareResultsEqual: areArraysShallowEqual,\n\t\t\t\tareRecordsEqual:
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAAgD;AAChD,mBAAwB;AAExB,mBAMO;
|
|
4
|
+
"sourcesContent": ["import { computed, EMPTY_ARRAY, transact } from '@tldraw/state'\nimport { AtomMap } from '@tldraw/store'\nimport { TLFontFace, TLShape, TLShapeId } from '@tldraw/tlschema'\nimport {\n\tareArraysShallowEqual,\n\tcompact,\n\tFileHelpers,\n\tmapObjectMapValues,\n\tobjectMapEntries,\n} from '@tldraw/utils'\nimport { areShapesContentEqual } from '../../../utils/areShapesContentEqual'\nimport type { Editor } from '../../Editor'\n\ninterface FontState {\n\treadonly state: 'loading' | 'ready' | 'error'\n\treadonly instance: FontFace\n\treadonly loadingPromise: Promise<void>\n}\n\ninterface ShapeFontFacesCache {\n\tget(id: TLShapeId): TLFontFace[] | undefined\n}\n\ninterface ShapeFontLoadStateCache {\n\tget(id: TLShapeId): (FontState | null)[] | undefined\n}\n\nconst EMPTY_SHAPE_FONT_FACES_CACHE: ShapeFontFacesCache = { get: () => undefined }\nconst EMPTY_SHAPE_FONT_LOAD_STATE_CACHE: ShapeFontLoadStateCache = { get: () => undefined }\n\n/** @public */\nexport class FontManager {\n\tconstructor(\n\t\tprivate readonly editor: Editor,\n\t\tprivate readonly assetUrls?: { [key: string]: string | undefined }\n\t) {\n\t\tthis.shapeFontFacesCache = editor.store.createComputedCache(\n\t\t\t'shape font faces',\n\t\t\t(shape: TLShape) => {\n\t\t\t\tconst shapeUtil = this.editor.getShapeUtil(shape)\n\t\t\t\treturn shapeUtil.getFontFaces(shape)\n\t\t\t},\n\t\t\t{\n\t\t\t\tareResultsEqual: areArraysShallowEqual,\n\t\t\t\tareRecordsEqual: areShapesContentEqual,\n\t\t\t}\n\t\t)\n\n\t\tthis.shapeFontLoadStateCache = editor.store.createCache<(FontState | null)[], TLShape>(\n\t\t\t(id: TLShapeId) => {\n\t\t\t\tconst fontFacesComputed = computed('font faces', () => this.getShapeFontFaces(id))\n\t\t\t\treturn computed(\n\t\t\t\t\t'font load state',\n\t\t\t\t\t() => {\n\t\t\t\t\t\tconst states = fontFacesComputed.get().map((face) => this.getFontState(face))\n\t\t\t\t\t\treturn states\n\t\t\t\t\t},\n\t\t\t\t\t{ isEqual: areArraysShallowEqual }\n\t\t\t\t)\n\t\t\t}\n\t\t)\n\t}\n\n\tdispose() {\n\t\tthis.fontStates.clear()\n\t\tthis.fontsToLoad.clear()\n\t\tthis.shapeFontFacesCache = EMPTY_SHAPE_FONT_FACES_CACHE\n\t\tthis.shapeFontLoadStateCache = EMPTY_SHAPE_FONT_LOAD_STATE_CACHE\n\t}\n\n\tprivate shapeFontFacesCache: ShapeFontFacesCache\n\tprivate shapeFontLoadStateCache: ShapeFontLoadStateCache\n\n\tgetShapeFontFaces(shape: TLShape | TLShapeId): TLFontFace[] {\n\t\tconst shapeId = typeof shape === 'string' ? shape : shape.id\n\t\treturn this.shapeFontFacesCache.get(shapeId) ?? EMPTY_ARRAY\n\t}\n\n\ttrackFontsForShape(shape: TLShape | TLShapeId) {\n\t\tconst shapeId = typeof shape === 'string' ? shape : shape.id\n\t\tthis.shapeFontLoadStateCache.get(shapeId)\n\t}\n\n\tasync loadRequiredFontsForCurrentPage(limit = Infinity) {\n\t\tconst neededFonts = new Set<TLFontFace>()\n\t\tfor (const shapeId of this.editor.getCurrentPageShapeIds()) {\n\t\t\tfor (const font of this.getShapeFontFaces(this.editor.getShape(shapeId)!)) {\n\t\t\t\tneededFonts.add(font)\n\t\t\t}\n\t\t}\n\n\t\tif (neededFonts.size > limit) {\n\t\t\treturn\n\t\t}\n\n\t\tconst promises = Array.from(neededFonts, (font) => this.ensureFontIsLoaded(font))\n\t\tawait Promise.all(promises)\n\t}\n\n\tprivate readonly fontStates = new AtomMap<TLFontFace, FontState>('font states')\n\tprivate getFontState(font: TLFontFace): FontState | null {\n\t\treturn this.fontStates.get(font) ?? null\n\t}\n\n\tensureFontIsLoaded(font: TLFontFace): Promise<void> {\n\t\tconst existingState = this.getFontState(font)\n\t\tif (existingState) return existingState.loadingPromise\n\n\t\tconst instance = this.findOrCreateFontFace(font)\n\t\t// dispose() clears fontStates while loads may still be in flight, so a late\n\t\t// callback must only touch the exact entry it was created for - not a fresh\n\t\t// entry from a later request. Check identity, not just presence.\n\t\tconst isStale = () => this.fontStates.__unsafe__getWithoutCapture(font) !== state\n\t\tconst state: FontState = {\n\t\t\tstate: 'loading',\n\t\t\tinstance,\n\t\t\tloadingPromise: instance\n\t\t\t\t.load()\n\t\t\t\t.then(() => {\n\t\t\t\t\tif (isStale()) {\n\t\t\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\t\t\tconsole.debug(`Font \"${font.family}\" load interrupted by editor dispose`)\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t\tthis.editor.getContainerDocument().fonts.add(instance)\n\t\t\t\t\tthis.fontStates.update(font, (s) => ({ ...s, state: 'ready' }))\n\t\t\t\t})\n\t\t\t\t.catch((err) => {\n\t\t\t\t\tif (isStale()) {\n\t\t\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\t\t\tconsole.debug(`Font \"${font.family}\" load interrupted by editor dispose`, err)\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t\tconsole.error(err)\n\t\t\t\t\tthis.fontStates.update(font, (s) => ({ ...s, state: 'error' }))\n\t\t\t\t}),\n\t\t}\n\n\t\tthis.fontStates.set(font, state)\n\t\treturn state.loadingPromise\n\t}\n\n\tprivate fontsToLoad = new Set<TLFontFace>()\n\trequestFonts(fonts: TLFontFace[]) {\n\t\tif (!this.fontsToLoad.size) {\n\t\t\tqueueMicrotask(() => {\n\t\t\t\tif (this.editor.isDisposed) return\n\t\t\t\tconst toLoad = this.fontsToLoad\n\t\t\t\tthis.fontsToLoad = new Set()\n\t\t\t\ttransact(() => {\n\t\t\t\t\tfor (const font of toLoad) {\n\t\t\t\t\t\tthis.ensureFontIsLoaded(font)\n\t\t\t\t\t}\n\t\t\t\t})\n\t\t\t})\n\t\t}\n\t\tfor (const font of fonts) {\n\t\t\tthis.fontsToLoad.add(font)\n\t\t}\n\t}\n\n\tprivate findOrCreateFontFace(font: TLFontFace) {\n\t\tconst containerDocument = this.editor.getContainerDocument()\n\n\t\t// `findOrCreateFontFace` runs for every font on every editor mount, and a fresh\n\t\t// editor (e.g. switching documents) gets a fresh FontManager with no memory of the\n\t\t// previous one. The dedup below is an O(n) scan of the document's whole FontFaceSet,\n\t\t// so without a cache that scan re-ran on every mount (measurably expensive on mobile\n\t\t// Safari). Cache the resolved FontFace per document so repeated lookups - and\n\t\t// remounts - are O(1). Keyed per document for cross-window embedding.\n\t\tlet cache = fontFaceCacheByDocument.get(containerDocument)\n\t\tif (!cache) {\n\t\t\tcache = new Map()\n\t\t\tfontFaceCacheByDocument.set(containerDocument, cache)\n\t\t}\n\t\tconst key = getFontFaceCacheKey(font)\n\t\tconst cached = cache.get(key)\n\t\tif (cached) return cached\n\n\t\tconst fonts = containerDocument.fonts\n\t\t// On a cache miss we still scan once, so font faces added outside this manager\n\t\t// (e.g. preloaded fonts) are reused rather than duplicated.\n\t\tfor (const existing of fonts) {\n\t\t\tif (\n\t\t\t\texisting.family === font.family &&\n\t\t\t\tobjectMapEntries(defaultFontFaceDescriptors).every(\n\t\t\t\t\t([key, defaultValue]) => existing[key] === (font[key] ?? defaultValue)\n\t\t\t\t)\n\t\t\t) {\n\t\t\t\tcache.set(key, existing)\n\t\t\t\treturn existing\n\t\t\t}\n\t\t}\n\n\t\tconst url = this.assetUrls?.[font.src.url] ?? font.src.url\n\t\tconst instance = new FontFace(font.family, `url(${JSON.stringify(url)})`, {\n\t\t\t...mapObjectMapValues(defaultFontFaceDescriptors, (key) => font[key]),\n\t\t\tdisplay: 'swap',\n\t\t})\n\n\t\tfonts.add(instance)\n\t\tcache.set(key, instance)\n\n\t\treturn instance\n\t}\n\n\tasync toEmbeddedCssDeclaration(font: TLFontFace) {\n\t\tconst url = this.assetUrls?.[font.src.url] ?? font.src.url\n\t\tconst dataUrl = await FileHelpers.urlToDataUrl(url)\n\n\t\tconst src = compact([\n\t\t\t`url(\"${dataUrl}\")`,\n\t\t\tfont.src.format ? `format(${font.src.format})` : null,\n\t\t\tfont.src.tech ? `tech(${font.src.tech})` : null,\n\t\t]).join(' ')\n\t\treturn compact([\n\t\t\t`@font-face {`,\n\t\t\t` font-family: \"${font.family}\";`,\n\t\t\tfont.ascentOverride ? ` ascent-override: ${font.ascentOverride};` : null,\n\t\t\tfont.descentOverride ? ` descent-override: ${font.descentOverride};` : null,\n\t\t\tfont.stretch ? ` font-stretch: ${font.stretch};` : null,\n\t\t\tfont.style ? ` font-style: ${font.style};` : null,\n\t\t\tfont.weight ? ` font-weight: ${font.weight};` : null,\n\t\t\tfont.featureSettings ? ` font-feature-settings: ${font.featureSettings};` : null,\n\t\t\tfont.lineGapOverride ? ` line-gap-override: ${font.lineGapOverride};` : null,\n\t\t\tfont.unicodeRange ? ` unicode-range: ${font.unicodeRange};` : null,\n\t\t\t` src: ${src};`,\n\t\t\t`}`,\n\t\t]).join('\\n')\n\t}\n}\n\n// From https://drafts.csswg.org/css-font-loading/#fontface-interface\nconst defaultFontFaceDescriptors = {\n\tstyle: 'normal',\n\tweight: 'normal',\n\tstretch: 'normal',\n\tunicodeRange: 'U+0-10FFFF',\n\tfeatureSettings: 'normal',\n\tascentOverride: 'normal',\n\tdescentOverride: 'normal',\n\tlineGapOverride: 'normal',\n}\n\n// A FontFace is fully determined by its family and descriptors, so resolved faces can be\n// cached per document and reused across FontManager instances (e.g. editor remounts),\n// turning the per-lookup FontFaceSet scan into an O(1) map lookup. Faces are never removed\n// from `document.fonts` (FontManager.dispose leaves them), so the cache stays valid for the\n// document's lifetime. Keyed per document for cross-window embedding.\nlet fontFaceCacheByDocument = new WeakMap<Document, Map<string, FontFace>>()\n\nfunction getFontFaceCacheKey(font: TLFontFace): string {\n\treturn JSON.stringify([\n\t\tfont.family,\n\t\t...objectMapEntries(defaultFontFaceDescriptors).map(\n\t\t\t([key, defaultValue]) => font[key] ?? defaultValue\n\t\t),\n\t])\n}\n\n/**\n * Resets the per-document font-face cache. Only intended for tests.\n * @internal\n */\nexport function clearFontFaceCacheForTests() {\n\tfontFaceCacheByDocument = new WeakMap()\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["key"]
|
|
7
7
|
}
|
|
@@ -33,16 +33,63 @@ var import_state = require("@tldraw/state");
|
|
|
33
33
|
var import_store = require("@tldraw/store");
|
|
34
34
|
var import_tlschema = require("@tldraw/tlschema");
|
|
35
35
|
var import_utils = require("@tldraw/utils");
|
|
36
|
-
var import_constants = require("../../../constants");
|
|
37
36
|
var import_Vec = require("../../../primitives/Vec");
|
|
38
37
|
var import_keyboard = require("../../../utils/keyboard");
|
|
39
38
|
var import_EditorManager = require("../EditorManager");
|
|
40
39
|
const POINTER_VELOCITY_REFERENCE_INTERVAL_MS = 16;
|
|
41
40
|
const POINTER_VELOCITY_REFERENCE_SMOOTHING = 0.5;
|
|
41
|
+
const ACTIVITY_TIMESTAMP_THROTTLE_MS = 1e3;
|
|
42
|
+
const ACTIVITY_TIMESTAMP_THROTTLE_FLOOR_MS = 100;
|
|
43
|
+
const ACTIVITY_EVENTS = [
|
|
44
|
+
"pointerdown",
|
|
45
|
+
"pointermove",
|
|
46
|
+
"pointerup",
|
|
47
|
+
"keydown",
|
|
48
|
+
"beforeinput",
|
|
49
|
+
"wheel",
|
|
50
|
+
"gesturestart",
|
|
51
|
+
"gesturechange"
|
|
52
|
+
];
|
|
42
53
|
class InputsManager extends import_EditorManager.EditorManager {
|
|
43
54
|
constructor(editor) {
|
|
44
55
|
super(editor);
|
|
45
56
|
this.addEditorEvent("frame", this._onFrame);
|
|
57
|
+
this.register(
|
|
58
|
+
(0, import_state.react)("presence activity listeners", () => {
|
|
59
|
+
if (this.editor.getIsMounted() && this._getHasCollaborators()) {
|
|
60
|
+
this._attachActivityListeners();
|
|
61
|
+
} else {
|
|
62
|
+
this._detachActivityListeners();
|
|
63
|
+
}
|
|
64
|
+
})
|
|
65
|
+
);
|
|
66
|
+
this.register(() => {
|
|
67
|
+
this._detachActivityListeners();
|
|
68
|
+
this._throttledActivityStamp.cancel();
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
_detachActivityListenersFn = null;
|
|
72
|
+
/**
|
|
73
|
+
* User input anywhere in the editor's tab counts as activity for collaborator presence —
|
|
74
|
+
* presence means "this person is here", whether or not the input lands on the editor itself
|
|
75
|
+
* (e.g. typing in a sidebar next to the canvas). Listen in the capture phase so input that
|
|
76
|
+
* other handlers swallow still counts.
|
|
77
|
+
*/
|
|
78
|
+
_attachActivityListeners() {
|
|
79
|
+
if (this._detachActivityListenersFn) return;
|
|
80
|
+
const win = this.editor.getContainerWindow();
|
|
81
|
+
for (const name of ACTIVITY_EVENTS) {
|
|
82
|
+
win.addEventListener(name, this.markActivity, { capture: true });
|
|
83
|
+
}
|
|
84
|
+
this._detachActivityListenersFn = () => {
|
|
85
|
+
for (const name of ACTIVITY_EVENTS) {
|
|
86
|
+
win.removeEventListener(name, this.markActivity, { capture: true });
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
_detachActivityListeners() {
|
|
91
|
+
this._detachActivityListenersFn?.();
|
|
92
|
+
this._detachActivityListenersFn = null;
|
|
46
93
|
}
|
|
47
94
|
_onFrame(elapsed) {
|
|
48
95
|
this.updatePointerVelocity(elapsed);
|
|
@@ -460,6 +507,29 @@ class InputsManager extends import_EditorManager.EditorManager {
|
|
|
460
507
|
_getHasCollaborators() {
|
|
461
508
|
return this.editor.getCollaborators().length > 0;
|
|
462
509
|
}
|
|
510
|
+
_throttledActivityStamp = (0, import_utils.throttle)(
|
|
511
|
+
() => {
|
|
512
|
+
const pointer = this.editor.store.unsafeGetWithoutCapture(import_tlschema.TLPOINTER_ID);
|
|
513
|
+
if (!pointer) return;
|
|
514
|
+
this.editor.run(
|
|
515
|
+
() => {
|
|
516
|
+
this.editor.store.put([{ ...pointer, lastActivityTimestamp: Date.now() }]);
|
|
517
|
+
},
|
|
518
|
+
{ history: "ignore" }
|
|
519
|
+
);
|
|
520
|
+
},
|
|
521
|
+
// Stay comfortably below the idle timeout so a continuously-active peer
|
|
522
|
+
// never flickers to idle between throttled stamps.
|
|
523
|
+
Math.max(
|
|
524
|
+
ACTIVITY_TIMESTAMP_THROTTLE_FLOOR_MS,
|
|
525
|
+
Math.min(ACTIVITY_TIMESTAMP_THROTTLE_MS, this.editor.options.collaboratorIdleTimeoutMs / 3)
|
|
526
|
+
),
|
|
527
|
+
{ trailing: false }
|
|
528
|
+
);
|
|
529
|
+
markActivity() {
|
|
530
|
+
if (!this._getHasCollaborators()) return;
|
|
531
|
+
this._throttledActivityStamp();
|
|
532
|
+
}
|
|
463
533
|
/**
|
|
464
534
|
* The previous point used for velocity calculation (updated each tick, not each pointer event).
|
|
465
535
|
* @internal
|
|
@@ -528,11 +598,11 @@ class InputsManager extends import_EditorManager.EditorManager {
|
|
|
528
598
|
typeName: "pointer",
|
|
529
599
|
x: pagePoint.x,
|
|
530
600
|
y: pagePoint.y,
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
),
|
|
601
|
+
// The activity timestamp is stamped by the container's input
|
|
602
|
+
// listeners (see `markActivity`), not by pointer position updates:
|
|
603
|
+
// synthetic moves, like the camera following another user, don't
|
|
604
|
+
// count as activity.
|
|
605
|
+
lastActivityTimestamp: this.editor.store.unsafeGetWithoutCapture(import_tlschema.TLPOINTER_ID)?.lastActivityTimestamp ?? 0,
|
|
536
606
|
meta: {}
|
|
537
607
|
}
|
|
538
608
|
]);
|
|
@@ -572,4 +642,7 @@ __decorateClass([
|
|
|
572
642
|
__decorateClass([
|
|
573
643
|
import_state.computed
|
|
574
644
|
], InputsManager.prototype, "_getHasCollaborators", 1);
|
|
645
|
+
__decorateClass([
|
|
646
|
+
import_utils.bind
|
|
647
|
+
], InputsManager.prototype, "markActivity", 1);
|
|
575
648
|
//# sourceMappingURL=InputsManager.js.map
|