@netless/window-manager 0.3.17 → 0.4.0-canary.10

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 (73) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/README.md +4 -43
  3. package/dist/App/Storage/StorageEvent.d.ts +8 -0
  4. package/dist/App/Storage/index.d.ts +26 -0
  5. package/dist/App/Storage/typings.d.ts +21 -0
  6. package/dist/App/Storage/utils.d.ts +5 -0
  7. package/dist/AppContext.d.ts +6 -3
  8. package/dist/AppListener.d.ts +2 -2
  9. package/dist/AppManager.d.ts +17 -14
  10. package/dist/AppProxy.d.ts +5 -3
  11. package/dist/AttributesDelegate.d.ts +19 -11
  12. package/dist/Base/Context.d.ts +0 -1
  13. package/dist/Base/index.d.ts +1 -2
  14. package/dist/BoxManager.d.ts +25 -8
  15. package/dist/BuiltinApps.d.ts +6 -0
  16. package/dist/ContainerResizeObserver.d.ts +10 -0
  17. package/dist/Cursor/Cursor.d.ts +2 -3
  18. package/dist/Cursor/index.d.ts +9 -5
  19. package/dist/Helper.d.ts +6 -0
  20. package/dist/ReconnectRefresher.d.ts +9 -3
  21. package/dist/Utils/Common.d.ts +3 -1
  22. package/dist/Utils/Reactive.d.ts +1 -1
  23. package/dist/Utils/RoomHacker.d.ts +2 -2
  24. package/dist/Utils/error.d.ts +3 -0
  25. package/dist/{MainView.d.ts → View/MainView.d.ts} +3 -4
  26. package/dist/View/ViewManager.d.ts +13 -0
  27. package/dist/constants.d.ts +3 -7
  28. package/dist/index.d.ts +24 -27
  29. package/dist/index.es.js +1 -1
  30. package/dist/index.es.js.map +1 -1
  31. package/dist/index.umd.js +1 -1
  32. package/dist/index.umd.js.map +1 -1
  33. package/dist/style.css +1 -1
  34. package/dist/typings.d.ts +1 -0
  35. package/docs/api.md +17 -0
  36. package/docs/migrate.md +42 -0
  37. package/package.json +6 -4
  38. package/src/App/Storage/StorageEvent.ts +21 -0
  39. package/src/App/Storage/index.ts +243 -0
  40. package/src/App/Storage/typings.ts +21 -0
  41. package/src/App/Storage/utils.ts +17 -0
  42. package/src/AppContext.ts +12 -4
  43. package/src/AppListener.ts +15 -11
  44. package/src/AppManager.ts +132 -95
  45. package/src/AppProxy.ts +49 -52
  46. package/src/AttributesDelegate.ts +76 -49
  47. package/src/Base/Context.ts +2 -6
  48. package/src/Base/index.ts +2 -2
  49. package/src/BoxManager.ts +95 -35
  50. package/src/BuiltinApps.ts +24 -0
  51. package/src/ContainerResizeObserver.ts +62 -0
  52. package/src/Cursor/Cursor.ts +35 -39
  53. package/src/Cursor/index.ts +79 -43
  54. package/src/Helper.ts +30 -0
  55. package/src/ReconnectRefresher.ts +25 -10
  56. package/src/Utils/Common.ts +35 -13
  57. package/src/Utils/Reactive.ts +9 -3
  58. package/src/Utils/RoomHacker.ts +20 -5
  59. package/src/Utils/error.ts +6 -1
  60. package/src/{MainView.ts → View/MainView.ts} +19 -27
  61. package/src/View/ViewManager.ts +53 -0
  62. package/src/constants.ts +2 -3
  63. package/src/index.ts +143 -171
  64. package/src/shim.d.ts +4 -0
  65. package/src/style.css +7 -1
  66. package/src/typings.ts +1 -0
  67. package/vite.config.js +4 -1
  68. package/dist/Utils/CameraStore.d.ts +0 -15
  69. package/dist/ViewManager.d.ts +0 -29
  70. package/dist/sdk.d.ts +0 -14
  71. package/src/Utils/CameraStore.ts +0 -72
  72. package/src/sdk.ts +0 -39
  73. package/src/viewManager.ts +0 -177
