neo.mjs 6.18.0 → 6.18.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/apps/ServiceWorker.mjs +2 -2
- package/apps/colors/view/HeaderToolbar.mjs +6 -6
- package/apps/portal/view/HeaderToolbar.mjs +1 -2
- package/apps/portal/view/home/MainContainer.mjs +39 -8
- package/apps/portal/view/home/parts/AfterMath.mjs +19 -16
- package/apps/portal/view/home/parts/BaseContainer.mjs +31 -0
- package/apps/portal/view/home/parts/Colors.mjs +43 -19
- package/apps/portal/view/home/parts/Features.mjs +6 -6
- package/apps/portal/view/home/parts/Helix.mjs +55 -19
- package/apps/portal/view/home/parts/HelloWorld.mjs +11 -10
- package/apps/portal/view/home/parts/How.mjs +66 -0
- package/apps/portal/view/home/parts/MainNeo.mjs +17 -14
- package/examples/ServiceWorker.mjs +2 -2
- package/examples/model/dialog/EditUserDialog.mjs +1 -8
- package/package.json +1 -1
- package/resources/data/deck/learnneo/pages/Events.md +15 -9
- package/resources/data/deck/learnneo/pages/GuideEvents.md +142 -19
- package/resources/data/deck/learnneo/pages/GuideViewModels.md +444 -0
- package/resources/data/deck/learnneo/tree.json +1 -0
- package/resources/scss/src/apps/portal/HeaderToolbar.scss +143 -125
- package/resources/scss/src/apps/portal/home/MainContainer.scss +0 -45
- package/resources/scss/src/apps/portal/home/parts/BaseContainer.scss +27 -0
- package/resources/scss/src/apps/portal/home/parts/MainNeo.scss +24 -0
- package/resources/scss/src/apps/portal/learn/ContentTreeList.scss +1 -1
- package/resources/scss/src/calendar/view/EditEventContainer.scss +1 -1
- package/resources/scss/src/calendar/view/calendars/List.scss +1 -1
- package/resources/scss/src/dialog/Base.scss +1 -6
- package/resources/scss/theme-dark/dialog/Base.scss +1 -0
- package/resources/scss/theme-light/dialog/Base.scss +1 -0
- package/resources/scss/theme-neo-light/Global.scss +13 -11
- package/resources/scss/theme-neo-light/dialog/Base.scss +1 -0
- package/src/DefaultConfig.mjs +2 -2
- package/src/button/Base.mjs +3 -2
- package/src/calendar/view/EditEventContainer.mjs +1 -1
- package/src/component/Base.mjs +49 -16
- package/src/controller/Base.mjs +5 -5
- package/src/core/Observable.mjs +23 -7
- package/src/dialog/Base.mjs +23 -45
- package/src/form/field/Color.mjs +5 -5
- package/src/main/addon/IntersectionObserver.mjs +20 -1
- package/src/model/Component.mjs +11 -9
- package/src/selection/DateSelectorModel.mjs +2 -2
- package/src/util/HashHistory.mjs +45 -12
- package/src/worker/Base.mjs +15 -8
package/src/component/Base.mjs
CHANGED
@@ -13,8 +13,10 @@ import VDomUtil from '../util/VDom.mjs';
|
|
13
13
|
import VNodeUtil from '../util/VNode.mjs';
|
14
14
|
|
15
15
|
const
|
16
|
-
|
17
|
-
|
16
|
+
addUnits = value => value == null ? value : isNaN(value) ? value : `${value}px`,
|
17
|
+
closestController = Symbol.for('closestController'),
|
18
|
+
closestModel = Symbol.for('closestModel'),
|
19
|
+
lengthRE = /^\d+\w+$/;
|
18
20
|
|
19
21
|
/**
|
20
22
|
* @class Neo.component.Base
|
@@ -577,9 +579,11 @@ class Base extends CoreBase {
|
|
577
579
|
afterSetDomListeners(value, oldValue) {
|
578
580
|
let me = this;
|
579
581
|
|
580
|
-
|
582
|
+
if (value?.[0] || oldValue?.[0]) {
|
583
|
+
me.getController()?.parseDomListeners(me);
|
581
584
|
|
582
|
-
|
585
|
+
DomEventManager.updateDomListeners(me, value, oldValue)
|
586
|
+
}
|
583
587
|
}
|
584
588
|
|
585
589
|
/**
|
@@ -1240,7 +1244,7 @@ class Base extends CoreBase {
|
|
1240
1244
|
* Creates a KeyNavigation instance if needed.
|
1241
1245
|
* @param {Object} value
|
1242
1246
|
* @param {Object} oldValue
|
1243
|
-
* @returns {Neo.util.KeyNavigation}
|
1247
|
+
* @returns {Neo.util.KeyNavigation|null}
|
1244
1248
|
* @protected
|
1245
1249
|
*/
|
1246
1250
|
beforeSetKeys(value, oldValue) {
|
@@ -1487,12 +1491,7 @@ class Base extends CoreBase {
|
|
1487
1491
|
* @param {String} id=this.id
|
1488
1492
|
*/
|
1489
1493
|
focus(id=this.id) {
|
1490
|
-
Neo.main.DomAccess.focus({
|
1491
|
-
id,
|
1492
|
-
windowId: this.id
|
1493
|
-
}).catch(err => {
|
1494
|
-
console.log('Error attempting to receive focus for component', err, this)
|
1495
|
-
})
|
1494
|
+
Neo.main.DomAccess.focus({id, windowId: this.windowId})
|
1496
1495
|
}
|
1497
1496
|
|
1498
1497
|
/**
|
@@ -1503,10 +1502,10 @@ class Base extends CoreBase {
|
|
1503
1502
|
const result = [];
|
1504
1503
|
|
1505
1504
|
if (this.floating) {
|
1506
|
-
result.push('neo-floating')
|
1505
|
+
result.push('neo-floating')
|
1507
1506
|
}
|
1508
1507
|
|
1509
|
-
return result
|
1508
|
+
return result
|
1510
1509
|
}
|
1511
1510
|
|
1512
1511
|
/**
|
@@ -1543,7 +1542,24 @@ class Base extends CoreBase {
|
|
1543
1542
|
* @returns {Neo.controller.Component|null}
|
1544
1543
|
*/
|
1545
1544
|
getController(ntype) {
|
1546
|
-
|
1545
|
+
let me = this,
|
1546
|
+
controller;
|
1547
|
+
|
1548
|
+
if (!ntype) {
|
1549
|
+
controller = me[closestController];
|
1550
|
+
|
1551
|
+
if (controller) {
|
1552
|
+
return controller
|
1553
|
+
}
|
1554
|
+
}
|
1555
|
+
|
1556
|
+
controller = me.getConfigInstanceByNtype('controller', ntype);
|
1557
|
+
|
1558
|
+
if (!ntype) {
|
1559
|
+
me[closestController] = controller;
|
1560
|
+
}
|
1561
|
+
|
1562
|
+
return controller
|
1547
1563
|
}
|
1548
1564
|
|
1549
1565
|
/**
|
@@ -1553,7 +1569,7 @@ class Base extends CoreBase {
|
|
1553
1569
|
* @returns {Promise<Neo.util.Rectangle>}
|
1554
1570
|
*/
|
1555
1571
|
async getDomRect(id=this.id, appName=this.appName) {
|
1556
|
-
|
1572
|
+
let result = await Neo.main.DomAccess.getBoundingClientRect({appName, id, windowId: this.windowId});
|
1557
1573
|
|
1558
1574
|
if (Array.isArray(result)) {
|
1559
1575
|
return result.map(rect => Rectangle.clone(rect))
|
@@ -1572,7 +1588,24 @@ class Base extends CoreBase {
|
|
1572
1588
|
return null
|
1573
1589
|
}
|
1574
1590
|
|
1575
|
-
|
1591
|
+
let me = this,
|
1592
|
+
model;
|
1593
|
+
|
1594
|
+
if (!ntype) {
|
1595
|
+
model = me[closestModel];
|
1596
|
+
|
1597
|
+
if (model) {
|
1598
|
+
return model
|
1599
|
+
}
|
1600
|
+
}
|
1601
|
+
|
1602
|
+
model = me.getConfigInstanceByNtype('model', ntype);
|
1603
|
+
|
1604
|
+
if (!ntype) {
|
1605
|
+
me[closestModel] = model
|
1606
|
+
}
|
1607
|
+
|
1608
|
+
return model
|
1576
1609
|
}
|
1577
1610
|
|
1578
1611
|
/**
|
package/src/controller/Base.mjs
CHANGED
@@ -96,15 +96,15 @@ class Base extends CoreBase {
|
|
96
96
|
*
|
97
97
|
*/
|
98
98
|
async onConstructed() {
|
99
|
-
let me
|
100
|
-
|
101
|
-
|
99
|
+
let me = this,
|
100
|
+
{defaultHash, windowId} = me,
|
101
|
+
currentHash = HashHistory.first(windowId);
|
102
102
|
|
103
103
|
// get outside the construction chain => a related cmp & vm has to be constructed too
|
104
104
|
await me.timeout(1);
|
105
105
|
|
106
106
|
if (currentHash) {
|
107
|
-
if (currentHash.windowId ===
|
107
|
+
if (currentHash.windowId === windowId) {
|
108
108
|
await me.onHashChange(currentHash, null)
|
109
109
|
}
|
110
110
|
} else {
|
@@ -113,7 +113,7 @@ class Base extends CoreBase {
|
|
113
113
|
* We only want to set a default route, in case the HashHistory is empty and there is no initial
|
114
114
|
* value that will get consumed.
|
115
115
|
*/
|
116
|
-
!Neo.config.hash && defaultHash && Neo.Main.setRoute({value: defaultHash})
|
116
|
+
!Neo.config.hash && defaultHash && Neo.Main.setRoute({value: defaultHash, windowId})
|
117
117
|
}
|
118
118
|
}
|
119
119
|
|
package/src/core/Observable.mjs
CHANGED
@@ -33,12 +33,28 @@ class Observable extends Base {
|
|
33
33
|
* @returns {String|null} eventId null in case an object gets passed as the name (multiple ids)
|
34
34
|
*/
|
35
35
|
addListener(name, opts, scope, eventId, data, order) {
|
36
|
-
let me
|
37
|
-
delay
|
38
|
-
|
39
|
-
|
36
|
+
let me = this,
|
37
|
+
delay = 0,
|
38
|
+
eventIdObject = typeof eventId === 'object',
|
39
|
+
nameObject = typeof name === 'object',
|
40
|
+
once = false,
|
41
|
+
optsType = typeof opts,
|
40
42
|
listener, existing, eventConfig;
|
41
43
|
|
44
|
+
/*
|
45
|
+
* let us support the following format too:
|
46
|
+
*
|
47
|
+
* currentWorker.on('connected', () => {
|
48
|
+
* Base.sendRemotes(className, remote)
|
49
|
+
* }, me, {once: true})
|
50
|
+
*/
|
51
|
+
if (eventIdObject && optsType === 'function') {
|
52
|
+
eventId.fn = opts;
|
53
|
+
opts = eventId;
|
54
|
+
optsType = 'object';
|
55
|
+
eventId = null;
|
56
|
+
}
|
57
|
+
|
42
58
|
if (nameObject) {
|
43
59
|
if (name.hasOwnProperty('delay')) {
|
44
60
|
delay = name.delay;
|
@@ -62,16 +78,16 @@ class Observable extends Base {
|
|
62
78
|
me.addListener(key, {delay, fn: value, once, scope})
|
63
79
|
}
|
64
80
|
})
|
65
|
-
} else if (
|
81
|
+
} else if (optsType === 'object') {
|
66
82
|
delay = delay || opts.delay;
|
67
83
|
eventId = eventId || opts.eventId;
|
68
84
|
listener = opts.fn;
|
69
85
|
once = once || opts.once;
|
70
86
|
order = order || opts.order;
|
71
87
|
scope = scope || opts.scope
|
72
|
-
} else if (
|
88
|
+
} else if (optsType === 'function') {
|
73
89
|
listener = opts
|
74
|
-
} else if (
|
90
|
+
} else if (optsType === 'string') {
|
75
91
|
listener = opts // VC hook, can get parsed after onConstructed in case the view uses the parent VC
|
76
92
|
} else {
|
77
93
|
throw new Error('Invalid addListener call: ' + name)
|
package/src/dialog/Base.mjs
CHANGED
@@ -136,17 +136,10 @@ class Base extends Panel {
|
|
136
136
|
title_: null,
|
137
137
|
/**
|
138
138
|
* Set to `true` to have tabbing wrap within this Dialog.
|
139
|
-
*
|
140
139
|
* Should be used with `modal`.
|
141
140
|
* @member {Boolean} trapFocus_=false
|
142
141
|
*/
|
143
|
-
trapFocus_: false
|
144
|
-
/**
|
145
|
-
* Set to `true` to have this Dialog centered in the viewport.
|
146
|
-
*
|
147
|
-
* @member {Boolean} centered_=false
|
148
|
-
*/
|
149
|
-
centered_: false
|
142
|
+
trapFocus_: false
|
150
143
|
}
|
151
144
|
|
152
145
|
/**
|
@@ -154,22 +147,7 @@ class Base extends Panel {
|
|
154
147
|
*/
|
155
148
|
construct(config) {
|
156
149
|
super.construct(config);
|
157
|
-
|
158
|
-
let me = this,
|
159
|
-
{style} = me;
|
160
|
-
|
161
|
-
me.createHeader();
|
162
|
-
|
163
|
-
if (!me.animateTargetId && !me.centered) {
|
164
|
-
Neo.assignDefaults(style, {
|
165
|
-
left : '50%',
|
166
|
-
top : '50%',
|
167
|
-
transform: 'translate(-50%, -50%)',
|
168
|
-
width : '50%'
|
169
|
-
});
|
170
|
-
|
171
|
-
me.style = style
|
172
|
-
}
|
150
|
+
this.createHeader()
|
173
151
|
}
|
174
152
|
|
175
153
|
/**
|
@@ -204,17 +182,6 @@ class Base extends Panel {
|
|
204
182
|
super.afterSetAppName(value, oldValue)
|
205
183
|
}
|
206
184
|
|
207
|
-
/**
|
208
|
-
* Triggered after the centered config got changed
|
209
|
-
* @param {Boolean} value
|
210
|
-
* @param {Boolean} oldValue
|
211
|
-
* @protected
|
212
|
-
*/
|
213
|
-
afterSetCentered(value, oldValue) {
|
214
|
-
NeoArray.toggle(this.vdom.cls, 'neo-centered', value);
|
215
|
-
this.update();
|
216
|
-
}
|
217
|
-
|
218
185
|
/**
|
219
186
|
* Triggered after the draggable config got changed
|
220
187
|
* @param {Boolean} value
|
@@ -392,8 +359,12 @@ class Base extends Panel {
|
|
392
359
|
{appName, id, style} = me,
|
393
360
|
rect = await me.getDomRect(me.animateTargetId);
|
394
361
|
|
362
|
+
// rendered outside the visible area
|
395
363
|
await me.render(true);
|
396
364
|
|
365
|
+
let [dialogRect, bodyRect] = await me.getDomRect([me.id, 'document.body']);
|
366
|
+
console.log(dialogRect, bodyRect);
|
367
|
+
|
397
368
|
// Move to cover the animation target
|
398
369
|
await Neo.applyDeltas(appName, {
|
399
370
|
id,
|
@@ -415,11 +386,10 @@ class Base extends Panel {
|
|
415
386
|
add: ['animated-hiding-showing']
|
416
387
|
},
|
417
388
|
style: {
|
418
|
-
height
|
419
|
-
left
|
420
|
-
top
|
421
|
-
|
422
|
-
width : style?.width || '50%'
|
389
|
+
height: style?.height || `${dialogRect.height}px`,
|
390
|
+
left : style?.left || `${Math.round(bodyRect.width / 2 - dialogRect.width / 2)}px`,
|
391
|
+
top : style?.top || `${Math.round(bodyRect.height / 2 - dialogRect.height / 2)}px`,
|
392
|
+
width : style?.width || `${dialogRect.width}px`
|
423
393
|
}
|
424
394
|
});
|
425
395
|
|
@@ -699,8 +669,11 @@ class Base extends Panel {
|
|
699
669
|
}
|
700
670
|
}
|
701
671
|
|
672
|
+
/**
|
673
|
+
*
|
674
|
+
*/
|
702
675
|
onKeyDownEscape() {
|
703
|
-
this.hidden = true
|
676
|
+
this.hidden = true
|
704
677
|
}
|
705
678
|
|
706
679
|
/**
|
@@ -710,7 +683,7 @@ class Base extends Panel {
|
|
710
683
|
let me = this;
|
711
684
|
|
712
685
|
if (animate) {
|
713
|
-
me.animateShow()
|
686
|
+
me.animateShow()
|
714
687
|
} else {
|
715
688
|
if (!me.rendered) {
|
716
689
|
me.render(true)
|
@@ -726,16 +699,21 @@ class Base extends Panel {
|
|
726
699
|
* @param {String} id=this.id
|
727
700
|
*/
|
728
701
|
syncModalMask(id=this.id) {
|
702
|
+
let {modal, windowId} = this;
|
703
|
+
|
729
704
|
// This should sync the visibility and position of the modal mask element.
|
730
|
-
Neo.main.DomAccess.syncModalMask({id, modal
|
705
|
+
Neo.main.DomAccess.syncModalMask({id, modal, windowId})
|
731
706
|
}
|
732
707
|
|
733
708
|
/**
|
734
709
|
*
|
735
710
|
*/
|
736
711
|
syncTrapFocus() {
|
737
|
-
|
738
|
-
|
712
|
+
let me = this,
|
713
|
+
{id, windowId} = me;
|
714
|
+
|
715
|
+
if (me.mounted) {
|
716
|
+
Neo.main.DomAccess.trapFocus({id, trap: me.trapFocus, windowId})
|
739
717
|
}
|
740
718
|
}
|
741
719
|
}
|
package/src/form/field/Color.mjs
CHANGED
@@ -19,9 +19,9 @@ class Color extends ComboBox {
|
|
19
19
|
*/
|
20
20
|
ntype: 'colorfield',
|
21
21
|
/**
|
22
|
-
* @member {String[]} baseCls=['neo-colorfield','neo-
|
22
|
+
* @member {String[]} baseCls=['neo-colorfield','neo-combobox','neo-pickerfield','neo-textfield']
|
23
23
|
*/
|
24
|
-
baseCls: ['neo-colorfield', 'neo-
|
24
|
+
baseCls: ['neo-colorfield', 'neo-combobox', 'neo-pickerfield', 'neo-textfield'],
|
25
25
|
/**
|
26
26
|
* The data.Model field which contains the color value
|
27
27
|
* @member {String} colorField='name'
|
@@ -95,10 +95,10 @@ class Color extends ComboBox {
|
|
95
95
|
* @returns {String}
|
96
96
|
*/
|
97
97
|
getColor() {
|
98
|
-
let me
|
99
|
-
{
|
98
|
+
let me = this,
|
99
|
+
{inputValue, value} = me;
|
100
100
|
|
101
|
-
return
|
101
|
+
return value ? me.colorFormatter(me, value) : me.forceSelection ? null : inputValue
|
102
102
|
}
|
103
103
|
|
104
104
|
/**
|
@@ -77,6 +77,25 @@ class NeoIntersectionObserver extends Base {
|
|
77
77
|
})
|
78
78
|
}
|
79
79
|
|
80
|
+
/**
|
81
|
+
* @param {IntersectionObserverEntry[]} entries
|
82
|
+
* @param {IntersectionObserver} observer
|
83
|
+
*/
|
84
|
+
isVisible(entries, observer) {
|
85
|
+
let me = this,
|
86
|
+
data, path, target;
|
87
|
+
|
88
|
+
entries.forEach(entry => {
|
89
|
+
target = entry.target;
|
90
|
+
data = target.dataset && {...target.dataset} || null;
|
91
|
+
path = DomEvents.getPathFromElement(entry.target).map(e => DomEvents.getTargetData(e));
|
92
|
+
|
93
|
+
if (entry.isIntersecting) {
|
94
|
+
me.sendMessage({data, id: observer.rootId, isIntersecting: true, path, targetId: target.id})
|
95
|
+
}
|
96
|
+
})
|
97
|
+
}
|
98
|
+
|
80
99
|
/**
|
81
100
|
* Add more or new items into an existing observer instance
|
82
101
|
* @param {Object} data
|
@@ -128,7 +147,7 @@ class NeoIntersectionObserver extends Base {
|
|
128
147
|
*/
|
129
148
|
register(data) {
|
130
149
|
let me = this,
|
131
|
-
cache
|
150
|
+
{cache} = me,
|
132
151
|
{id, observe} = data,
|
133
152
|
observer;
|
134
153
|
|
package/src/model/Component.mjs
CHANGED
@@ -153,12 +153,14 @@ class Component extends Base {
|
|
153
153
|
* @protected
|
154
154
|
*/
|
155
155
|
beforeSetStores(value, oldValue) {
|
156
|
-
|
156
|
+
if (value) {
|
157
|
+
let controller = this.component.getController();
|
157
158
|
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
159
|
+
Object.entries(value).forEach(([key, storeValue]) => {
|
160
|
+
controller?.parseConfig(storeValue);
|
161
|
+
value[key] = ClassSystemUtil.beforeSetInstance(storeValue)
|
162
|
+
})
|
163
|
+
}
|
162
164
|
|
163
165
|
return value
|
164
166
|
}
|
@@ -445,13 +447,13 @@ class Component extends Base {
|
|
445
447
|
* @returns {Neo.model.Component|null}
|
446
448
|
*/
|
447
449
|
getParent() {
|
448
|
-
let
|
450
|
+
let {parent} = this;
|
449
451
|
|
450
|
-
if (
|
451
|
-
return
|
452
|
+
if (parent) {
|
453
|
+
return parent
|
452
454
|
}
|
453
455
|
|
454
|
-
return
|
456
|
+
return this.component.parent?.getModel() || null
|
455
457
|
}
|
456
458
|
|
457
459
|
/**
|
@@ -138,7 +138,7 @@ class DateSelectorModel extends Model {
|
|
138
138
|
super.register(component);
|
139
139
|
|
140
140
|
let scope = {scope: this.id},
|
141
|
-
{view} = this
|
141
|
+
{view} = this;
|
142
142
|
|
143
143
|
view.keys?._keys.push(
|
144
144
|
{fn: 'onKeyDownDown' ,key: 'Down' ,...scope},
|
@@ -153,7 +153,7 @@ class DateSelectorModel extends Model {
|
|
153
153
|
*/
|
154
154
|
unregister() {
|
155
155
|
let scope = {scope: this.id},
|
156
|
-
{view} = this
|
156
|
+
{view} = this;
|
157
157
|
|
158
158
|
view.keys?.removeKeys([
|
159
159
|
{fn: 'onKeyDownDown' ,key: 'Down' ,...scope},
|
package/src/util/HashHistory.mjs
CHANGED
@@ -8,7 +8,6 @@ import Observable from '../core/Observable.mjs';
|
|
8
8
|
*/
|
9
9
|
class HashHistory extends Base {
|
10
10
|
/**
|
11
|
-
* True automatically applies the core.Observable mixin
|
12
11
|
* @member {Boolean} observable=true
|
13
12
|
* @static
|
14
13
|
*/
|
@@ -16,7 +15,7 @@ class HashHistory extends Base {
|
|
16
15
|
|
17
16
|
static config = {
|
18
17
|
/**
|
19
|
-
* @member {String} className='Neo.util.
|
18
|
+
* @member {String} className='Neo.util.HashHistory'
|
20
19
|
* @protected
|
21
20
|
*/
|
22
21
|
className: 'Neo.util.HashHistory',
|
@@ -31,24 +30,54 @@ class HashHistory extends Base {
|
|
31
30
|
*/
|
32
31
|
maxItems: 50,
|
33
32
|
/**
|
34
|
-
*
|
33
|
+
* Storing one stack per windowId
|
34
|
+
* @member {Object} stacks={}
|
35
35
|
* @protected
|
36
36
|
*/
|
37
|
-
|
37
|
+
stacks: {}
|
38
38
|
}
|
39
39
|
|
40
40
|
/**
|
41
|
+
* Convenience shortcut
|
42
|
+
* @param {Number} [windowId]
|
41
43
|
* @returns {Object}
|
42
44
|
*/
|
43
|
-
first() {
|
44
|
-
return this.
|
45
|
+
first(windowId) {
|
46
|
+
return this.getAt(0, windowId)
|
45
47
|
}
|
46
48
|
|
47
49
|
/**
|
50
|
+
* @param {Number} index
|
51
|
+
* @param {Number} [windowId]
|
48
52
|
* @returns {Number}
|
49
53
|
*/
|
50
|
-
|
51
|
-
return this.
|
54
|
+
getAt(index, windowId) {
|
55
|
+
return this.getStack(windowId)[index]
|
56
|
+
}
|
57
|
+
|
58
|
+
/**
|
59
|
+
* @param {Number} [windowId]
|
60
|
+
* @returns {Number}
|
61
|
+
*/
|
62
|
+
getCount(windowId) {
|
63
|
+
return this.getStack(windowId).length
|
64
|
+
}
|
65
|
+
|
66
|
+
/**
|
67
|
+
* @param {Number} [windowId]
|
68
|
+
* @returns {Number}
|
69
|
+
*/
|
70
|
+
getStack(windowId) {
|
71
|
+
let me = this,
|
72
|
+
{stacks} = me,
|
73
|
+
stackId = windowId || Object.keys(stacks)[0],
|
74
|
+
stack = stacks[stackId];
|
75
|
+
|
76
|
+
if (!stack) {
|
77
|
+
stacks[stackId] = stack = []
|
78
|
+
}
|
79
|
+
|
80
|
+
return stack
|
52
81
|
}
|
53
82
|
|
54
83
|
/**
|
@@ -59,10 +88,12 @@ class HashHistory extends Base {
|
|
59
88
|
* @param {Number} data.windowId
|
60
89
|
*/
|
61
90
|
push(data) {
|
62
|
-
let me
|
63
|
-
{
|
91
|
+
let me = this,
|
92
|
+
{windowId} = data,
|
93
|
+
stack = me.getStack(windowId);
|
64
94
|
|
65
95
|
if (stack[0]?.hashString !== data.hashString) {
|
96
|
+
delete data[windowId];
|
66
97
|
stack.unshift(data);
|
67
98
|
|
68
99
|
if (stack.length > me.maxItems) {
|
@@ -74,10 +105,12 @@ class HashHistory extends Base {
|
|
74
105
|
}
|
75
106
|
|
76
107
|
/**
|
108
|
+
* Convenience shortcut
|
109
|
+
* @param {Number} [windowId]
|
77
110
|
* @returns {Object}
|
78
111
|
*/
|
79
|
-
second() {
|
80
|
-
return this.
|
112
|
+
second(windowId) {
|
113
|
+
return this.getAt(0, windowId)
|
81
114
|
}
|
82
115
|
}
|
83
116
|
|
package/src/worker/Base.mjs
CHANGED
@@ -252,9 +252,14 @@ class Base extends CoreBase {
|
|
252
252
|
|
253
253
|
return new Promise(function(resolve, reject) {
|
254
254
|
let message = me.sendMessage(dest, opts, transfer),
|
255
|
-
msgId = message
|
255
|
+
msgId = message?.id;
|
256
256
|
|
257
|
-
|
257
|
+
if (!msgId) {
|
258
|
+
// a window got closed and the message port no longer exist (SharedWorkers)
|
259
|
+
reject()
|
260
|
+
} else {
|
261
|
+
me.promises[msgId] = {reject, resolve}
|
262
|
+
}
|
258
263
|
})
|
259
264
|
}
|
260
265
|
|
@@ -282,22 +287,24 @@ class Base extends CoreBase {
|
|
282
287
|
port = me.getPort({id: opts.port}).port
|
283
288
|
} else if (opts.windowId) {
|
284
289
|
portObject = me.getPort({windowId: opts.windowId});
|
285
|
-
port = portObject
|
290
|
+
port = portObject?.port;
|
286
291
|
|
287
|
-
opts.port = portObject
|
292
|
+
opts.port = portObject?.id
|
288
293
|
} else if (opts.appName) {
|
289
294
|
portObject = me.getPort({appName: opts.appName});
|
290
|
-
port = portObject
|
295
|
+
port = portObject?.port;
|
291
296
|
|
292
|
-
opts.port = portObject
|
297
|
+
opts.port = portObject?.id
|
293
298
|
} else {
|
294
299
|
port = me.ports[0].port
|
295
300
|
}
|
296
301
|
}
|
297
302
|
|
298
|
-
|
303
|
+
if (port) {
|
304
|
+
message = new Message(opts);
|
305
|
+
port.postMessage(message, transfer);
|
306
|
+
}
|
299
307
|
|
300
|
-
port.postMessage(message, transfer);
|
301
308
|
return message
|
302
309
|
}
|
303
310
|
}
|