@xibosignage/xibo-layout-renderer 1.0.28 → 1.0.29
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/Modules/ActionController/ActionController.d.ts +4 -1
- package/dist/xibo-layout-renderer.cjs.js +108 -35
- package/dist/xibo-layout-renderer.cjs.js.map +1 -1
- package/dist/xibo-layout-renderer.d.ts +4 -1
- package/dist/xibo-layout-renderer.esm.js +108 -35
- package/dist/xibo-layout-renderer.esm.js.map +1 -1
- package/dist/xibo-layout-renderer.js +108 -35
- package/dist/xibo-layout-renderer.min.js +7 -7
- package/dist/xibo-layout-renderer.min.js.map +1 -1
- package/package.json +1 -1
|
@@ -73575,7 +73575,7 @@ ${segmentInfoString(segmentInfo)}`); // If there's an init segment associated wi
|
|
|
73575
73575
|
cssText += "\n visibility: hidden;\n opacity: 0;\n z-index: 0;\n ";
|
|
73576
73576
|
}
|
|
73577
73577
|
$media.style.cssText = cssText;
|
|
73578
|
-
if (self.render === 'html' || self.mediaType === 'ticker' || self.mediaType === 'webpage') {
|
|
73578
|
+
if (self.mediaType !== 'spacer' && (self.render === 'html' || self.mediaType === 'ticker' || self.mediaType === 'webpage')) {
|
|
73579
73579
|
self.checkIframeStatus = true;
|
|
73580
73580
|
self.iframe = prepareIframe(self);
|
|
73581
73581
|
} else if (self.mediaType === "image") {
|
|
@@ -73723,8 +73723,6 @@ ${segmentInfoString(segmentInfo)}`); // If there's an init segment associated wi
|
|
|
73723
73723
|
region.html.appendChild(media.html);
|
|
73724
73724
|
}
|
|
73725
73725
|
function prepareHtmlMedia(media, region) {
|
|
73726
|
-
// Set state as false ( for now )
|
|
73727
|
-
media.ready = false;
|
|
73728
73726
|
if (media.html) {
|
|
73729
73727
|
var mediaId = getMediaId(media);
|
|
73730
73728
|
// Clean up old copy of the media
|
|
@@ -73736,14 +73734,16 @@ ${segmentInfoString(segmentInfo)}`); // If there's an init segment associated wi
|
|
|
73736
73734
|
mediaId: mediaId,
|
|
73737
73735
|
mediaInRegion: mediaInRegion
|
|
73738
73736
|
});
|
|
73739
|
-
// Append iframe
|
|
73740
|
-
media.html.innerHTML = '';
|
|
73741
|
-
media.html.appendChild(media.iframe);
|
|
73742
73737
|
if (!mediaInRegion) {
|
|
73743
|
-
//
|
|
73738
|
+
// Append iframe and insert into region only when not already in the DOM.
|
|
73739
|
+
// Calling innerHTML = '' when the element is already present detaches the
|
|
73740
|
+
// iframe, causing the browser to reload its src unnecessarily (e.g. when
|
|
73741
|
+
// a media was preloaded then skipped by a navigation action).
|
|
73742
|
+
media.html.innerHTML = '';
|
|
73743
|
+
media.html.appendChild(media.iframe);
|
|
73744
73744
|
region.html.appendChild(media.html);
|
|
73745
|
-
media.ready = true;
|
|
73746
73745
|
}
|
|
73746
|
+
media.ready = true;
|
|
73747
73747
|
}
|
|
73748
73748
|
}
|
|
73749
73749
|
exports.FaultCodes = void 0;
|
|
@@ -74051,7 +74051,12 @@ ${segmentInfoString(segmentInfo)}`); // If there's an init segment associated wi
|
|
|
74051
74051
|
var _this$sspImpressionUr, _this$sspErrorUrls;
|
|
74052
74052
|
_this.xlr.emitter.emit('sspWidgetEnd', (_this$sspImpressionUr = _this.sspImpressionUrls) !== null && _this$sspImpressionUr !== void 0 ? _this$sspImpressionUr : [], (_this$sspErrorUrls = _this.sspErrorUrls) !== null && _this$sspErrorUrls !== void 0 ? _this$sspErrorUrls : [], _this.sspImpressionUrls ? _this.duration : 0);
|
|
74053
74053
|
}
|
|
74054
|
-
media.
|
|
74054
|
+
// Only advance the region if this media is still the active one.
|
|
74055
|
+
// A user-triggered next/prev action may have already moved currMedia
|
|
74056
|
+
// on, in which case the timer firing here would cause a double-advance.
|
|
74057
|
+
if (media === media.region.currMedia) {
|
|
74058
|
+
media.region.playNextMedia();
|
|
74059
|
+
}
|
|
74055
74060
|
});
|
|
74056
74061
|
this.on('cancelled', function (media) {
|
|
74057
74062
|
if (media.state === MediaState.CANCELLED) return;
|
|
@@ -74095,6 +74100,10 @@ ${segmentInfoString(segmentInfo)}`); // If there's an init segment associated wi
|
|
|
74095
74100
|
key: "startMediaTimer",
|
|
74096
74101
|
value: function startMediaTimer(media) {
|
|
74097
74102
|
var _this2 = this;
|
|
74103
|
+
// Always reset the counter so a media replayed after cancellation runs
|
|
74104
|
+
// for its full duration rather than the residual time left from the
|
|
74105
|
+
// previous play.
|
|
74106
|
+
this.mediaTimeCount = 0;
|
|
74098
74107
|
var preloadTimeMs = 2000;
|
|
74099
74108
|
var preloadTimeBufferMs = media.duration * 1000 / 2 - preloadTimeMs;
|
|
74100
74109
|
var isPreparingNextMedia = false;
|
|
@@ -74970,11 +74979,19 @@ ${segmentInfoString(segmentInfo)}`); // If there's an init segment associated wi
|
|
|
74970
74979
|
nxtMedia: (_this$nxtMedia2 = this.nxtMedia) === null || _this$nxtMedia2 === void 0 ? void 0 : _this$nxtMedia2.containerName
|
|
74971
74980
|
});
|
|
74972
74981
|
if (!this.layout.isOverlay && crossedEnd) {
|
|
74982
|
+
var _this$currMedia8;
|
|
74973
74983
|
this.finished();
|
|
74974
74984
|
if (this.layout.allEnded) {
|
|
74975
74985
|
console.debug('??? XLR.debug >> Region - playNextMedia - layout all ended');
|
|
74976
74986
|
return;
|
|
74977
74987
|
}
|
|
74988
|
+
// Freeze single-media HTML at its last state while waiting for other
|
|
74989
|
+
// regions to complete. The guard at the top only catches the second
|
|
74990
|
+
// call; this one catches the first completion when complete was just
|
|
74991
|
+
// set by finished() above.
|
|
74992
|
+
if (((_this$currMedia8 = this.currMedia) === null || _this$currMedia8 === void 0 ? void 0 : _this$currMedia8.render) === 'html' && this.totalMediaObjects === 1 && this.oldMedia === this.currMedia) {
|
|
74993
|
+
return;
|
|
74994
|
+
}
|
|
74978
74995
|
}
|
|
74979
74996
|
this.transitionNodes(this.oldMedia, this.currMedia);
|
|
74980
74997
|
}
|
|
@@ -74984,11 +75001,18 @@ ${segmentInfoString(segmentInfo)}`); // If there's an init segment associated wi
|
|
|
74984
75001
|
if (this.currentMediaIndex <= 0 || this.ended) {
|
|
74985
75002
|
return;
|
|
74986
75003
|
}
|
|
75004
|
+
var interruptedMedia = this.currMedia;
|
|
74987
75005
|
this.oldMedia = this.currMedia;
|
|
74988
75006
|
this.currentMediaIndex -= 1;
|
|
74989
75007
|
this.currMedia = this.mediaObjects[this.currentMediaIndex];
|
|
74990
75008
|
this.nxtMedia = this.mediaObjects[(this.currentMediaIndex + 1) % this.totalMediaObjects];
|
|
74991
75009
|
this.complete = false;
|
|
75010
|
+
// Cancel the interrupted media after advancing currMedia, using the same
|
|
75011
|
+
// pattern as gotoMediaInRegion — emitting after the update ensures the
|
|
75012
|
+
// handler's (media === currMedia) guard correctly skips playNextMedia.
|
|
75013
|
+
if ((interruptedMedia === null || interruptedMedia === void 0 ? void 0 : interruptedMedia.state) === MediaState.PLAYING) {
|
|
75014
|
+
interruptedMedia.emitter.emit('cancelled', interruptedMedia);
|
|
75015
|
+
}
|
|
74992
75016
|
console.debug('region::playPreviousMedia', this);
|
|
74993
75017
|
this.transitionNodes(this.oldMedia, this.currMedia);
|
|
74994
75018
|
}
|
|
@@ -75066,6 +75090,7 @@ ${segmentInfoString(segmentInfo)}`); // If there's an init segment associated wi
|
|
|
75066
75090
|
_defineProperty(this, "$actionControllerTitle", void 0);
|
|
75067
75091
|
_defineProperty(this, "$actionsContainer", void 0);
|
|
75068
75092
|
_defineProperty(this, "translations", {});
|
|
75093
|
+
_defineProperty(this, "keyboardHandler", null);
|
|
75069
75094
|
this.parent = parent;
|
|
75070
75095
|
this.actions = actions;
|
|
75071
75096
|
this.options = options;
|
|
@@ -75230,7 +75255,7 @@ ${segmentInfoString(segmentInfo)}`); // If there's an init segment associated wi
|
|
|
75230
75255
|
this.parent.xlr.gotoPrevLayout();
|
|
75231
75256
|
}
|
|
75232
75257
|
}
|
|
75233
|
-
/** Change media in region (next/previous) */
|
|
75258
|
+
/** Change media in region (next/previous) with wrap-around at boundaries. */
|
|
75234
75259
|
}, {
|
|
75235
75260
|
key: "gotoMediaInRegion",
|
|
75236
75261
|
value: function gotoMediaInRegion(regionId, actionType) {
|
|
@@ -75238,15 +75263,34 @@ ${segmentInfoString(segmentInfo)}`); // If there's an init segment associated wi
|
|
|
75238
75263
|
regionId: regionId,
|
|
75239
75264
|
actionType: actionType
|
|
75240
75265
|
});
|
|
75241
|
-
// Find target region
|
|
75242
75266
|
this.parent.regions.forEach(function (regionObj) {
|
|
75243
|
-
if (regionObj.id
|
|
75244
|
-
|
|
75245
|
-
|
|
75246
|
-
|
|
75247
|
-
|
|
75248
|
-
|
|
75267
|
+
if (regionObj.id !== regionId || regionObj.ended) return;
|
|
75268
|
+
var total = regionObj.totalMediaObjects;
|
|
75269
|
+
if (total === 0) return;
|
|
75270
|
+
// Snapshot the currently-playing media before updating currMedia so
|
|
75271
|
+
// we can cancel it cleanly after the region state is advanced.
|
|
75272
|
+
var interruptedMedia = regionObj.currMedia;
|
|
75273
|
+
// Compute new index with wrap-around. We do NOT delegate to
|
|
75274
|
+
// playNextMedia() / playPreviousMedia() here because those carry
|
|
75275
|
+
// normal playlist-cycle semantics (finished(), regionExpired()) that
|
|
75276
|
+
// must not fire during user-driven navigation.
|
|
75277
|
+
var newIndex = actionType === 'next' ? (regionObj.currentMediaIndex + 1) % total : (regionObj.currentMediaIndex - 1 + total) % total;
|
|
75278
|
+
regionObj.oldMedia = regionObj.currMedia;
|
|
75279
|
+
regionObj.currentMediaIndex = newIndex;
|
|
75280
|
+
regionObj.currMedia = regionObj.mediaObjects[newIndex];
|
|
75281
|
+
regionObj.nxtMedia = regionObj.mediaObjects[(newIndex + 1) % total];
|
|
75282
|
+
regionObj.complete = false;
|
|
75283
|
+
// Properly cancel the interrupted media AFTER updating currMedia.
|
|
75284
|
+
// Using 'cancelled' rather than bare clearInterval ensures state is
|
|
75285
|
+
// reset from PLAYING and mediaTimeCount is zeroed — without this,
|
|
75286
|
+
// returning to a cancelled media causes run() → 'start' to bail on
|
|
75287
|
+
// the state === PLAYING guard, leaving the region stuck indefinitely.
|
|
75288
|
+
// currMedia is already updated so the handler's guard
|
|
75289
|
+
// (media === media.region.currMedia) correctly skips playNextMedia.
|
|
75290
|
+
if ((interruptedMedia === null || interruptedMedia === void 0 ? void 0 : interruptedMedia.state) === MediaState.PLAYING) {
|
|
75291
|
+
interruptedMedia.emitter.emit('cancelled', interruptedMedia);
|
|
75249
75292
|
}
|
|
75293
|
+
regionObj.transitionNodes(regionObj.oldMedia, regionObj.currMedia);
|
|
75250
75294
|
});
|
|
75251
75295
|
}
|
|
75252
75296
|
}, {
|
|
@@ -75297,11 +75341,19 @@ ${segmentInfoString(segmentInfo)}`); // If there's an init segment associated wi
|
|
|
75297
75341
|
console.debug('[ActionController::loadMediaInRegion] Target media already queued, skipping duplicate insertion');
|
|
75298
75342
|
return;
|
|
75299
75343
|
}
|
|
75300
|
-
// Cancel the
|
|
75301
|
-
//
|
|
75302
|
-
|
|
75303
|
-
|
|
75304
|
-
|
|
75344
|
+
// Cancel the interrupted media so it doesn't double-advance when the playlist
|
|
75345
|
+
// returns to it. currMedia has not been advanced yet at this point (playNextMedia
|
|
75346
|
+
// does that below), so we cannot use emitter.emit('cancelled') — the handler's
|
|
75347
|
+
// currMedia guard would fire and call playNextMedia a second time. Instead we
|
|
75348
|
+
// cancel directly: clear the timer and reset state so the 'start' handler does
|
|
75349
|
+
// not bail on the state === PLAYING guard when this media is replayed.
|
|
75350
|
+
if (((_targetRegion2 = targetRegion) === null || _targetRegion2 === void 0 || (_targetRegion2 = _targetRegion2.currMedia) === null || _targetRegion2 === void 0 ? void 0 : _targetRegion2.state) === MediaState.PLAYING) {
|
|
75351
|
+
var interruptedMedia = targetRegion.currMedia;
|
|
75352
|
+
if (interruptedMedia.mediaTimer) {
|
|
75353
|
+
clearInterval(interruptedMedia.mediaTimer);
|
|
75354
|
+
interruptedMedia.mediaTimer = undefined;
|
|
75355
|
+
}
|
|
75356
|
+
interruptedMedia.state = MediaState.CANCELLED;
|
|
75305
75357
|
}
|
|
75306
75358
|
// Reset complete so the HTML-media guard in playNextMedia() doesn't block
|
|
75307
75359
|
// the transition (that guard is for single-media loops, not navWidget injections).
|
|
@@ -75330,6 +75382,12 @@ ${segmentInfoString(segmentInfo)}`); // If there's an init segment associated wi
|
|
|
75330
75382
|
}, {
|
|
75331
75383
|
key: "runAction",
|
|
75332
75384
|
value: function runAction(actionData, options) {
|
|
75385
|
+
// If this layout is no longer active (being cancelled or navigated away from),
|
|
75386
|
+
// discard the action so it doesn't interfere with the outgoing transition.
|
|
75387
|
+
// inLoop is set to false synchronously before finishAllRegions() in all nav paths.
|
|
75388
|
+
if (!this.parent.inLoop) {
|
|
75389
|
+
return;
|
|
75390
|
+
}
|
|
75333
75391
|
console.debug('[ActionController::runAction] Triggering action', {
|
|
75334
75392
|
actionData: actionData
|
|
75335
75393
|
});
|
|
@@ -75417,31 +75475,37 @@ ${segmentInfoString(segmentInfo)}`); // If there's an init segment associated wi
|
|
|
75417
75475
|
key: "initKeyboardActions",
|
|
75418
75476
|
value: function initKeyboardActions() {
|
|
75419
75477
|
var self = this;
|
|
75420
|
-
// Store actions in a map
|
|
75421
75478
|
var keyActions = new Map();
|
|
75422
|
-
this.$actionController.querySelectorAll('.action[
|
|
75479
|
+
this.$actionController.querySelectorAll('.action[triggertype="keyPress"]').forEach(function ($el) {
|
|
75423
75480
|
var dataset = $el.dataset;
|
|
75424
75481
|
var code = dataset.triggercode;
|
|
75425
75482
|
if (code) {
|
|
75426
|
-
// Create an empty array, if not yet set
|
|
75427
75483
|
if (!keyActions.get(code)) {
|
|
75428
75484
|
keyActions.set(code, []);
|
|
75429
75485
|
}
|
|
75430
|
-
// Add new action to array
|
|
75431
75486
|
keyActions.get(code).push(dataset);
|
|
75432
75487
|
}
|
|
75433
75488
|
});
|
|
75434
|
-
//
|
|
75435
|
-
|
|
75489
|
+
// Nothing to do if this layout has no keyboard-triggered actions.
|
|
75490
|
+
if (keyActions.size === 0) return;
|
|
75491
|
+
this.keyboardHandler = function (ev) {
|
|
75436
75492
|
var actions = keyActions.get(ev.code);
|
|
75437
|
-
// Are there action for this key code?
|
|
75438
75493
|
if (actions) {
|
|
75439
|
-
// Run all actions associated with it
|
|
75440
75494
|
actions.forEach(function (dataset) {
|
|
75441
75495
|
self.runAction(dataset, self.options);
|
|
75442
75496
|
});
|
|
75443
75497
|
}
|
|
75444
|
-
}
|
|
75498
|
+
};
|
|
75499
|
+
document.addEventListener('keydown', this.keyboardHandler);
|
|
75500
|
+
}
|
|
75501
|
+
/** Remove the keydown listener registered by initKeyboardActions. Call when the layout ends or is cancelled. */
|
|
75502
|
+
}, {
|
|
75503
|
+
key: "removeKeyboardActions",
|
|
75504
|
+
value: function removeKeyboardActions() {
|
|
75505
|
+
if (this.keyboardHandler) {
|
|
75506
|
+
document.removeEventListener('keydown', this.keyboardHandler);
|
|
75507
|
+
this.keyboardHandler = null;
|
|
75508
|
+
}
|
|
75445
75509
|
}
|
|
75446
75510
|
}]);
|
|
75447
75511
|
}();
|
|
@@ -75676,6 +75740,7 @@ ${segmentInfoString(segmentInfo)}`); // If there's an init segment associated wi
|
|
|
75676
75740
|
});
|
|
75677
75741
|
this.on('end', /*#__PURE__*/function () {
|
|
75678
75742
|
var _ref = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee2(layout) {
|
|
75743
|
+
var _layout$actionControl;
|
|
75679
75744
|
var $layout, _$layout$parentElemen;
|
|
75680
75745
|
return _regeneratorRuntime().wrap(function _callee2$(_context2) {
|
|
75681
75746
|
while (1) switch (_context2.prev = _context2.next) {
|
|
@@ -75734,9 +75799,10 @@ ${segmentInfoString(segmentInfo)}`); // If there's an init segment associated wi
|
|
|
75734
75799
|
}
|
|
75735
75800
|
// Emit layout end event
|
|
75736
75801
|
console.debug('>>>>> XLR.debug Awaited XLR::emitSync > End - Calling layoutEnd event');
|
|
75737
|
-
|
|
75802
|
+
(_layout$actionControl = layout.actionController) === null || _layout$actionControl === void 0 || _layout$actionControl.removeKeyboardActions();
|
|
75803
|
+
_context2.next = 14;
|
|
75738
75804
|
return layout.xlr.emitSync('layoutEnd', layout);
|
|
75739
|
-
case
|
|
75805
|
+
case 14:
|
|
75740
75806
|
if (_this.xlr.config.platform !== exports.ConsumerPlatform.CMS && layout.inLoop) {
|
|
75741
75807
|
// Transition next layout to current layout and prepare next layout if exist
|
|
75742
75808
|
_this.xlr.prepareLayouts().then( /*#__PURE__*/function () {
|
|
@@ -75766,7 +75832,7 @@ ${segmentInfoString(segmentInfo)}`); // If there's an init segment associated wi
|
|
|
75766
75832
|
};
|
|
75767
75833
|
}());
|
|
75768
75834
|
}
|
|
75769
|
-
case
|
|
75835
|
+
case 15:
|
|
75770
75836
|
case "end":
|
|
75771
75837
|
return _context2.stop();
|
|
75772
75838
|
}
|
|
@@ -75777,9 +75843,11 @@ ${segmentInfoString(segmentInfo)}`); // If there's an init segment associated wi
|
|
|
75777
75843
|
};
|
|
75778
75844
|
}());
|
|
75779
75845
|
this.on('cancelled', function (layout) {
|
|
75846
|
+
var _layout$actionControl2;
|
|
75780
75847
|
console.debug('>>>>> XLR.debug / Layout cancelled > Layout ID > ', layout.id);
|
|
75781
75848
|
layout.state = exports.ELayoutState.CANCELLED;
|
|
75782
75849
|
layout.inLoop = false;
|
|
75850
|
+
(_layout$actionControl2 = layout.actionController) === null || _layout$actionControl2 === void 0 || _layout$actionControl2.removeKeyboardActions();
|
|
75783
75851
|
// Dispose video handlers immediately so their stall watchdogs and error
|
|
75784
75852
|
// callbacks can't fire against a layout whose DOM is about to be removed.
|
|
75785
75853
|
var _iterator = _createForOfIteratorHelper(layout.regions),
|
|
@@ -75938,7 +76006,8 @@ ${segmentInfoString(segmentInfo)}`); // If there's an init segment associated wi
|
|
|
75938
76006
|
_this2.regions.push(regionObj);
|
|
75939
76007
|
});
|
|
75940
76008
|
this.actionController.initTouchActions();
|
|
75941
|
-
|
|
76009
|
+
// Keyboard actions are registered in run() so the global document listener
|
|
76010
|
+
// is only active while the layout is actually playing, not during background preparation.
|
|
75942
76011
|
}
|
|
75943
76012
|
}, {
|
|
75944
76013
|
key: "run",
|
|
@@ -75957,6 +76026,7 @@ ${segmentInfoString(segmentInfo)}`); // If there's an init segment associated wi
|
|
|
75957
76026
|
shouldParse: false
|
|
75958
76027
|
});
|
|
75959
76028
|
if ($layoutContainer) {
|
|
76029
|
+
var _this$actionControlle;
|
|
75960
76030
|
$layoutContainer.style.setProperty('visibility', 'visible');
|
|
75961
76031
|
$layoutContainer.style.setProperty('opacity', '1');
|
|
75962
76032
|
$layoutContainer.style.setProperty('z-index', this.zIndex !== null ? "".concat(this.zIndex) : '1');
|
|
@@ -75965,6 +76035,9 @@ ${segmentInfoString(segmentInfo)}`); // If there's an init segment associated wi
|
|
|
75965
76035
|
// Also set the background color of the player window > body
|
|
75966
76036
|
document.body.style.setProperty('background-color', "".concat(this.bgColor));
|
|
75967
76037
|
}
|
|
76038
|
+
// Register keyboard actions now that the layout is active.
|
|
76039
|
+
// Done here (not in parseXlf) so the global listener is scoped to playback time.
|
|
76040
|
+
(_this$actionControlle = this.actionController) === null || _this$actionControlle === void 0 || _this$actionControlle.initKeyboardActions();
|
|
75968
76041
|
// Emit start event
|
|
75969
76042
|
this.emitter.emit('start', this);
|
|
75970
76043
|
// Play regions
|