package/dist/style.css CHANGED
@@ -1 +1 @@
1
- .netless-window-manager-playground{width:100%;height:100%;position:relative;z-index:1;overflow:hidden;user-select:none}.netless-window-manager-sizer{position:absolute;top:0;left:0;width:100%;height:100%;z-index:1;overflow:hidden;display:flex}.netless-window-manager-sizer-horizontal{flex-direction:column}.netless-window-manager-sizer:before,.netless-window-manager-sizer:after{flex:1;content:"";display:block}.netless-window-manager-chess-sizer:before,.netless-window-manager-chess-sizer:after{background-image:linear-gradient(45deg,#b0b0b0 25%,transparent 25%),linear-gradient(-45deg,#b0b0b0 25%,transparent 25%),linear-gradient(45deg,transparent 75%,#b0b0b0 75%),linear-gradient(-45deg,transparent 75%,#b0b0b0 75%);background-color:#fff;background-size:20px 20px;background-position:0 0,0 10px,10px -10px,-10px 0px}.netless-window-manager-wrapper{position:relative;z-index:1;width:100%;height:100%;overflow:hidden}.netless-window-manager-main-view{width:100%;height:100%}.netless-window-manager-cursor-pencil-image{width:26px;height:26px}.netless-window-manager-cursor-eraser-image{width:26px;height:26px}.netless-window-manager-cursor-selector-image{width:24px;height:24px}.netless-window-manager-cursor-selector-avatar{border-radius:50%;border-style:solid;border-width:2px;border-color:#fff;margin-bottom:2px}.netless-window-manager-cursor-selector-avatar img{width:12px}.netless-window-manager-cursor-inner{border-radius:4px;display:flex;align-items:center;justify-content:center;flex-direction:row;padding-left:4px;padding-right:4px;font-size:12px}.netless-window-manager-cursor-inner-mellow{height:32px;border-radius:16px;display:flex;align-items:center;justify-content:center;flex-direction:row;padding-left:16px;padding-right:16px}.netless-window-manager-cursor-tag-name{font-size:12px;margin-left:4px;padding:2px 8px;border-radius:4px}.netless-window-manager-cursor-mid{display:flex;flex-direction:column;align-items:center;justify-content:center;position:fixed;width:26px;height:26px;z-index:2147483647;left:0;top:0;will-change:transform;transition:transform .05s;transform-origin:0 0;user-select:none}.netless-window-manager-cursor-pencil-offset{margin-left:-20px}.netless-window-manager-cursor-selector-offset{margin-left:-22px;margin-top:56px}.netless-window-manager-cursor-text-offset{margin-left:-30px;margin-top:18px}.netless-window-manager-cursor-shape-offset{display:flex;flex-direction:column;align-items:center;justify-content:center;position:absolute;width:180px;height:64px;margin-left:-30px;margin-top:12px}.netless-window-manager-cursor-name{width:100%;height:48px;display:flex;align-items:center;justify-content:center;position:absolute;top:-40px}.cursor-image-wrapper{display:flex;justify-content:center}.tele-fancy-scrollbar{overscroll-behavior:contain;overflow:auto;overflow-y:scroll;overflow-y:overlay;-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar;scrollbar-width:auto}.tele-fancy-scrollbar::-webkit-scrollbar{height:8px;width:8px}.tele-fancy-scrollbar::-webkit-scrollbar-track{background-color:transparent}.tele-fancy-scrollbar::-webkit-scrollbar-thumb{background-color:#444e601a;background-color:transparent;border-radius:4px;transition:background-color .4s}.tele-fancy-scrollbar:hover::-webkit-scrollbar-thumb{background-color:#444e601a}.tele-fancy-scrollbar::-webkit-scrollbar-thumb:hover{background-color:#444e6033}.tele-fancy-scrollbar::-webkit-scrollbar-thumb:active{background-color:#444e6033}.tele-fancy-scrollbar::-webkit-scrollbar-thumb:vertical{min-height:50px}.tele-fancy-scrollbar::-webkit-scrollbar-thumb:horizontal{min-width:50px}.telebox-box{position:absolute;top:0;left:0;z-index:100;will-change:transform;transition:width .4s cubic-bezier(.4,.9,.71,1.02),height .4s cubic-bezier(.55,.82,.63,.95),opacity .6s cubic-bezier(.7,0,.84,0),transform .4s ease}.telebox-box-main{position:relative;width:100%;height:100%;display:flex;flex-direction:column;overflow:hidden;background:#f9f9fc;box-shadow:0 4px 10px #2f419226;border-radius:6px;border:1px solid #e3e3ec}.telebox-titlebar-wrap{flex-shrink:0;position:relative;z-index:1}.telebox-content-wrap{flex:1;width:100%;overflow:hidden;display:flex;justify-content:center;align-items:center}.telebox-content{width:100%;height:100%;position:relative}.telebox-footer-wrap{flex-shrink:0;display:flex;flex-direction:column}.telebox-footer-wrap:before{content:"";display:block;flex:1}.telebox-resize-handle{position:absolute;z-index:2147483647}.telebox-n{width:100%;height:5px;left:0;top:-5px;cursor:n-resize}.telebox-s{width:100%;height:5px;left:0;bottom:-5px;cursor:s-resize}.telebox-w{width:5px;height:100%;left:-5px;top:0;cursor:w-resize}.telebox-e{width:5px;height:100%;right:-5px;top:0;cursor:e-resize}.telebox-nw{width:15px;height:15px;top:-5px;left:-5px;cursor:nw-resize}.telebox-ne{width:15px;height:15px;top:-5px;right:-5px;cursor:ne-resize}.telebox-se{width:15px;height:15px;bottom:-5px;right:-5px;cursor:se-resize}.telebox-sw{width:15px;height:15px;bottom:-5px;left:-5px;cursor:sw-resize}.telebox-track-mask{position:fixed;top:0;left:0;z-index:2147483647;width:100%;height:100%;background:rgba(0,0,0,.0001);cursor:move}.telebox-cursor-n{cursor:n-resize}.telebox-cursor-s{cursor:s-resize}.telebox-cursor-w{cursor:w-resize}.telebox-cursor-e{cursor:e-resize}.telebox-cursor-nw{cursor:nw-resize}.telebox-cursor-ne{cursor:ne-resize}.telebox-cursor-se{cursor:se-resize}.telebox-cursor-sw{cursor:sw-resize}.telebox-maximized .telebox-resize-handles,.telebox-no-resize .telebox-resize-handles{display:none}.telebox-maximized{box-shadow:none;transition:none}.telebox-minimized{will-change:transform;transition:width 50ms cubic-bezier(.4,.9,.71,1.02),height 50ms cubic-bezier(.55,.82,.63,.95),opacity .6s cubic-bezier(.7,0,.84,0),transform .6s ease;opacity:0;pointer-events:none;user-select:none}.telebox-transforming{will-change:transform;transition:opacity .6s cubic-bezier(.7,0,.84,0)}.telebox-readonly .telebox-resize-handle{cursor:initial!important;pointer-events:none!important}.telebox-color-scheme-dark .telebox-box-main{color:#e9e9e9;background:#212126;border-color:#43434d}.telebox-titlebar{box-sizing:border-box;height:26px;display:flex;align-items:center;padding:0 16px;background:#fff;user-select:none;border-bottom:1px solid #eeeef7}.telebox-title{overflow:hidden;margin:0 24px 0 0;padding:0;font-size:14px;font-weight:400;font-family:PingFangSC-Regular,PingFang SC;white-space:nowrap;word-break:keep-all;text-overflow:ellipsis;color:#191919}.telebox-titlebar-btns{white-space:nowrap;word-break:keep-all;margin-left:auto;font-size:0}.telebox-titlebar-btn{width:22px;height:22px;padding:0;outline:0;border:none;background:0 0;cursor:pointer}.telebox-titlebar-btn~.telebox-titlebar-btn{margin-left:10px}.telebox-titlebar-btn-icon{width:22px;height:22px}.telebox-readonly .telebox-titlebar-btn{cursor:not-allowed}.telebox-titlebar-icon-minimize{background:center/cover no-repeat url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB2aWV3Qm94PSIwIDAgMjggMjgiPgogICAgPGRlZnM+CiAgICAgICAgPHBhdGggaWQ9ImEiIGQ9Ik0wIDBoMjh2MjhIMHoiIC8+CiAgICA8L2RlZnM+CiAgICA8ZyBmaWxsPSJub25lIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPgogICAgICAgIDxtYXNrIGlkPSJiIiBmaWxsPSIjZmZmIj4KICAgICAgICAgICAgPHVzZSB4bGluazpocmVmPSIjYSIgLz4KICAgICAgICA8L21hc2s+CiAgICAgICAgPHBhdGggZmlsbD0iI0E3QTdDQSIgZmlsbC1ydWxlPSJub256ZXJvIiBkPSJNOSAxM2gxMHYxLjZIOXoiIG1hc2s9InVybCgjYikiIC8+CiAgICA8L2c+Cjwvc3ZnPgo=)}.telebox-titlebar-icon-maximize{background:center/cover no-repeat url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB2aWV3Qm94PSIwIDAgMjggMjgiPgogICAgPGRlZnM+CiAgICAgICAgPHBhdGggaWQ9ImEiIGQ9Ik0wIDBoMjh2MjhIMHoiIC8+CiAgICA8L2RlZnM+CiAgICA8ZyBmaWxsPSJub25lIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPgogICAgICAgIDxtYXNrIGlkPSJiIiBmaWxsPSIjZmZmIj4KICAgICAgICAgICAgPHVzZSB4bGluazpocmVmPSIjYSIgLz4KICAgICAgICA8L21hc2s+CiAgICAgICAgPGcgZmlsbD0iI0E3QTdDQSIgZmlsbC1ydWxlPSJub256ZXJvIiBtYXNrPSJ1cmwoI2IpIj4KICAgICAgICAgICAgPHBhdGgKICAgICAgICAgICAgICAgIGQ9Ik0yMC40ODEgMTcuMWgxLjJ2NC41ODFIMTcuMXYtMS4yaDMuMzgxVjE3LjF6bS0xNC4xOTA1LS4wMDloMS4ydjMuMzgxaDMuMzgwOXYxLjJoLTQuNTgxdi00LjU4MXpNMTcuMSA2LjE5MDVoNC41ODF2NC41ODA5aC0xLjJ2LTMuMzgxSDE3LjF2LTEuMnptLTEwLjcwMDguMTA4N2g0Ljc5ODV2MS4ySDcuNTk5MnYzLjU5ODVoLTEuMlY2LjI5OTJ6IiAvPgogICAgICAgIDwvZz4KICAgIDwvZz4KPC9zdmc+Cg==)}.telebox-titlebar-icon-maximize.is-active{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB2aWV3Qm94PSIwIDAgMjggMjgiPgogICAgPGRlZnM+CiAgICAgICAgPHBhdGggaWQ9ImEiIGQ9Ik0wIDBoMjZ2MjZIMHoiIC8+CiAgICAgICAgPHBhdGggaWQ9ImMiIGQ9Ik0yNi44NjkgMEwyOCAxLjEzMVYyNi44N0wyNi44NjkgMjhIMS4xM0wwIDI2Ljg3VjEuMTMxTDEuMTMgMHoiIC8+CiAgICA8L2RlZnM+CiAgICA8ZyBmaWxsPSJub25lIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPgogICAgICAgIDxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKDEgMSkiPgogICAgICAgICAgICA8bWFzayBpZD0iYiIgZmlsbD0iI2ZmZiI+CiAgICAgICAgICAgICAgICA8dXNlIHhsaW5rOmhyZWY9IiNhIiAvPgogICAgICAgICAgICA8L21hc2s+CiAgICAgICAgICAgIDxwYXRoIGZpbGw9Im5vbmUiIGQ9Ik0tNC42NDI5LTQuNjQyOWgzNS4yODU4djM1LjI4NThILTQuNjQyOXoiIG1hc2s9InVybCgjYikiIC8+CiAgICAgICAgPC9nPgogICAgICAgIDxnPgogICAgICAgICAgICA8bWFzayBpZD0iZCIgZmlsbD0iI2ZmZiI+CiAgICAgICAgICAgICAgICA8dXNlIHhsaW5rOmhyZWY9IiNjIiAvPgogICAgICAgICAgICA8L21hc2s+CiAgICAgICAgICAgIDxwYXRoIGZpbGw9Im5vbmUiIGQ9Ik0tMTcuNTE2OCAxNEwxNC0xNy41MTY4IDQ1LjUxNjggMTQgMTQgNDUuNTE2OHoiIG1hc2s9InVybCgjZCkiIC8+CiAgICAgICAgPC9nPgogICAgICAgIDxwYXRoIHN0cm9rZT0iI0E3QTdDQSIgc3Ryb2tlLXdpZHRoPSIxLjIiCiAgICAgICAgICAgIGQ9Ik0xMC4wODg2IDIxLjQ4NjV2LTMuNjk2Nkg2LjM5Mk0yMS4zODU1IDEwLjE4OTVoLTMuNjk2NlY2LjQ5M00yMS40MDIgMTcuNzk4M2gtMy42OTY2djMuNjk2Nk0xMC4yNTAzIDYuMTQ5OHYzLjg5ODVINi4zNTE3IiAvPgogICAgPC9nPgo8L3N2Zz4K)}.telebox-titlebar-icon-close{background:center/cover no-repeat url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyOCAyOCI+CiAgICA8ZyBmaWxsPSJub25lIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiIHN0cm9rZT0iI0E3QTdDQSIgc3Ryb2tlLXdpZHRoPSIxLjQiPgogICAgICAgIDxwYXRoIGQ9Ik04LjM1MyAyMC4zMzIxTDIwLjMzMiA4LjM1M00yMC4zMzIyIDIwLjMzMjFMOC4zNTMgOC4zNTMiIC8+CiAgICA8L2c+Cjwvc3ZnPgo=)}.telebox-color-scheme-dark .telebox-titlebar{color:#e9e9e9;background:#43434d;border-bottom:none}.telebox-collector{visibility:hidden;display:block;position:absolute;z-index:200;width:40px;height:40px;margin:0;padding:0;border:none;outline:0;font-size:0;border-radius:50%;background:#fff;box-shadow:0 2px 6px #2f419226;cursor:pointer;user-select:none;pointer-events:none;background-repeat:no-repeat;background-size:18px 16px;background-position:center}.telebox-collector-visible{visibility:visible;pointer-events:initial}.telebox-collector-readonly{cursor:not-allowed}.telebox-color-scheme-dark.telebox-collector{background-color:#43434d}.telebox-max-titlebar{display:none;position:absolute;top:0;left:0;z-index:50000;user-select:none}.telebox-max-titlebar-maximized{display:flex}.telebox-titles{flex:1;height:100%;margin:0 16px 0 -16px;overflow-y:hidden;overflow-x:scroll;overflow-x:overlay;-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar;scrollbar-width:auto}.telebox-titles::-webkit-scrollbar{height:8px;width:8px}.telebox-titles::-webkit-scrollbar-track{background-color:transparent}.telebox-titles::-webkit-scrollbar-thumb{background-color:#eeeef7cc;background-color:transparent;border-radius:4px;transition:background-color .4s}.telebox-titles:hover::-webkit-scrollbar-thumb{background-color:#eeeef7cc}.telebox-titles::-webkit-scrollbar-thumb:hover{background-color:#eeeef7}.telebox-titles::-webkit-scrollbar-thumb:active{background-color:#eeeef7}.telebox-titles::-webkit-scrollbar-thumb:vertical{min-height:50px}.telebox-titles::-webkit-scrollbar-thumb:horizontal{min-width:50px}.telebox-titles-content{height:100%;display:flex;flex-wrap:nowrap;align-items:center;padding:0}.telebox-titles-tab{overflow:hidden;max-width:182px;min-width:50px;padding:0 26px 0 16px;outline:0;font-size:13px;font-family:PingFangSC-Regular,PingFang SC;font-weight:400;text-overflow:ellipsis;white-space:nowrap;word-break:keep-all;border:none;border-right:1px solid #e5e5f0;color:#7b88a0;background:0 0;cursor:pointer}.telebox-titles-tab~.telebox-titles-tab{margin-left:2px}.telebox-titles-tab-focus{color:#357bf6}.telebox-readonly .telebox-titles-tab{cursor:not-allowed}.telebox-color-scheme-dark{color-scheme:dark}.telebox-color-scheme-dark.telebox-titlebar{color:#e9e9e9;background:#43434d;border-bottom:none}.telebox-color-scheme-dark .telebox-titles-tab{border-right-color:#7b88a0}.telebox-color-scheme-dark .telebox-title{color:#e9e9e9}
1
+ .page-renderer-pages-container{position:relative;overflow:hidden}.page-renderer-page{position:absolute;top:0;left:0;will-change:transform;background-position:center;background-size:cover;background-repeat:no-repeat}.page-renderer-page-img{display:block;width:100%;height:auto;user-select:none}.netless-app-docs-viewer-static-scrollbar{position:absolute;top:0;right:0;z-index:2147483647;width:8px;min-height:30px;margin:0;padding:0;border:none;outline:none;border-radius:4px;background:rgba(68,78,96,.4);box-shadow:1px 1px 8px #ffffffb3;opacity:0;transition:background .4s,opacity .4s 3s,transform .2s;will-change:transform,height;user-select:none}.netless-app-docs-viewer-static-scrollbar.netless-app-docs-viewer-static-scrollbar-dragging{background:rgba(68,78,96,.6);opacity:1;transition:background .4s,opacity .4s 3s!important}.netless-app-docs-viewer-static-scrollbar:hover,.netless-app-docs-viewer-static-scrollbar:focus{background:rgba(68,78,96,.5)}.netless-app-docs-viewer-static-scrollbar:active{background:rgba(68,78,96,.6)}.netless-app-docs-viewer-content:hover .netless-app-docs-viewer-static-scrollbar{opacity:1;transition:background .4s,opacity .4s,transform .2s}.netless-app-docs-viewer-readonly .netless-app-docs-viewer-static-scrollbar{display:none}.netless-app-docs-viewer-static-pages:hover .netless-app-docs-viewer-static-scrollbar{opacity:1;transition:background .4s,opacity .4s,transform .2s}.netless-window-manager-playground{width:100%;height:100%;position:relative;z-index:1;overflow:hidden;user-select:none}.netless-window-manager-sizer{position:absolute;top:0;left:0;width:100%;height:100%;z-index:1;overflow:hidden;display:flex}.netless-window-manager-sizer-horizontal{flex-direction:column}.netless-window-manager-sizer:before,.netless-window-manager-sizer:after{flex:1;content:"";display:block}.netless-window-manager-chess-sizer:before,.netless-window-manager-chess-sizer:after{background-image:linear-gradient(45deg,#b0b0b0 25%,transparent 25%),linear-gradient(-45deg,#b0b0b0 25%,transparent 25%),linear-gradient(45deg,transparent 75%,#b0b0b0 75%),linear-gradient(-45deg,transparent 75%,#b0b0b0 75%);background-color:#fff;background-size:20px 20px;background-position:0 0,0 10px,10px -10px,-10px 0px}.netless-window-manager-wrapper{position:relative;z-index:1;width:100%;height:100%;overflow:hidden}.netless-window-manager-main-view{width:100%;height:100%}.netless-window-manager-cursor-pencil-image{width:26px;height:26px}.netless-window-manager-cursor-eraser-image{width:26px;height:26px}.netless-window-manager-cursor-selector-image{width:24px;height:24px}.netless-window-manager-cursor-selector-avatar{border-radius:50%;border-style:solid;border-width:2px;border-color:#fff;margin-bottom:2px}.netless-window-manager-cursor-selector-avatar img{width:12px}.netless-window-manager-cursor-inner{border-radius:4px;display:flex;align-items:center;justify-content:center;flex-direction:row;padding-left:4px;padding-right:4px;font-size:12px}.netless-window-manager-cursor-inner-mellow{height:32px;border-radius:16px;display:flex;align-items:center;justify-content:center;flex-direction:row;padding-left:16px;padding-right:16px}.netless-window-manager-cursor-tag-name{font-size:12px;margin-left:4px;padding:2px 8px;border-radius:4px}.netless-window-manager-cursor-mid{display:flex;flex-direction:column;align-items:center;justify-content:center;position:absolute;width:26px;height:26px;z-index:2147483647;left:0;top:0;will-change:transform;transition:transform .05s;transform-origin:0 0;user-select:none}.netless-window-manager-cursor-pencil-offset{margin-left:-20px}.netless-window-manager-cursor-selector-offset{margin-left:-22px;margin-top:56px}.netless-window-manager-cursor-text-offset{margin-left:-30px;margin-top:18px}.netless-window-manager-cursor-shape-offset{display:flex;flex-direction:column;align-items:center;justify-content:center;position:absolute;width:180px;height:64px;margin-left:-30px;margin-top:12px}.netless-window-manager-cursor-name{width:100%;height:48px;display:flex;align-items:center;justify-content:center;position:absolute;top:-40px}.cursor-image-wrapper{display:flex;justify-content:center}.telebox-collector{position:absolute;right:10px;bottom:15px}.tele-fancy-scrollbar{overscroll-behavior:contain;overflow:auto;overflow-y:scroll;overflow-y:overlay;-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar;scrollbar-width:auto}.tele-fancy-scrollbar::-webkit-scrollbar{height:8px;width:8px}.tele-fancy-scrollbar::-webkit-scrollbar-track{background-color:transparent}.tele-fancy-scrollbar::-webkit-scrollbar-thumb{background-color:#444e601a;background-color:transparent;border-radius:4px;transition:background-color .4s}.tele-fancy-scrollbar:hover::-webkit-scrollbar-thumb{background-color:#444e601a}.tele-fancy-scrollbar::-webkit-scrollbar-thumb:hover{background-color:#444e6033}.tele-fancy-scrollbar::-webkit-scrollbar-thumb:active{background-color:#444e6033}.tele-fancy-scrollbar::-webkit-scrollbar-thumb:vertical{min-height:50px}.tele-fancy-scrollbar::-webkit-scrollbar-thumb:horizontal{min-width:50px}.telebox-box{position:absolute;top:0;left:0;z-index:100;will-change:transform;transition:width .4s cubic-bezier(.4,.9,.71,1.02),height .4s cubic-bezier(.55,.82,.63,.95),opacity .6s cubic-bezier(.7,0,.84,0),transform .4s ease}.telebox-box-main{position:relative;width:100%;height:100%;display:flex;flex-direction:column;overflow:hidden;background:#f9f9fc;box-shadow:0 4px 10px #2f419226;border-radius:6px;border:1px solid #e3e3ec}.telebox-titlebar-wrap{flex-shrink:0;position:relative;z-index:1}.telebox-content-wrap{flex:1;width:100%;overflow:hidden;display:flex;justify-content:center;align-items:center}.telebox-content{width:100%;height:100%;position:relative}.telebox-footer-wrap{flex-shrink:0;display:flex;flex-direction:column}.telebox-footer-wrap:before{content:"";display:block;flex:1}.telebox-resize-handle{position:absolute;z-index:2147483647}.telebox-n{width:100%;height:5px;left:0;top:-5px;cursor:n-resize}.telebox-s{width:100%;height:5px;left:0;bottom:-5px;cursor:s-resize}.telebox-w{width:5px;height:100%;left:-5px;top:0;cursor:w-resize}.telebox-e{width:5px;height:100%;right:-5px;top:0;cursor:e-resize}.telebox-nw{width:15px;height:15px;top:-5px;left:-5px;cursor:nw-resize}.telebox-ne{width:15px;height:15px;top:-5px;right:-5px;cursor:ne-resize}.telebox-se{width:15px;height:15px;bottom:-5px;right:-5px;cursor:se-resize}.telebox-sw{width:15px;height:15px;bottom:-5px;left:-5px;cursor:sw-resize}.telebox-track-mask{position:fixed;top:0;left:0;z-index:2147483647;width:100%;height:100%;background:rgba(0,0,0,.0001);cursor:move}.telebox-cursor-n{cursor:n-resize}.telebox-cursor-s{cursor:s-resize}.telebox-cursor-w{cursor:w-resize}.telebox-cursor-e{cursor:e-resize}.telebox-cursor-nw{cursor:nw-resize}.telebox-cursor-ne{cursor:ne-resize}.telebox-cursor-se{cursor:se-resize}.telebox-cursor-sw{cursor:sw-resize}.telebox-maximized .telebox-resize-handles,.telebox-no-resize .telebox-resize-handles{display:none}.telebox-maximized{box-shadow:none;transition:none}.telebox-minimized{will-change:transform;transition:width 50ms cubic-bezier(.4,.9,.71,1.02),height 50ms cubic-bezier(.55,.82,.63,.95),opacity .6s cubic-bezier(.7,0,.84,0),transform .6s ease;opacity:0;pointer-events:none;user-select:none}.telebox-transforming{will-change:transform;transition:opacity .6s cubic-bezier(.7,0,.84,0)}.telebox-readonly .telebox-resize-handle{cursor:initial!important;pointer-events:none!important}.telebox-color-scheme-dark .telebox-box-main{color:#e9e9e9;background:#212126;border-color:#43434d}.telebox-titlebar{box-sizing:border-box;height:26px;display:flex;align-items:center;padding:0 16px;background:#fff;user-select:none;border-bottom:1px solid #eeeef7}.telebox-title{overflow:hidden;margin:0 24px 0 0;padding:0;font-size:14px;font-weight:400;font-family:PingFangSC-Regular,PingFang SC;white-space:nowrap;word-break:keep-all;text-overflow:ellipsis;color:#191919}.telebox-titlebar-btns{white-space:nowrap;word-break:keep-all;margin-left:auto;font-size:0}.telebox-titlebar-btn{width:22px;height:22px;padding:0;outline:0;border:none;background:0 0;cursor:pointer}.telebox-titlebar-btn~.telebox-titlebar-btn{margin-left:10px}.telebox-titlebar-btn-icon{width:22px;height:22px}.telebox-readonly .telebox-titlebar-btn{cursor:not-allowed}.telebox-titlebar-icon-minimize{background:center/cover no-repeat url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB2aWV3Qm94PSIwIDAgMjggMjgiPgogICAgPGRlZnM+CiAgICAgICAgPHBhdGggaWQ9ImEiIGQ9Ik0wIDBoMjh2MjhIMHoiIC8+CiAgICA8L2RlZnM+CiAgICA8ZyBmaWxsPSJub25lIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPgogICAgICAgIDxtYXNrIGlkPSJiIiBmaWxsPSIjZmZmIj4KICAgICAgICAgICAgPHVzZSB4bGluazpocmVmPSIjYSIgLz4KICAgICAgICA8L21hc2s+CiAgICAgICAgPHBhdGggZmlsbD0iI0E3QTdDQSIgZmlsbC1ydWxlPSJub256ZXJvIiBkPSJNOSAxM2gxMHYxLjZIOXoiIG1hc2s9InVybCgjYikiIC8+CiAgICA8L2c+Cjwvc3ZnPgo=)}.telebox-titlebar-icon-maximize{background:center/cover no-repeat url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB2aWV3Qm94PSIwIDAgMjggMjgiPgogICAgPGRlZnM+CiAgICAgICAgPHBhdGggaWQ9ImEiIGQ9Ik0wIDBoMjh2MjhIMHoiIC8+CiAgICA8L2RlZnM+CiAgICA8ZyBmaWxsPSJub25lIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPgogICAgICAgIDxtYXNrIGlkPSJiIiBmaWxsPSIjZmZmIj4KICAgICAgICAgICAgPHVzZSB4bGluazpocmVmPSIjYSIgLz4KICAgICAgICA8L21hc2s+CiAgICAgICAgPGcgZmlsbD0iI0E3QTdDQSIgZmlsbC1ydWxlPSJub256ZXJvIiBtYXNrPSJ1cmwoI2IpIj4KICAgICAgICAgICAgPHBhdGgKICAgICAgICAgICAgICAgIGQ9Ik0yMC40ODEgMTcuMWgxLjJ2NC41ODFIMTcuMXYtMS4yaDMuMzgxVjE3LjF6bS0xNC4xOTA1LS4wMDloMS4ydjMuMzgxaDMuMzgwOXYxLjJoLTQuNTgxdi00LjU4MXpNMTcuMSA2LjE5MDVoNC41ODF2NC41ODA5aC0xLjJ2LTMuMzgxSDE3LjF2LTEuMnptLTEwLjcwMDguMTA4N2g0Ljc5ODV2MS4ySDcuNTk5MnYzLjU5ODVoLTEuMlY2LjI5OTJ6IiAvPgogICAgICAgIDwvZz4KICAgIDwvZz4KPC9zdmc+Cg==)}.telebox-titlebar-icon-maximize.is-active{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB2aWV3Qm94PSIwIDAgMjggMjgiPgogICAgPGRlZnM+CiAgICAgICAgPHBhdGggaWQ9ImEiIGQ9Ik0wIDBoMjZ2MjZIMHoiIC8+CiAgICAgICAgPHBhdGggaWQ9ImMiIGQ9Ik0yNi44NjkgMEwyOCAxLjEzMVYyNi44N0wyNi44NjkgMjhIMS4xM0wwIDI2Ljg3VjEuMTMxTDEuMTMgMHoiIC8+CiAgICA8L2RlZnM+CiAgICA8ZyBmaWxsPSJub25lIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPgogICAgICAgIDxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKDEgMSkiPgogICAgICAgICAgICA8bWFzayBpZD0iYiIgZmlsbD0iI2ZmZiI+CiAgICAgICAgICAgICAgICA8dXNlIHhsaW5rOmhyZWY9IiNhIiAvPgogICAgICAgICAgICA8L21hc2s+CiAgICAgICAgICAgIDxwYXRoIGZpbGw9Im5vbmUiIGQ9Ik0tNC42NDI5LTQuNjQyOWgzNS4yODU4djM1LjI4NThILTQuNjQyOXoiIG1hc2s9InVybCgjYikiIC8+CiAgICAgICAgPC9nPgogICAgICAgIDxnPgogICAgICAgICAgICA8bWFzayBpZD0iZCIgZmlsbD0iI2ZmZiI+CiAgICAgICAgICAgICAgICA8dXNlIHhsaW5rOmhyZWY9IiNjIiAvPgogICAgICAgICAgICA8L21hc2s+CiAgICAgICAgICAgIDxwYXRoIGZpbGw9Im5vbmUiIGQ9Ik0tMTcuNTE2OCAxNEwxNC0xNy41MTY4IDQ1LjUxNjggMTQgMTQgNDUuNTE2OHoiIG1hc2s9InVybCgjZCkiIC8+CiAgICAgICAgPC9nPgogICAgICAgIDxwYXRoIHN0cm9rZT0iI0E3QTdDQSIgc3Ryb2tlLXdpZHRoPSIxLjIiCiAgICAgICAgICAgIGQ9Ik0xMC4wODg2IDIxLjQ4NjV2LTMuNjk2Nkg2LjM5Mk0yMS4zODU1IDEwLjE4OTVoLTMuNjk2NlY2LjQ5M00yMS40MDIgMTcuNzk4M2gtMy42OTY2djMuNjk2Nk0xMC4yNTAzIDYuMTQ5OHYzLjg5ODVINi4zNTE3IiAvPgogICAgPC9nPgo8L3N2Zz4K)}.telebox-titlebar-icon-close{background:center/cover no-repeat url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyOCAyOCI+CiAgICA8ZyBmaWxsPSJub25lIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiIHN0cm9rZT0iI0E3QTdDQSIgc3Ryb2tlLXdpZHRoPSIxLjQiPgogICAgICAgIDxwYXRoIGQ9Ik04LjM1MyAyMC4zMzIxTDIwLjMzMiA4LjM1M00yMC4zMzIyIDIwLjMzMjFMOC4zNTMgOC4zNTMiIC8+CiAgICA8L2c+Cjwvc3ZnPgo=)}.telebox-color-scheme-dark .telebox-titlebar{color:#e9e9e9;background:#43434d;border-bottom:none}.telebox-collector{visibility:hidden;display:block;position:absolute;z-index:200;width:40px;height:40px;margin:0;padding:0;border:none;outline:0;font-size:0;border-radius:50%;background:#fff;box-shadow:0 2px 6px #2f419226;cursor:pointer;user-select:none;pointer-events:none;background-repeat:no-repeat;background-size:18px 16px;background-position:center}.telebox-collector-visible{visibility:visible;pointer-events:initial}.telebox-collector-readonly{cursor:not-allowed}.telebox-color-scheme-dark.telebox-collector{background-color:#43434d}.telebox-max-titlebar{display:none;position:absolute;top:0;left:0;z-index:50000;user-select:none}.telebox-max-titlebar-maximized{display:flex}.telebox-titles{flex:1;height:100%;margin:0 16px 0 -16px;overflow-y:hidden;overflow-x:scroll;overflow-x:overlay;-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar;scrollbar-width:auto}.telebox-titles::-webkit-scrollbar{height:8px;width:8px}.telebox-titles::-webkit-scrollbar-track{background-color:transparent}.telebox-titles::-webkit-scrollbar-thumb{background-color:#eeeef7cc;background-color:transparent;border-radius:4px;transition:background-color .4s}.telebox-titles:hover::-webkit-scrollbar-thumb{background-color:#eeeef7cc}.telebox-titles::-webkit-scrollbar-thumb:hover{background-color:#eeeef7}.telebox-titles::-webkit-scrollbar-thumb:active{background-color:#eeeef7}.telebox-titles::-webkit-scrollbar-thumb:vertical{min-height:50px}.telebox-titles::-webkit-scrollbar-thumb:horizontal{min-width:50px}.telebox-titles-content{height:100%;display:flex;flex-wrap:nowrap;align-items:center;padding:0}.telebox-titles-tab{overflow:hidden;max-width:182px;min-width:50px;padding:0 26px 0 16px;outline:0;font-size:13px;font-family:PingFangSC-Regular,PingFang SC;font-weight:400;text-overflow:ellipsis;white-space:nowrap;word-break:keep-all;border:none;border-right:1px solid #e5e5f0;color:#7b88a0;background:0 0;cursor:pointer}.telebox-titles-tab~.telebox-titles-tab{margin-left:2px}.telebox-titles-tab-focus{color:#357bf6}.telebox-readonly .telebox-titles-tab{cursor:not-allowed}.telebox-color-scheme-dark{color-scheme:dark}.telebox-color-scheme-dark.telebox-titlebar{color:#e9e9e9;background:#43434d;border-bottom:none}.telebox-color-scheme-dark .telebox-titles-tab{border-right-color:#7b88a0}.telebox-color-scheme-dark .telebox-title{color:#e9e9e9}
package/dist/typings.d.ts CHANGED
@@ -70,3 +70,4 @@ export declare type AppListenerKeys = keyof AppEmitterEvent;
70
70
  export type { AppContext } from "./AppContext";
71
71
  export type { ReadonlyTeleBox, TeleBoxRect };
72
72
  export type { SceneState, SceneDefinition, View, AnimationMode, Displayer, Room, Player };
73
+ export type { Storage, StorageStateChangedEvent, StorageStateChangedListener } from "./App/Storage";
package/docs/api.md CHANGED
@@ -4,6 +4,8 @@
4
4
  - [静态方法](#static-methods)
5
5
  - [`mount`](#mount)
6
6
  - [`register`](#register)
7
+ - [`setContainer`](#set-container)
8
+ - [`setCollectorContainer`](#set-collector-container)
7
9
  - [实例方法](#instance-methods)
8
10
  - [`addApp`](#addApp)
9
11
  - [`closeApp`](#closeApp)
@@ -63,6 +65,21 @@ WindowManager.register({
63
65
  })
64
66
  ```
65
67
 
68
+ <h3 id="set-container">setContainer</h3>
69
+
70
+ > 设置白板挂载容器
71
+
72
+ ```typescript
73
+ WindowManager.setContainer(document.getElementById("container"));
74
+ ```
75
+
76
+ <h3 id="set-container">setCollectorContainer</h3>
77
+
78
+ > 设置 `Collector` 挂载的容器
79
+
80
+ ```typescript
81
+ WindowManager.setCollectorContainer(document.getElementById("collector-container"));
82
+ ```
66
83
 
67
84
  <h2 id="instance-methods">实例方法</h2>
68
85
 
@@ -0,0 +1,42 @@
1
+
2
+ ### 注意事项
3
+
4
+ 多窗口模式必须开启白板的 `useMultiViews` 和 `useMobXState` 选项
5
+
6
+ 会造成原本以下 `room` 上的一些方法和 `state` 失效
7
+
8
+ `方法`
9
+
10
+ - `room.bindHtmlElement()` 用 `WindowManager.mount()` 代替
11
+ - `room.scalePptToFit()` 暂无代替,不再推荐调用 `scalePptToFit`
12
+ - `room.setScenePath()` 用 `manager.setMainViewScenePath()` 代替
13
+ - `room.setSceneIndex()` 用 `manager.setMainViewSceneIndex()` 代替
14
+
15
+ > 为了方便使用 `manager` 替换了 `room` 上的一些方法可以直接对 `mainView` 生效
16
+
17
+ - `room.disableCameraTransform`
18
+ - `room.moveCamera`
19
+ - `room.moveCameraToContain`
20
+ - `room.convertToPointInWorld`
21
+ - `room.setCameraBound`
22
+
23
+ `camera`
24
+
25
+ - `room.state.cameraState` 用 `manager.mainView.camera` 和 `manager.mainView.size` 代替
26
+
27
+ 想要监听主白板 `camera` 的变化, 请使用如下方式代替
28
+
29
+ ```javascript
30
+ manager.mainView.callbacks.on("onCameraUpdated", camera => {
31
+ console.log(camera);
32
+ });
33
+ ```
34
+
35
+ 监听主白板 `size` 变化
36
+
37
+ ```javascript
38
+ manager.mainView.callbacks.on("onSizeUpdated", size => {
39
+ console.log(size);
40
+ });
41
+ ```
42
+
package/package.json CHANGED
@@ -1,10 +1,11 @@
1
1
  {
2
2
  "name": "@netless/window-manager",
3
- "version": "0.3.17",
3
+ "version": "0.4.0-canary.10",
4
4
  "description": "",
5
5
  "main": "dist/index.es.js",
6
6
  "module": "dist/index.es.js",
7
7
  "types": "dist/index.d.ts",
8
+ "repository": "netless-io/window-manager",
8
9
  "scripts": {
9
10
  "prettier": "prettier --write .",
10
11
  "build": "vite build && yarn type-gen",
@@ -22,12 +23,13 @@
22
23
  },
23
24
  "dependencies": {
24
25
  "@juggle/resize-observer": "^3.3.1",
25
- "@netless/app-docs-viewer": "0.1.26",
26
+ "@netless/app-docs-viewer": "0.2.0",
26
27
  "@netless/app-media-player": "0.1.0-beta.5",
27
- "@netless/telebox-insider": "^0.2.16",
28
+ "@netless/telebox-insider": "0.2.18",
28
29
  "emittery": "^0.9.2",
29
30
  "lodash": "^4.17.21",
30
31
  "p-retry": "^4.6.1",
32
+ "side-effect-manager": "^0.1.5",
31
33
  "uuid": "^7.0.3",
32
34
  "video.js": ">=7"
33
35
  },
@@ -56,6 +58,6 @@
56
58
  "typescript": "^4.3.5",
57
59
  "video.js": "^7.14.3",
58
60
  "vite": "^2.5.3",
59
- "white-web-sdk": "^2.15.12"
61
+ "white-web-sdk": "^2.16.0"
60
62
  }
61
63
  }
@@ -0,0 +1,21 @@
1
+ export type StorageEventListener<T> = (event: T) => void;
2
+
3
+ export class StorageEvent<TMessage> {
4
+ listeners = new Set<StorageEventListener<TMessage>>();
5
+
6
+ get length(): number {
7
+ return this.listeners.size;
8
+ }
9
+
10
+ dispatch(message: TMessage): void {
11
+ this.listeners.forEach(callback => callback(message));
12
+ }
13
+
14
+ addListener(listener: StorageEventListener<TMessage>): void {
15
+ this.listeners.add(listener);
16
+ }
17
+
18
+ removeListener(listener: StorageEventListener<TMessage>): void {
19
+ this.listeners.delete(listener);
20
+ }
21
+ }
@@ -0,0 +1,243 @@
1
+ import type { AkkoObjectUpdatedProperty } from "white-web-sdk";
2
+ import { get, has, isObject } from "lodash";
3
+ import { SideEffectManager } from "side-effect-manager";
4
+ import type { AppContext } from "../../AppContext";
5
+ import { safeListenPropsUpdated } from "../../Utils/Reactive";
6
+ import { isRef, makeRef, plainObjectKeys } from "./utils";
7
+ import type { Diff, MaybeRefValue, RefValue, StorageStateChangedEvent } from "./typings";
8
+ import { StorageEvent } from "./StorageEvent";
9
+
10
+ export * from './typings';
11
+
12
+ const STORAGE_NS = "_WM-STORAGE_";
13
+
14
+ export class Storage<TState = any> implements Storage<TState> {
15
+ readonly id: string;
16
+
17
+ private readonly _context: AppContext<{ [STORAGE_NS]: TState }>;
18
+ private readonly _sideEffect = new SideEffectManager();
19
+ private _state: TState;
20
+ private _destroyed = false;
21
+
22
+ private _refMap = new WeakMap<any, RefValue>();
23
+
24
+ /**
25
+ * `setState` alters local state immediately before sending to server. This will cache the old value for onStateChanged diffing.
26
+ */
27
+ private _lastValue = new Map<string | number | symbol, TState[Extract<keyof TState, string>]>();
28
+
29
+ constructor(context: AppContext<any>, id: string, defaultState?: TState) {
30
+ if (id == null) {
31
+ throw new Error("Cannot create Storage with empty id.");
32
+ }
33
+
34
+ if (defaultState && !isObject(defaultState)) {
35
+ throw new Error(`Default state for Storage ${id} is not an object.`);
36
+ }
37
+
38
+ this._context = context;
39
+ this.id = id;
40
+
41
+ const attrs = context.getAttributes();
42
+ this._state = {} as TState;
43
+ const rawState = get<TState>(attrs, [STORAGE_NS, id], this._state);
44
+
45
+ if (this._context.getIsWritable()) {
46
+ if (!isObject(rawState) || rawState === this._state) {
47
+ if (!attrs[STORAGE_NS]) {
48
+ this._context.updateAttributes([STORAGE_NS], {});
49
+ }
50
+ this._context.updateAttributes([STORAGE_NS, this.id], this._state);
51
+ if (defaultState) {
52
+ this.setState(defaultState);
53
+ }
54
+ } else {
55
+ // strip mobx
56
+ plainObjectKeys(rawState).forEach(key => {
57
+ try {
58
+ const rawValue = isObject(rawState[key]) ? JSON.parse(JSON.stringify(rawState[key])) : rawState[key];
59
+ if (isRef<TState[Extract<keyof TState, string>]>(rawValue)) {
60
+ this._state[key] = rawValue.v;
61
+ if (isObject(rawValue.v)) {
62
+ this._refMap.set(rawValue.v, rawValue);
63
+ }
64
+ } else {
65
+ this._state[key] = rawValue;
66
+ }
67
+ } catch (e) {
68
+ console.error(e);
69
+ }
70
+ });
71
+ }
72
+ }
73
+
74
+ this._sideEffect.addDisposer(
75
+ safeListenPropsUpdated(
76
+ () => get(context.getAttributes(), [STORAGE_NS, this.id]),
77
+ this._updateProperties.bind(this),
78
+ this.destroy.bind(this)
79
+ )
80
+ );
81
+ }
82
+
83
+ get state(): Readonly<TState> {
84
+ if (this._destroyed) {
85
+ console.warn(`Accessing state on destroyed Storage "${this.id}"`)
86
+ }
87
+ return this._state;
88
+ }
89
+
90
+ readonly onStateChanged = new StorageEvent<StorageStateChangedEvent<TState>>();
91
+
92
+ ensureState(state: Partial<TState>): void {
93
+ return this.setState(
94
+ plainObjectKeys(state).reduce((payload, key) => {
95
+ if (!has(this._state, key)) {
96
+ payload[key] = state[key];
97
+ }
98
+ return payload;
99
+ }, {} as Partial<TState>)
100
+ );
101
+ }
102
+
103
+ setState(state: Partial<TState>): void {
104
+ if (this._destroyed) {
105
+ console.error(new Error(`Cannot call setState on destroyed Storage "${this.id}".`));
106
+ return;
107
+ }
108
+
109
+ if (!this._context.getIsWritable()) {
110
+ console.error(new Error(`Cannot setState on Storage "${this.id}" without writable access`), state);
111
+ return;
112
+ }
113
+
114
+ const keys = plainObjectKeys(state);
115
+ if (keys.length > 0) {
116
+ keys.forEach(key => {
117
+ const value = state[key];
118
+ if (value === this._state[key]) {
119
+ return;
120
+ }
121
+
122
+ if (value === void 0) {
123
+ this._lastValue.set(key, this._state[key]);
124
+ delete this._state[key];
125
+ this._context.updateAttributes([STORAGE_NS, this.id, key], value);
126
+ } else {
127
+ this._lastValue.set(key, this._state[key]);
128
+ this._state[key] = value as TState[Extract<keyof TState, string>];
129
+
130
+ let payload: MaybeRefValue<typeof value> = value;
131
+ if (isObject(value)) {
132
+ let refValue = this._refMap.get(value);
133
+ if (!refValue) {
134
+ refValue = makeRef(value);
135
+ this._refMap.set(value, refValue);
136
+ }
137
+ payload = refValue;
138
+ }
139
+
140
+ this._context.updateAttributes([STORAGE_NS, this.id, key], payload);
141
+ }
142
+ });
143
+ }
144
+ }
145
+
146
+ emptyStore(): void {
147
+ if (this._destroyed) {
148
+ console.error(new Error(`Cannot empty destroyed Storage "${this.id}".`));
149
+ return;
150
+ }
151
+
152
+ if (!this._context.getIsWritable()) {
153
+ console.error(new Error(`Cannot empty Storage "${this.id}" without writable access.`));
154
+ return;
155
+ }
156
+
157
+ this._context.updateAttributes([STORAGE_NS, this.id], {});
158
+ }
159
+
160
+ deleteStore(): void {
161
+ if (!this._context.getIsWritable()) {
162
+ console.error(new Error(`Cannot delete Storage "${this.id}" without writable access.`));
163
+ return;
164
+ }
165
+
166
+ this.destroy();
167
+
168
+ this._context.updateAttributes([STORAGE_NS, this.id], void 0);
169
+ }
170
+
171
+ get destroyed(): boolean {
172
+ return this._destroyed;
173
+ }
174
+
175
+ destroy() {
176
+ this._destroyed = true;
177
+ this._sideEffect.flushAll();
178
+ }
179
+
180
+ private _updateProperties(actions: ReadonlyArray<AkkoObjectUpdatedProperty<TState, string>>): void {
181
+ if (this._destroyed) {
182
+ console.error(new Error(`Cannot call _updateProperties on destroyed Storage "${this.id}".`));
183
+ return;
184
+ }
185
+
186
+ if (actions.length > 0) {
187
+ const diffs: Diff<TState> = {};
188
+
189
+ for (let i = 0; i < actions.length; i++) {
190
+ try {
191
+ const action = actions[i]
192
+ const key = action.key as Extract<keyof TState, string>;
193
+ const value = isObject(action.value) ? JSON.parse(JSON.stringify(action.value)) : action.value;
194
+ let oldValue: TState[Extract<keyof TState, string>] | undefined;
195
+ if (this._lastValue.has(key)) {
196
+ oldValue = this._lastValue.get(key);
197
+ this._lastValue.delete(key);
198
+ }
199
+
200
+ switch (action.kind) {
201
+ case 2: {
202
+ // Removed
203
+ if (has(this._state, key)) {
204
+ oldValue = this._state[key];
205
+ delete this._state[key];
206
+ }
207
+ diffs[key] = { oldValue };
208
+ break;
209
+ }
210
+ default: {
211
+ let newValue = value;
212
+
213
+ if (isRef<TState[Extract<keyof TState, string>]>(value)) {
214
+ const { k, v } = value;
215
+ const curValue = this._state[key];
216
+ if (isObject(curValue) && this._refMap.get(curValue)?.k === k) {
217
+ newValue = curValue;
218
+ } else {
219
+ newValue = v;
220
+ if (isObject(v)) {
221
+ this._refMap.set(v, value);
222
+ }
223
+ }
224
+ }
225
+
226
+ if (newValue !== this._state[key]) {
227
+ oldValue = this._state[key];
228
+ this._state[key] = newValue;
229
+ }
230
+
231
+ diffs[key] = { newValue, oldValue };
232
+ break;
233
+ }
234
+ }
235
+ } catch (e) {
236
+ console.error(e)
237
+ }
238
+ }
239
+
240
+ this.onStateChanged.dispatch(diffs);
241
+ }
242
+ }
243
+ }
@@ -0,0 +1,21 @@
1
+ import type { StorageEventListener } from "./StorageEvent";
2
+
3
+ export type RefValue<TValue = any> = { k: string; v: TValue; __isRef: true };
4
+
5
+ export type ExtractRawValue<TValue> = TValue extends RefValue<infer TRefValue> ? TRefValue : TValue;
6
+
7
+ export type AutoRefValue<TValue> = RefValue<ExtractRawValue<TValue>>;
8
+
9
+ export type MaybeRefValue<TValue> = TValue | AutoRefValue<TValue>;
10
+
11
+ export type DiffOne<T> = { oldValue?: T; newValue?: T };
12
+
13
+ export type Diff<T> = { [K in keyof T]?: DiffOne<T[K]> };
14
+
15
+ export type StorageOnSetStatePayload<TState = unknown> = {
16
+ [K in keyof TState]?: MaybeRefValue<TState[K]>;
17
+ };
18
+
19
+ export type StorageStateChangedEvent<TState = any> = Diff<TState>
20
+
21
+ export type StorageStateChangedListener<TState = any> = StorageEventListener<StorageStateChangedEvent<TState>>
@@ -0,0 +1,17 @@
1
+ import { has } from "lodash";
2
+ import { genUID } from "side-effect-manager";
3
+ import type { AutoRefValue, ExtractRawValue, RefValue } from "./typings";
4
+
5
+ export const plainObjectKeys = Object.keys as <T>(o: T) => Array<Extract<keyof T, string>>;
6
+
7
+ export function isRef<TValue = unknown>(e: unknown): e is RefValue<TValue> {
8
+ return Boolean(has(e, '__isRef'));
9
+ }
10
+
11
+ export function makeRef<TValue>(v: TValue): RefValue<TValue> {
12
+ return { k: genUID(), v, __isRef: true };
13
+ }
14
+
15
+ export function makeAutoRef<TValue>(v: TValue): AutoRefValue<TValue> {
16
+ return isRef<ExtractRawValue<TValue>>(v) ? v : makeRef(v as ExtractRawValue<TValue>);
17
+ }
package/src/AppContext.ts CHANGED
@@ -15,8 +15,9 @@ import type { BoxManager } from "./BoxManager";
15
15
  import type { AppEmitterEvent } from "./index";
16
16
  import type { AppManager } from "./AppManager";
17
17
  import type { AppProxy } from "./AppProxy";
18
+ import { Storage } from './App/Storage';
18
19
 
19
- export class AppContext<TAttrs extends Record<string, any>, AppOptions = any> {
20
+ export class AppContext<TAttrs extends Record<string, any> = any, AppOptions = any> {
20
21
  public readonly emitter: Emittery<AppEmitterEvent<TAttrs>>;
21
22
  public readonly mobxUtils = {
22
23
  autorun,
@@ -29,19 +30,19 @@ export class AppContext<TAttrs extends Record<string, any>, AppOptions = any> {
29
30
  listenDisposed,
30
31
  unlistenDisposed
31
32
  };
32
- private boxManager: BoxManager;
33
+
33
34
  private store = this.manager.store;
34
35
  public readonly isAddApp: boolean;
35
36
  public readonly isReplay = this.manager.isReplay;
36
37
 
37
38
  constructor(
38
39
  private manager: AppManager,
40
+ private boxManager: BoxManager,
39
41
  public appId: string,
40
42
  private appProxy: AppProxy,
41
43
  private appOptions?: AppOptions | (() => AppOptions),
42
44
  ) {
43
45
  this.emitter = appProxy.appEmitter;
44
- this.boxManager = this.manager.boxManager;
45
46
  this.isAddApp = appProxy.isAddApp;
46
47
  }
47
48
 
@@ -103,7 +104,6 @@ export class AppContext<TAttrs extends Record<string, any>, AppOptions = any> {
103
104
  public async setScenePath(scenePath: string): Promise<void> {
104
105
  if (!this.appProxy.box) return;
105
106
  this.appProxy.setFullPath(scenePath);
106
- this.appProxy.context.switchAppToWriter(this.appId);
107
107
  }
108
108
 
109
109
  public mountView(dom: HTMLDivElement): void {
@@ -120,4 +120,12 @@ export class AppContext<TAttrs extends Record<string, any>, AppOptions = any> {
120
120
  public getAppOptions(): AppOptions | undefined {
121
121
  return typeof this.appOptions === 'function' ? (this.appOptions as () => AppOptions)() : this.appOptions
122
122
  }
123
+
124
+ public createStorage<TState>(storeId: string, defaultState?: TState): Storage<TState> {
125
+ const storage = new Storage(this, storeId, defaultState);
126
+ this.emitter.on("destroy", () => {
127
+ storage.destroy();
128
+ });
129
+ return storage;
130
+ }
123
131
  }
@@ -7,10 +7,13 @@ import { setViewFocusScenePath } from './Utils/Common';
7
7
 
8
8
  export class AppListeners {
9
9
  private displayer = this.manager.displayer;
10
- private boxManager = this.manager.boxManager;
11
10
 
12
11
  constructor(private manager: AppManager) {}
13
12
 
13
+ private get boxManager() {
14
+ return this.manager.boxManager;
15
+ }
16
+
14
17
  public addListeners() {
15
18
  this.displayer.addMagixEventListener(MagixEventName, this.mainMagixEventListener);
16
19
  }
@@ -31,10 +34,6 @@ export class AppListeners {
31
34
  this.appResizeHandler(data.payload);
32
35
  break;
33
36
  }
34
- case Events.SwitchViewsToFreedom: {
35
- this.switchViewsToFreedomHandler();
36
- break;
37
- }
38
37
  case Events.AppBoxStateChange: {
39
38
  this.boxStateChangeHandler(data.payload);
40
39
  break;
@@ -43,6 +42,10 @@ export class AppListeners {
43
42
  this.setMainViewScenePathHandler(data.payload);
44
43
  break;
45
44
  }
45
+ case Events.MoveCameraToContain: {
46
+ this.moveCameraToContainHandler(data.payload);
47
+ break;
48
+ }
46
49
  default:
47
50
  break;
48
51
  }
@@ -50,23 +53,24 @@ export class AppListeners {
50
53
  };
51
54
 
52
55
  private appMoveHandler = (payload: any) => {
53
- this.boxManager.moveBox(payload);
56
+ this.boxManager?.moveBox(payload);
54
57
  };
55
58
 
56
59
  private appResizeHandler = (payload: any) => {
57
- this.boxManager.resizeBox(Object.assign(payload, { skipUpdate: true }));
60
+ this.boxManager?.resizeBox(Object.assign(payload, { skipUpdate: true }));
58
61
  this.manager.room?.refreshViewSize();
59
62
  };
60
63
 
61
- private switchViewsToFreedomHandler = () => {
62
- this.manager.viewManager.freedomAllViews();
63
- };
64
-
65
64
  private boxStateChangeHandler = (state: TeleBoxState) => {
66
65
  callbacks.emit("boxStateChange", state);
67
66
  }
68
67
 
69
68
  private setMainViewScenePathHandler = ({ nextScenePath }: { nextScenePath: string }) => {
70
69
  setViewFocusScenePath(this.manager.mainView, nextScenePath);
70
+ callbacks.emit("mainViewScenePathChange", nextScenePath);
71
+ }
72
+
73
+ private moveCameraToContainHandler = (payload: any) => {
74
+ this.manager.mainView.moveCameraToContain(payload);
71
75
  }
72
76
  }