@netless/window-manager 0.4.0-canary.1 → 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 (62) hide show
  1. package/dist/App/Storage/StorageEvent.d.ts +8 -0
  2. package/dist/App/Storage/index.d.ts +26 -0
  3. package/dist/App/Storage/typings.d.ts +21 -0
  4. package/dist/App/Storage/utils.d.ts +5 -0
  5. package/dist/AppContext.d.ts +3 -1
  6. package/dist/AppListener.d.ts +0 -1
  7. package/dist/AppManager.d.ts +7 -7
  8. package/dist/AppProxy.d.ts +2 -3
  9. package/dist/Base/Context.d.ts +0 -1
  10. package/dist/BoxManager.d.ts +2 -1
  11. package/dist/BuiltinApps.d.ts +6 -0
  12. package/dist/ContainerResizeObserver.d.ts +10 -0
  13. package/dist/Cursor/Cursor.d.ts +2 -3
  14. package/dist/Cursor/index.d.ts +7 -4
  15. package/dist/Helper.d.ts +6 -0
  16. package/dist/ReconnectRefresher.d.ts +5 -2
  17. package/dist/Utils/Common.d.ts +3 -1
  18. package/dist/Utils/Reactive.d.ts +1 -1
  19. package/dist/{MainView.d.ts → View/MainView.d.ts} +2 -4
  20. package/dist/View/ViewManager.d.ts +13 -0
  21. package/dist/constants.d.ts +1 -6
  22. package/dist/index.d.ts +13 -13
  23. package/dist/index.es.js +1 -1
  24. package/dist/index.es.js.map +1 -1
  25. package/dist/index.umd.js +1 -1
  26. package/dist/index.umd.js.map +1 -1
  27. package/dist/style.css +1 -1
  28. package/dist/typings.d.ts +1 -0
  29. package/package.json +5 -4
  30. package/src/App/Storage/StorageEvent.ts +21 -0
  31. package/src/App/Storage/index.ts +243 -0
  32. package/src/App/Storage/typings.ts +21 -0
  33. package/src/App/Storage/utils.ts +17 -0
  34. package/src/AppContext.ts +10 -2
  35. package/src/AppListener.ts +1 -8
  36. package/src/AppManager.ts +54 -35
  37. package/src/AppProxy.ts +14 -36
  38. package/src/Base/Context.ts +0 -4
  39. package/src/BoxManager.ts +9 -7
  40. package/src/BuiltinApps.ts +24 -0
  41. package/src/ContainerResizeObserver.ts +62 -0
  42. package/src/Cursor/Cursor.ts +23 -34
  43. package/src/Cursor/index.ts +70 -41
  44. package/src/Helper.ts +30 -0
  45. package/src/ReconnectRefresher.ts +13 -5
  46. package/src/Utils/Common.ts +35 -13
  47. package/src/Utils/Reactive.ts +9 -3
  48. package/src/Utils/RoomHacker.ts +15 -0
  49. package/src/{MainView.ts → View/MainView.ts} +9 -25
  50. package/src/View/ViewManager.ts +53 -0
  51. package/src/constants.ts +1 -3
  52. package/src/index.ts +46 -86
  53. package/src/shim.d.ts +4 -0
  54. package/src/style.css +6 -0
  55. package/src/typings.ts +1 -0
  56. package/vite.config.js +4 -1
  57. package/dist/Utils/CameraStore.d.ts +0 -15
  58. package/dist/ViewManager.d.ts +0 -29
  59. package/dist/sdk.d.ts +0 -14
  60. package/src/Utils/CameraStore.ts +0 -72
  61. package/src/sdk.ts +0 -39
  62. 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: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}.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/package.json CHANGED
@@ -1,10 +1,11 @@
1
1
  {
2
2
  "name": "@netless/window-manager",
3
- "version": "0.4.0-canary.1",
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,9 +23,9 @@
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.17",
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",
@@ -57,6 +58,6 @@
57
58
  "typescript": "^4.3.5",
58
59
  "video.js": "^7.14.3",
59
60
  "vite": "^2.5.3",
60
- "white-web-sdk": "^2.15.12"
61
+ "white-web-sdk": "^2.16.0"
61
62
  }
62
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,
@@ -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
  }
@@ -34,10 +34,6 @@ export class AppListeners {
34
34
  this.appResizeHandler(data.payload);
35
35
  break;
36
36
  }
