neo.mjs 6.10.4 → 6.10.5

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 (70) hide show
  1. package/apps/ServiceWorker.mjs +2 -2
  2. package/apps/form/model/SideNav.mjs +3 -3
  3. package/apps/form/view/SideNavList.mjs +8 -3
  4. package/apps/form/view/ViewportController.mjs +6 -7
  5. package/apps/portal/Overwrites.mjs +21 -0
  6. package/apps/portal/app.mjs +7 -0
  7. package/apps/portal/data/blog.json +743 -0
  8. package/apps/portal/index.html +15 -0
  9. package/apps/portal/model/BlogPost.mjs +59 -0
  10. package/apps/{learnneo → portal}/model/Content.mjs +3 -3
  11. package/apps/{learnneo → portal}/neo-config.json +1 -1
  12. package/apps/portal/store/BlogPosts.mjs +43 -0
  13. package/apps/{learnneo → portal}/store/Content.mjs +2 -5
  14. package/apps/{learnneo/view/home → portal/view}/HeaderToolbar.mjs +22 -14
  15. package/apps/portal/view/Viewport.mjs +59 -0
  16. package/apps/portal/view/ViewportController.mjs +79 -0
  17. package/apps/portal/view/blog/Container.mjs +50 -0
  18. package/apps/portal/view/blog/List.mjs +173 -0
  19. package/apps/{newwebsite/view/Viewport.mjs → portal/view/home/MainContainer.mjs} +7 -8
  20. package/apps/{learnneo/view/home → portal/view/learn}/ContentTreeList.mjs +6 -6
  21. package/apps/{learnneo/view/home → portal/view/learn}/ContentView.mjs +3 -3
  22. package/apps/{learnneo/view → portal/view/learn}/LivePreview.mjs +6 -6
  23. package/apps/{learnneo/view/home → portal/view/learn}/MainContainer.mjs +27 -31
  24. package/apps/{learnneo/view/home → portal/view/learn}/MainContainerController.mjs +3 -3
  25. package/apps/{learnneo/view/home → portal/view/learn}/MainContainerModel.mjs +3 -3
  26. package/apps/website/Overwrites.mjs +16 -0
  27. package/apps/website/app.mjs +2 -1
  28. package/apps/website/view/blog/List.mjs +1 -1
  29. package/buildScripts/webpack/development/webpack.config.appworker.mjs +3 -1
  30. package/buildScripts/webpack/json/myApps.template.json +1 -1
  31. package/buildScripts/webpack/production/webpack.config.appworker.mjs +3 -1
  32. package/examples/ServiceWorker.mjs +2 -2
  33. package/package.json +2 -2
  34. package/resources/examples/data/formSideNav.json +19 -19
  35. package/resources/scss/src/apps/portal/blog/Container.scss +18 -0
  36. package/resources/scss/src/apps/portal/blog/List.scss +183 -0
  37. package/resources/scss/src/apps/{newwebsite/Viewport.scss → portal/home/MainContainer.scss} +1 -1
  38. package/resources/scss/src/tab/Strip.scss +1 -0
  39. package/resources/scss/theme-neo-light/button/Base.scss +5 -5
  40. package/resources/scss/theme-neo-light/tab/header/Button.scss +8 -7
  41. package/src/DefaultConfig.mjs +2 -2
  42. package/src/component/Base.mjs +5 -0
  43. package/src/component/Toast.mjs +5 -2
  44. package/src/container/Base.mjs +14 -0
  45. package/src/controller/Application.mjs +2 -1
  46. package/src/controller/Base.mjs +14 -3
  47. package/src/controller/Component.mjs +1 -1
  48. package/src/core/Base.mjs +7 -5
  49. package/src/data/RecordFactory.mjs +3 -3
  50. package/src/form/Container.mjs +50 -0
  51. package/src/form/field/Text.mjs +2 -2
  52. package/src/form/field/TextArea.mjs +5 -0
  53. package/src/main/addon/WindowPosition.mjs +24 -14
  54. package/src/tab/Strip.mjs +21 -36
  55. package/src/tab/header/Button.mjs +5 -7
  56. package/src/worker/Base.mjs +41 -29
  57. package/src/worker/Manager.mjs +4 -3
  58. package/src/worker/mixin/RemoteMethodAccess.mjs +20 -18
  59. package/apps/learnneo/app.mjs +0 -6
  60. package/apps/learnneo/index.html +0 -21
  61. package/apps/learnneo/view/Viewport.mjs +0 -52
  62. package/apps/learnneo/view/ViewportController.mjs +0 -19
  63. package/apps/newwebsite/app.mjs +0 -6
  64. package/apps/newwebsite/index.html +0 -13
  65. package/apps/newwebsite/neo-config.json +0 -7
  66. /package/resources/scss/src/apps/{learnneo/home → portal}/HeaderToolbar.scss +0 -0
  67. /package/resources/scss/src/apps/{learnneo → portal}/Viewport.scss +0 -0
  68. /package/resources/scss/src/apps/{learnneo/home → portal/learn}/ContentTreeList.scss +0 -0
  69. /package/resources/scss/src/apps/{learnneo/home → portal/learn}/ContentView.scss +0 -0
  70. /package/resources/scss/src/apps/{learnneo/home → portal/learn}/MainContainer.scss +0 -0
@@ -21,6 +21,12 @@ class Base extends CoreBase {
21
21
  * @protected
22
22
  */
23
23
  ntype: 'controller',
24
+ /**
25
+ * If the URL does not contain a hash value when creating this controller instance,
26
+ * neo will set this hash value for us.
27
+ * @member {String|null} defaultHash=null
28
+ */
29
+ defaultHash: null,
24
30
  /**
25
31
  * @member {String|null} defaultRoute=null
26
32
  */
@@ -90,9 +96,14 @@ class Base extends CoreBase {
90
96
  *
91
97
  */
92
98
  onConstructed() {
93
- let currentHash = HashHistory.first();
99
+ let currentHash = HashHistory.first(),
100
+ defaultHash = this.defaultHash;
94
101
 
95
- currentHash && this.onHashChange(currentHash, null)
102
+ if (currentHash) {
103
+ this.onHashChange(currentHash, null)
104
+ } else if (defaultHash) {
105
+ Neo.Main.setRoute({value: defaultHash})
106
+ }
96
107
  }
97
108
 
98
109
  /**
@@ -185,7 +196,7 @@ class Base extends CoreBase {
185
196
  * @returns {Number}
186
197
  */
187
198
  #sortRoutes(route1, route2) {
188
- return route1.match(amountSlashesRegex).length - route2.match(amountSlashesRegex).length
199
+ return (route1.match(amountSlashesRegex) || []).length - (route2.match(amountSlashesRegex)|| []).length
189
200
  }
190
201
  }
191
202
 