37
- case Events.SwitchViewsToFreedom: {
38
- this.switchViewsToFreedomHandler();
39
- break;
40
- }
41
37
  case Events.AppBoxStateChange: {
42
38
  this.boxStateChangeHandler(data.payload);
43
39
  break;
@@ -65,16 +61,13 @@ export class AppListeners {
65
61
  this.manager.room?.refreshViewSize();
66
62
  };
67
63
 
68
- private switchViewsToFreedomHandler = () => {
69
- this.manager.viewManager.freedomAllViews();
70
- };
71
-
72
64
  private boxStateChangeHandler = (state: TeleBoxState) => {
73
65
  callbacks.emit("boxStateChange", state);
74
66
  }
75
67
 
76
68
  private setMainViewScenePathHandler = ({ nextScenePath }: { nextScenePath: string }) => {
77
69
  setViewFocusScenePath(this.manager.mainView, nextScenePath);
70
+ callbacks.emit("mainViewScenePathChange", nextScenePath);
78
71
  }
79
72
 
80
73
  private moveCameraToContainHandler = (payload: any) => {
package/src/AppManager.ts CHANGED
@@ -1,24 +1,23 @@
1
1
  import pRetry from "p-retry";
2
- import { sortBy } from "lodash";
3
2
  import { AppAttributes, AppStatus, Events, MagixEventName } from "./constants";
4
3
  import { AppListeners } from "./AppListener";
5
4
  import { AppProxy } from "./AppProxy";
6
- import { store } from "./AttributesDelegate";
7
- import { autorun, isPlayer, isRoom, ScenePathType, ViewVisionMode } from "white-web-sdk";
8
- import { callbacks, emitter, WindowManager } from "./index";
9
- import { CameraStore } from "./Utils/CameraStore";
10
- import { genAppId, makeValidScenePath, setScenePath } from "./Utils/Common";
5
+ import { autorun, isPlayer, isRoom, ScenePathType } from "white-web-sdk";
6
+ import { callbacks, emitter, WindowManager, reconnectRefresher } from "./index";
7
+ import { genAppId, makeValidScenePath, setScenePath, setViewFocusScenePath } from "./Utils/Common";
11
8
  import { log } from "./Utils/log";
12
- import { MainViewProxy } from "./MainView";
9
+ import { MainViewProxy } from "./View/MainView";
13
10
  import { onObjectRemoved, safeListenPropsUpdated } from "./Utils/Reactive";
14
- import { ReconnectRefresher } from "./ReconnectRefresher";
15
- import { ViewManager } from "./ViewManager";
11
+ import { get, sortBy } from "lodash";
12
+ import { store } from "./AttributesDelegate";
13
+ import { ViewManager } from "./View/ViewManager";
14
+ import type { ReconnectRefresher } from "./ReconnectRefresher";
16
15
  import type { BoxManager } from "./BoxManager";
17
16
  import type { Displayer, DisplayerState, Room } from "white-web-sdk";
18
17
  import type { AddAppParams, BaseInsertParams, TeleBoxRect, EmitterEvent } from "./index";
18
+
19
19
  export class AppManager {
20
20
  public displayer: Displayer;
21
- public cameraStore: CameraStore;
22
21
  public viewManager: ViewManager;
23
22
  public appProxies: Map<string, AppProxy> = new Map();
24
23
  public appStatus: Map<string, AppStatus> = new Map();
@@ -30,6 +29,8 @@ export class AppManager {
30
29
  private appListeners: AppListeners;
31
30
  public boxManager?: BoxManager;
32
31
 
32
+ private _prevSceneIndex: number | undefined;
33
+
33
34
  constructor(public windowManger: WindowManager) {
34
35
  this.displayer = windowManger.displayer;
35
36
  this.store.setContext({
@@ -37,19 +38,18 @@ export class AppManager {
37
38
  safeSetAttributes: attributes => this.safeSetAttributes(attributes),
38
39
  safeUpdateAttributes: (keys, val) => this.safeUpdateAttributes(keys, val),
39
40
  });
40
- this.cameraStore = new CameraStore();
41
41
  this.mainViewProxy = new MainViewProxy(this);
42
- this.viewManager = new ViewManager(this);
42
+ this.viewManager = new ViewManager(this.displayer);
43
43
  this.appListeners = new AppListeners(this);
44
44
  this.displayer.callbacks.on(this.eventName, this.displayerStateListener);
45
45
  this.appListeners.addListeners();
46
46
 
47
- this.refresher = new ReconnectRefresher(this.room, {
48
- notifyReconnected: () => this.notifyReconnected(),
49
- });
47
+ this.refresher = reconnectRefresher;
48
+ this.refresher.setRoom(this.room);
49
+ this.refresher.setContext({ emitter });
50
50
 
51
51
  emitter.once("onCreated").then(() => this.onCreated());
52
-
52
+ emitter.on("onReconnected", () => this.onReconnected());
53
53
  if (isPlayer(this.displayer)) {
54
54
  emitter.on("seek", time => {
55
55
  this.appProxies.forEach(appProxy => {
@@ -97,6 +97,15 @@ export class AppManager {
97
97
  }
98
98
  });
99
99
  });
100
+ this.refresher?.add("mainViewIndex", () => {
101
+ return autorun(() => {
102
+ const mainSceneIndex = get(this.attributes, "_mainSceneIndex");
103
+ if (mainSceneIndex !== undefined && this._prevSceneIndex !== mainSceneIndex) {
104
+ callbacks.emit("mainViewSceneIndexChange", mainSceneIndex);
105
+ this._prevSceneIndex = mainSceneIndex;
106
+ }
107
+ });
108
+ });
100
109
  if (!this.attributes.apps || Object.keys(this.attributes.apps).length === 0) {
101
110
  const mainScenePath = this.store.getMainViewScenePath();
102
111
  if (!mainScenePath) return;
@@ -187,15 +196,18 @@ export class AppManager {
187
196
  mainView.disableCameraTransform = disableCameraTransform;
188
197
  mainView.divElement = divElement;
189
198
  if (!mainView.focusScenePath) {
190
- this.store.setMainViewFocusPath(mainView);
199
+ this.setMainViewFocusPath();
191
200
  }
192
- if (this.store.focus === undefined && mainView.mode !== ViewVisionMode.Writable) {
193
- this.viewManager.switchMainViewToWriter();
194
- }
195
- this.mainViewProxy.addMainViewListener();
196
201
  emitter.emit("mainViewMounted");
197
202
  }
198
203
 
204
+ public setMainViewFocusPath() {
205
+ const scenePath = this.store.getMainViewScenePath();
206
+ if (scenePath) {
207
+ setViewFocusScenePath(this.mainView, scenePath);
208
+ }
209
+ }
210
+
199
211
  public async addApp(params: AddAppParams, isDynamicPPT: boolean): Promise<string | undefined> {
200
212
  log("addApp", params);
201
213
  const { appId, needFocus } = await this.beforeAddApp(params, isDynamicPPT);
@@ -281,7 +293,7 @@ export class AppManager {
281
293
  emitter.emit("observerIdChange", this.displayer.observerId);
282
294
  };
283
295
 
284
- private displayerWritableListener = (isReadonly: boolean) => {
296
+ public displayerWritableListener = (isReadonly: boolean) => {
285
297
  const isWritable = !isReadonly;
286
298
  const isManualWritable =
287
299
  this.windowManger.readonly === undefined || this.windowManger.readonly === false;
@@ -294,9 +306,6 @@ export class AppManager {
294
306
  appProxy.emitAppIsWritableChange();
295
307
  });
296
308
  if (isWritable === true) {
297
- if (!this.store.focus) {
298
- this.mainViewProxy.switchViewModeToWriter();
299
- }
300
309
  this.mainView.disableCameraTransform = false;
301
310
  } else {
302
311
  this.mainView.disableCameraTransform = true;
@@ -346,15 +355,16 @@ export class AppManager {
346
355
  await this._setMainViewScenePath(scenePath);
347
356
  } else if (scenePathType === ScenePathType.Dir) {
348
357
  const validScenePath = makeValidScenePath(this.displayer, scenePath);
349
- await this._setMainViewScenePath(validScenePath);
358
+ if (validScenePath) {
359
+ await this._setMainViewScenePath(validScenePath);
360
+ }
350
361
  }
351
362
  }
352
363
  }
353
364
 
354
365
  private async _setMainViewScenePath(scenePath: string) {
355
366
  this.safeSetAttributes({ _mainScenePath: scenePath });
356
- await this.viewManager.switchMainViewToWriter();
357
- setScenePath(this.room, scenePath);
367
+ this.setMainViewFocusPath();
358
368
  this.store.setMainViewFocusPath(this.mainView);
359
369
  this.dispatchInternalEvent(Events.SetMainViewScenePath, { nextScenePath: scenePath });
360
370
  }
@@ -362,12 +372,20 @@ export class AppManager {
362
372
  public async setMainViewSceneIndex(index: number) {
363
373
  if (this.room) {
364
374
  this.safeSetAttributes({ _mainSceneIndex: index });
365
- await this.viewManager.switchMainViewToWriter();
366
- this.room.setSceneIndex(index);
367
- const nextScenePath = this.room.state.sceneState.scenePath;
368
- this.store.setMainViewScenePath(nextScenePath);
369
- this.store.setMainViewFocusPath(this.mainView);
370
- this.dispatchInternalEvent(Events.SetMainViewScenePath, { nextScenePath });
375
+ const mainViewScenePath = this.store.getMainViewScenePath() as string;
376
+ if (mainViewScenePath) {
377
+ const sceneList = mainViewScenePath.split("/");
378
+ sceneList.pop();
379
+ let sceneDir = sceneList.join("/");
380
+ if (sceneDir === "") {
381
+ sceneDir = "/";
382
+ }
383
+ const scenePath = makeValidScenePath(this.displayer, sceneDir, index);
384
+ if (scenePath) {
385
+ this.store.setMainViewScenePath(scenePath);
386
+ this.setMainViewFocusPath();
387
+ }
388
+ }
371
389
  }
372
390
  }
373
391
 
@@ -433,7 +451,7 @@ export class AppManager {
433
451
  }
434
452
  }
435
453
 
436
- public async notifyReconnected() {
454
+ public async onReconnected() {
437
455
  const appProxies = Array.from(this.appProxies.values());
438
456
  const reconnected = appProxies.map(appProxy => {
439
457
  return appProxy.onReconnected();
@@ -470,5 +488,6 @@ export class AppManager {
470
488
  this.refresher?.destroy();
471
489
  this.mainViewProxy.destroy();
472
490
  callbacks.clearListeners();
491
+ this._prevSceneIndex = undefined;
473
492
  }
474
493
  }