@@ -189,7 +189,7 @@ class Component extends Base {
189
189
  handlerScope = me.getHandlerScope(eventHandler, component);
190
190
 
191
191
  if (!handlerScope) {
192
- Logger.logError('Unknown event handler for', eventHandler, component)
192
+ console.error('Unknown event handler for', eventHandler, component)
193
193
  } else if (handlerScope !== true) {
194
194
  listener.fn = handlerScope[eventHandler].bind(handlerScope)
195
195
  }
package/src/core/Base.mjs CHANGED
@@ -189,12 +189,14 @@ class Base {
189
189
  delayable = me.delayable ? Neo.merge({}, me.delayable, ctorDelayable) : ctorDelayable;
190
190
 
191
191
  Object.entries(delayable).forEach(([key, value]) => {
192
- let map = {
193
- debounce() {me[key] = new debounce(me[key], me, value.timer)},
194
- throttle() {me[key] = new throttle(me[key], me, value.timer)}
195
- };
192
+ if (value) {
193
+ let map = {
194
+ debounce() {me[key] = new debounce(me[key], me, value.timer)},
195
+ throttle() {me[key] = new throttle(me[key], me, value.timer)}
196
+ };
196
197
 
197
- map[value.type]?.()
198
+ map[value.type]?.()
199
+ }
198
200
  })
199
201
  }
200
202
 
@@ -68,6 +68,9 @@ class RecordFactory extends Base {
68
68
  properties;
69
69
 
70
70
  Object.defineProperties(me, {
71
+ [Symbol.for('isRecord')]: {
72
+ value: true
73
+ },
71
74
  _isModified: {
72
75
  value : false,
73
76
  writable: true
@@ -87,9 +90,6 @@ class RecordFactory extends Base {
87
90
  parsedValue = instance.parseRecordValue(me, field, value, config);
88
91
 
89
92
  properties = {
90
- [Symbol.for('isRecord')]: {
91
- value: true
92
- },
93
93
  [symbol]: {
94
94
  value : parsedValue,
95
95
  writable: true
@@ -136,6 +136,56 @@ class Container extends BaseContainer {
136
136
  return fields
137
137
  }
138
138
 
139
+
140
+ /**
141
+ * This function will return one of the following states:
142
+ * - clean => all fields are clean (untouched)
143
+ * - invalid => at least one field is invalid
144
+ * - valid => all required fields are valid
145
+ * - inProgress => at least one field is valid, at least one field is clean
146
+ * @returns {Promise<String>}
147
+ */
148
+ async getFormState() {
149
+ let fields = await this.getFields(),
150
+ i = 0,
151
+ hasCleanFields = false,
152
+ hasInvalidFields = false,
153
+ hasUncleanFields = false,
154
+ hasValidFields = false,
155
+ len = fields.length,
156
+ field, isClean, isValid;
157
+
158
+ for (; i < len; i++) {
159
+ field = fields[i];
160
+ isClean = field.clean;
161
+ isValid = field.isValid();
162
+
163
+ if (!isClean && !isValid) {
164
+ return 'invalid'
165
+ } else if (isValid) {
166
+ hasValidFields = true
167
+ } else if (!isValid) {
168
+ hasInvalidFields = true
169
+ }
170
+
171
+ if (isClean) {
172
+ hasCleanFields = true
173
+ } else {
174
+ hasUncleanFields = true
175
+ }
176
+ }
177
+
178
+ if (!hasInvalidFields) {
179
+ return 'valid'
180
+ }
181
+
182
+ if (hasCleanFields && !hasUncleanFields) {
183
+ return 'clean'
184
+ }
185
+
186
+ return 'inProgress'
187
+ }
188
+
139
189
  /**
140
190
  * @returns {Promise<Object>}
141
191
  */
@@ -703,7 +703,7 @@ class Text extends Base {
703
703
 
704
704
  me.silentVdomUpdate = true;
705
705
 
706
- me.validate(false);
706
+ oldValue !== undefined && me.validate(me.clean);
707
707
  me.changeInputElKey('required', value ? value : null);
708
708
  me.labelText = me.labelText; // apply the optional text if needed
709
709
 
@@ -1279,7 +1279,7 @@ class Text extends Base {
1279
1279
  cls;
1280
1280
 
1281
1281
  if (!me.readOnly) {
1282
- me.validate(); // silent
1282
+ me.validate(false);
1283
1283
 
1284
1284
  cls = me.cls; // has to get set after validate()
1285
1285
 
@@ -37,6 +37,11 @@ class TextArea extends Text {
37
37
  * @member {String[]} baseCls=['neo-textarea','neo-textfield']
38
38
  */
39
39
  baseCls: ['neo-textarea', 'neo-textfield'],
40
+ /**
41
+ * True shows a clear trigger in case the field has a non-empty value.
42
+ * @member {Boolean} clearable=false
43
+ */
44
+ clearable: false,
40
45
  /**
41
46
  * The visible width of the text control, in average character widths.
42
47
  * If it is specified, it must be a positive integer.
@@ -13,9 +13,9 @@ class WindowPosition extends Base {
13
13
  */
14
14
  className: 'Neo.main.addon.WindowPosition',
15
15
  /**
16
- * @member {Boolean} adjustWindowPositions=true
16
+ * @member {Boolean} adjustWindowPositions=false
17
17
  */
18
- adjustWindowPositions: true,
18
+ adjustWindowPositions: false,
19
19
  /**
20
20
  * @member {String|null} intervalId=null
21
21
  */
@@ -25,9 +25,9 @@ class WindowPosition extends Base {
25
25
  */
26
26
  intervalTime: 20,
27
27
  /**
28
- * @member {Boolean} observeResize_=true
28
+ * @member {Boolean} observeResize_=false
29
29
  */
30
- observeResize_: true,
30
+ observeResize_: false,
31
31
  /**
32
32
  * Remote method access for other workers
33
33
  * @member {Object} remote
@@ -61,6 +61,12 @@ class WindowPosition extends Base {
61
61
  windows: {}
62
62
  }
63
63
 
64
+ /**
65
+ * @member {Function|null} resizeListener=null
66
+ * @protected
67
+ */
68
+ resizeListener = null
69
+
64
70
  /**
65
71
  * @param {Object} config
66
72
  */
@@ -85,9 +91,11 @@ class WindowPosition extends Base {
85
91
  afterSetObserveResize(value, oldValue) {
86
92
  let me = this;
87
93
 
88
- if (value) {
89
- window[value ? 'addEventListener' : 'removeEventListener']('resize', me.onResize.bind(me))
94
+ if (!me.resizeListener) {
95
+ me.resizeListener = me.onResize.bind(me)
90
96
  }
97
+
98
+ window[value ? 'addEventListener' : 'removeEventListener']('resize', me.resizeListener)
91
99
  }
92
100
 
93
101
  /**
@@ -196,7 +204,7 @@ class WindowPosition extends Base {
196
204
  /**
197
205
  * @param {Object} event
198
206
  */
199
- onResize(event) {
207
+ onResize(event) { console.log('onResize');
200
208
  let me = this,
201
209
  win = window,
202
210
  height, width;
@@ -213,14 +221,16 @@ class WindowPosition extends Base {
213
221
  break
214
222
  }
215
223
 
216
- Neo.Main.windowResizeTo({
217
- height : height,
218
- width : width,
219
- windowName: key
220
- })
221
- });
224
+ if (me.adjustWindowPositions) {
225
+ Neo.Main.windowResizeTo({
226
+ height,
227
+ width,
228
+ windowName: key
229
+ });
222
230
 
223
- me.adjustWindowPositions && me.adjustPositions()
231
+ me.adjustPositions()
232
+ }
233
+ })
224
234
  }
225
235
 
226
236
  /**
package/src/tab/Strip.mjs CHANGED
@@ -44,44 +44,28 @@ class Strip extends Component {
44
44
  * @protected
45
45
  */
46
46
  afterSetUseActiveTabIndicator(value, oldValue) {
47
- if (oldValue !== undefined) {
48
- let me = this;
49
-
50
- me.vdom.cn[0].removeDom = !value;
51
-
52
- if (me.mounted && value) {
53
- me.getActiveTabRectThenMove();
54
- } else {
55
- me.update();
56
- }
57
- }
47
+ this.vdom.cn[0].removeDom = !value;
48
+ this.update()
58
49
  }
59
50
 
60
51
  /**
52
+ * Gets the DomRect of the active tab, then moves the indicator
61
53
  * @param {Object|null} opts
62
54
  * @param {Number} opts.oldValue
63
55
  * @param {Number} opts.value
64
- * Gets the DomRect of the active tab, then moves the indicator
65
56
  */
66
57
  getActiveTabRectThenMove(opts) {
67
58
  let me = this,
68
- ids = [],
59
+ ids = [me.id],
69
60
  tabContainer = me.getTabContainer();
70
61
 
71
- if (me.vnode) {
72
- if (opts) {
73
- ids.push(tabContainer.getTabAtIndex(opts.value), tabContainer.getTabAtIndex(opts.oldValue));
74
- } else {
75
- ids.push(tabContainer.getTabAtIndex(tabContainer.activeIndex));
76
- }
77
-
78
- ids = ids.map(e => e?.id).filter(Boolean);
62
+ // We do not need a movement, in case there is no oldValue
63
+ if (me.useActiveTabIndicator && me.vnode && Neo.isNumber(opts?.oldValue)) {
64
+ ids.push(tabContainer.getTabAtIndex(opts.value).id, tabContainer.getTabAtIndex(opts.oldValue).id);
79
65
 
80
- if (me.useActiveTabIndicator) {
81
- me.getDomRect(ids).then(data => {
82
- me.moveActiveIndicator(data);
83
- });
84
- }
66
+ me.getDomRect(ids).then(data => {
67
+ me.moveActiveIndicator(data)
68
+ })
85
69
  }
86
70
  }
87
71
 
@@ -89,7 +73,7 @@ class Strip extends Component {
89
73
  *
90
74
  */
91
75
  getTabContainer() {
92
- return Neo.getComponent(this.tabContainerId);
76
+ return Neo.getComponent(this.tabContainerId)
93
77
  }
94
78
 
95
79
  /**
@@ -105,8 +89,9 @@ class Strip extends Component {
105
89
  * @param {Number} rects[0].y
106
90
  */
107
91
  moveActiveIndicator(rects) {
108
- let me = this,
109
- rect = rects[1] || rects[0],
92
+ let me = this,
93
+ tabStripRect = rects.shift(),
94
+ rect = rects[1] || rects[0],
110
95
  activeTabIndicator, tabContainer;
111
96
 
112
97
  if (me.useActiveTabIndicator) {
@@ -118,20 +103,20 @@ class Strip extends Component {
118
103
  case 'top':
119
104
  activeTabIndicator.style = {
120
105
  height: null,
121
- left : `${rect.left}px`,
106
+ left : `${rect.left - tabStripRect.left}px`,
122
107
  top : null,
123
108
  width : `${rect.width}px`
124
109
  };
125
- break;
110
+ break
126
111
  case 'left':
127
112
  case 'right':
128
113
  activeTabIndicator.style = {
129
114
  height: `${rect.height}px`,
130
115
  left : null,
131
- top : `${rect.top}px`,
116
+ top : `${rect.top - tabStripRect.top}px`,
132
117
  width : null
133
118
  };
134
- break;
119
+ break
135
120
  }
136
121
 
137
122
  // in case there is a dynamic change (oldValue), call this method again
@@ -140,7 +125,7 @@ class Strip extends Component {
140
125
  me.update();
141
126
 
142
127
  setTimeout(() => {
143
- me.moveActiveIndicator([rects[0]]);
128
+ me.moveActiveIndicator([tabStripRect, rects[0]])
144
129
  }, 50)
145
130
  } else {
146
131
  activeTabIndicator.style.opacity = 1;
@@ -148,8 +133,8 @@ class Strip extends Component {
148
133
 
149
134
  setTimeout(() => {
150
135
  activeTabIndicator.style.opacity = 0;
151
- me.update();
152
- }, 300);
136
+ me.update()
137
+ }, 300)
153
138
  }
154
139
  }
155
140
  }
@@ -71,26 +71,24 @@ class Button extends BaseButton {
71
71
  * @protected
72
72
  */
73
73
  afterSetUseActiveTabIndicator(value, oldValue) {
74
- this.updateUseActiveTabIndicator();
74
+ this.updateUseActiveTabIndicator()
75
75
  }
76
76
 
77
77
  /**
78
78
  * @param {Object} data
79
79
  */
80
80
  showRipple(data) {
81
- !this.pressed && super.showRipple(data);
81
+ !this.pressed && super.showRipple(data)
82
82
  }
83
83
 
84
84
  /**
85
85
  * @param {Boolean} silent=false
86
86
  */
87
87
  updateUseActiveTabIndicator(silent=false) {
88
- let me = this,
89
- vdom = me.vdom;
90
-
91
- vdom.cn[4].removeDom = !me.useActiveTabIndicator;
88
+ let me = this;
92
89
 
93
- me[silent ? '_vdom' : 'vdom'] = vdom;
90
+ me.vdom.cn[4].removeDom = !me.useActiveTabIndicator;
91
+ !silent && me.update()
94
92
  }
95
93
  }
96
94
 
@@ -112,10 +112,8 @@ class Base extends CoreBase {
112
112
  onConnect(data) {
113
113
  // short delay to ensure app VCs are in place
114
114
  setTimeout(() => {
115
- this.fire('connect', {
116
- appName: data.appName
117
- });
118
- }, 10);
115
+ this.fire('connect', {appName: data.appName})
116
+ }, 10)
119
117
  }
120
118
 
121
119
  /**
@@ -129,9 +127,10 @@ class Base extends CoreBase {
129
127
  me.isConnected = true;
130
128
 
131
129
  me.ports.push({
132
- appName: null,
130
+ appName : null,
133
131
  id,
134
- port : e.ports[0]
132
+ port : e.ports[0],
133
+ windowId: null
135
134
  });
136
135
 
137
136
  me.ports[me.ports.length - 1].port.onmessage = me.onMessage.bind(me);
@@ -141,7 +140,7 @@ class Base extends CoreBase {
141
140
 
142
141
  me.sendMessage('main', {action: 'workerConstructed', port: id});
143
142
 
144
- me.afterConnect();
143
+ me.afterConnect()
145
144
  }
146
145
 
147
146
  /**
@@ -154,7 +153,7 @@ class Base extends CoreBase {
154
153
 
155
154
  if (!me.isSharedWorker) {
156
155
  me.sendMessage('main', {action: 'workerConstructed'});
157
- me.afterConnect();
156
+ me.afterConnect()
158
157
  }
159
158
  }
160
159
 
@@ -163,9 +162,7 @@ class Base extends CoreBase {
163
162
  * @param {Object} data
164
163
  */
165
164
  onDisconnect(data) {
166
- this.fire('disconnect', {
167
- appName: data.appName
168
- });
165
+ this.fire('disconnect', {appName: data.appName})
169
166
  }
170
167
 
171
168
  /**
@@ -186,12 +183,12 @@ class Base extends CoreBase {
186
183
  me['on' + Neo.capitalize(action)](data);
187
184
  } else if (promise = action === 'reply' && me.promises[replyId]) {
188
185
  if (data.reject) {
189
- promise.reject(data.data);
186
+ promise.reject(data.data)
190
187
  } else {
191
- promise.resolve(data.data);
188
+ promise.resolve(data.data)
192
189
  }
193
190
 
194
- delete me.promises[replyId];
191
+ delete me.promises[replyId]
195
192
  }
196
193
  }
197
194
 
@@ -199,9 +196,7 @@ class Base extends CoreBase {
199
196
  * @param {Object} msg
200
197
  */
201
198
  onPing(msg) {
202
- this.resolve(msg, {
203
- originMsg: msg
204
- });
199
+ this.resolve(msg, {originMsg: msg})
205
200
  }
206
201
 
207
202
  /**
@@ -217,8 +212,8 @@ class Base extends CoreBase {
217
212
  for (port of me.ports) {
218
213
  if (!port.appName) {
219
214
  port.appName = appName;
220
- me.onConnect({ appName });
221
- break;
215
+ me.onConnect({appName});
216
+ break
222
217
  }
223
218
  }
224
219
  }
@@ -228,7 +223,19 @@ class Base extends CoreBase {
228
223
  */
229
224
  onRegisterNeoConfig(msg) {
230
225
  Neo.config = Neo.config || {};
231
- Object.assign(Neo.config, msg.data);
226
+
227
+ let me = this,
228
+ {windowId} = msg.data,
229
+ port;
230
+
231
+ for (port of me.ports) {
232
+ if (!port.windowId) {
233
+ port.windowId = windowId;
234
+ break
235
+ }
236
+ }
237
+
238
+ Object.assign(Neo.config, msg.data)
232
239
  }
233
240
 
234
241
  /**
@@ -246,12 +253,12 @@ class Base extends CoreBase {
246
253
  let message = me.sendMessage(dest, opts, transfer),
247
254
  msgId = message.id;
248
255
 
249
- me.promises[msgId] = { reject, resolve };
250
- });
256
+ me.promises[msgId] = { reject, resolve }
257
+ })
251
258
  }
252
259
 
253
260
  /**
254
- * @param {String} dest app, data, main or vdom (excluding the current worker)
261
+ * @param {String} dest app, canvas, data, main or vdom (excluding the current worker)
255
262
  * @param {Object} opts configs for Neo.worker.Message
256
263
  * @param {Array} [transfer] An optional array of Transferable objects to transfer ownership of.
257
264
  * If the ownership of an object is transferred, it becomes unusable (neutered) in the context it was sent from
@@ -268,24 +275,29 @@ class Base extends CoreBase {
268
275
  if (me.channelPorts[dest]) {
269
276
  port = me.channelPorts[dest];
270
277
  } else if (!me.isSharedWorker) {
271
- port = globalThis;
278
+ port = globalThis
272
279
  } else {
273
280
  if (opts.port) {
274
- port = me.getPort({id: opts.port}).port;
275
- } else if (opts.appName) {
281
+ port = me.getPort({id: opts.port}).port
282
+ } else if (opts.windowId) {
283
+ portObject = me.getPort({windowId: opts.windowId});
284
+ port = portObject.port;
285
+
286
+ opts.port = portObject.id
287
+ } else if (opts.appName) {
276
288
  portObject = me.getPort({appName: opts.appName});
277
289
  port = portObject.port;
278
290
 
279
- opts.port = portObject.id;
291
+ opts.port = portObject.id
280
292
  } else {
281
- port = me.ports[0].port;
293
+ port = me.ports[0].port
282
294
  }
283
295
  }
284
296
 
285
297
  message = new Message(opts);
286
298
 
287
299
  port.postMessage(message, transfer);
288
- return message;
300
+ return message
289
301
  }
290
302
  }
291
303
 
@@ -6,7 +6,8 @@ import Observable from '../core/Observable.mjs';
6
6
  import RemoteMethodAccess from './mixin/RemoteMethodAccess.mjs';
7
7
 
8
8
  const NeoConfig = Neo.config,
9
- devMode = NeoConfig.environment === 'development';
9
+ devMode = NeoConfig.environment === 'development',
10
+ windowId = new Date().getTime();
10
11
 
11
12
  /**
12
13
  * The worker manager lives inside the main thread and creates the App, Data & VDom worker.
@@ -207,8 +208,8 @@ class Manager extends Base {
207
208
 
208
209
  me.sendMessage(key, {
209
210
  action: 'registerNeoConfig',
210
- data : config
211
- });
211
+ data : {...config, windowId}
212
+ })
212
213
  }
213
214
  }
214
215
 
@@ -18,6 +18,15 @@ class RemoteMethodAccess extends Base {
18
18
  mixin: true
19
19
  }
20
20
 
21
+ /**
22
+ * @param {Object} source
23
+ * @param {Object} target
24
+ */
25
+ assignPort(source, target) {
26
+ const {appName, port, windowId} = source;
27
+ Object.assign(target, {appName, port, windowId})
28
+ }
29
+
21
30
  /**
22
31
  * @param {Object} remote
23
32
  * @param method
@@ -36,10 +45,7 @@ class RemoteMethodAccess extends Base {
36
45
  remoteMethod : method
37
46
  };
38
47
 
39
- if (me.isSharedWorker) {
40
- opts.appName = data?.appName;
41
- opts.port = data?.port;
42
- }
48
+ me.isSharedWorker && me.assignPort(data, opts);
43
49
 
44
50
  return me.promiseMessage(origin, opts, buffer);
45
51
  }
@@ -109,19 +115,17 @@ class RemoteMethodAccess extends Base {
109
115
  * @param {Object} data
110
116
  */
111
117
  reject(msg, data) {
112
- let opts = {
118
+ let me = this,
119
+
120
+ opts = {
113
121
  action : 'reply',
114
122
  data,
115
123
  reject : true,
116
124
  replyId: msg.id
117
125
  };
118
126
 
119
- if (this.isSharedWorker) {
120
- opts.appName = msg.appName;
121
- opts.port = msg.port;
122
- }
123
-
124
- this.sendMessage(msg.origin, opts);
127
+ me.isSharedWorker && me.assignPort(msg, opts);
128
+ me.sendMessage(msg.origin, opts);
125
129
  }
126
130
 
127
131
  /**
@@ -130,18 +134,16 @@ class RemoteMethodAccess extends Base {
130
134
  * @param {Object} data
131
135
  */
132
136
  resolve(msg, data) {
133
- let opts = {
137
+ let me = this,
138
+
139
+ opts = {
134
140
  action : 'reply',
135
141
  data,
136
142
  replyId: msg.id
137
143
  };
138
144
 
139
- if (this.isSharedWorker) {
140
- opts.appName = msg.appName;
141
- opts.port = msg.port;
142
- }
143
-
144
- this.sendMessage(msg.origin, opts);
145
+ me.isSharedWorker && me.assignPort(msg, opts);
146
+ me.sendMessage(msg.origin, opts);
145
147
  }
146
148
  }
147
149
 
@@ -1,6 +0,0 @@
1
- import Viewport from './view/Viewport.mjs';
2
-
3
- export const onStart = () => Neo.app({
4
- mainView: Viewport,
5
- name : 'LearnNeo'
6
- })