@viewlift/player-backup 1.0.0-lighteningjs → 1.0.1-lighteningjs

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.
@@ -0,0 +1,2 @@
1
+ .seekbar-container{background:#444;border-radius:6px;bottom:50px;cursor:pointer;height:12px;left:50%;margin:0;position:absolute;transform:translateX(-50%);user-select:none;width:90%;z-index:20}.seekbar-buffer{background:#888;z-index:1}.seekbar-buffer,.seekbar-progress{border-radius:6px;height:100%;position:absolute;width:0}.seekbar-progress{background:#4169e1;transition:width .1s linear;z-index:2}.seekbar-thumb{background:#fff;border:2px solid #4169e1;border-radius:50%;box-shadow:0 2px 8px rgba(0,0,0,.2);cursor:pointer;height:16px;position:absolute;top:50%;transform:translate(-50%,-50%);transition:background .2s;width:16px;z-index:3}.seekbar-thumb:hover{background:#ffeaea}.seekbar-tooltip{background:#222;border-radius:4px;bottom:24px;color:#fff;font-size:12px;left:0;padding:2px 8px;pointer-events:none;position:absolute;transform:translateX(-50%);white-space:nowrap;z-index:10}.seekbar-duration-label,.seekbar-time-label{color:#eee;font-size:13px;margin-right:4px;position:relative;top:18px;z-index:5}.play-pause-btn{left:50%;position:absolute!important;top:50%;transform:translate(-50%,-50%);z-index:30}
2
+ /*# sourceMappingURL=index.cjs.css.map */
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["playerSeekbar.css","player-ui.css"],"names":[],"mappings":"AAAA,mBAME,eAAgB,CAGhB,iBAAkB,CALlB,WAAY,CAIZ,cAAe,CAHf,WAAY,CAHZ,QAAS,CAQT,QAAS,CATT,iBAAkB,CAElB,0BAA2B,CAQ3B,gBAAiB,CAJjB,SAAU,CAKV,UACF,CAEA,gBAGE,eAAgB,CAGhB,SACF,CAEA,kCAJE,iBAAkB,CAHlB,WAAY,CADZ,iBAAkB,CAGlB,OAaF,CARA,kBAGE,kBAAmB,CAInB,2BAA6B,CAD7B,SAEF,CAEA,eAME,eAAgB,CAEhB,wBAAyB,CADzB,iBAAkB,CAGlB,mCAAqC,CACrC,cAAe,CANf,WAAY,CAJZ,iBAAkB,CAClB,OAAQ,CACR,8BAAgC,CAShC,yBAA2B,CAR3B,UAAW,CAKX,SAIF,CACA,qBACE,kBACF,CAEA,iBAKE,eAAgB,CAGhB,iBAAkB,CANlB,WAAY,CAIZ,UAAW,CAGX,cAAe,CANf,MAAO,CAIP,eAAgB,CAIhB,mBAAoB,CAVpB,iBAAkB,CAGlB,0BAA2B,CAM3B,kBAAmB,CAEnB,UACF,CAEA,4CAIE,UAAW,CADX,cAAe,CAEf,gBAAiB,CAJjB,iBAAkB,CAClB,QAAS,CAIT,SACF,CCzEA,gBAEE,QAAS,CADT,2BAA6B,CAE7B,OAAQ,CACR,8BAAgC,CAChC,UACF","file":"index.cjs.css","sourcesContent":[".seekbar-container {\n position: absolute;\n left: 50%;\n transform: translateX(-50%);\n bottom: 50px;\n height: 12px;\n background: #444;\n width: 90%;\n cursor: pointer;\n border-radius: 6px;\n margin: 0;\n user-select: none;\n z-index: 20;\n}\n\n.seekbar-buffer {\n position: absolute;\n height: 100%;\n background: #888;\n width: 0;\n border-radius: 6px;\n z-index: 1;\n}\n\n.seekbar-progress {\n position: absolute;\n height: 100%;\n background: #4169E1;\n width: 0;\n border-radius: 6px;\n z-index: 2;\n transition: width 0.1s linear;\n}\n\n.seekbar-thumb {\n position: absolute;\n top: 50%;\n transform: translate(-50%, -50%);\n width: 16px;\n height: 16px;\n background: #fff;\n border-radius: 50%;\n border: 2px solid #4169E1;\n z-index: 3;\n box-shadow: 0 2px 8px rgba(0,0,0,0.2);\n cursor: pointer;\n transition: background 0.2s;\n}\n.seekbar-thumb:hover {\n background: #ffeaea;\n}\n\n.seekbar-tooltip {\n position: absolute;\n bottom: 24px;\n left: 0;\n transform: translateX(-50%);\n background: #222;\n color: #fff;\n padding: 2px 8px;\n border-radius: 4px;\n font-size: 12px;\n white-space: nowrap;\n pointer-events: none;\n z-index: 10;\n}\n\n.seekbar-time-label, .seekbar-duration-label {\n position: relative;\n top: 18px;\n font-size: 13px;\n color: #eee;\n margin-right: 4px;\n z-index: 5;\n}\n","/* Center play/pause button absolutely in the middle of the player */\n.play-pause-btn {\n position: absolute !important;\n left: 50%;\n top: 50%;\n transform: translate(-50%, -50%);\n z-index: 30;\n} "]}
package/dist/index.cjs.js CHANGED
@@ -1 +1 @@
1
- "use strict";require("@viewlift/player-backup/esm/bundle.css");var t,e=function(t){return"lgTv"==t?"lg":"vizioTv"==t?"vizio":"xfinityX1"==t?"xfinityX1":"xbox"==t?"xBox":"samsung"};!function(t){t.LG="lgTv",t.Vizio="vizioTv",t.XfinityX1="xfinityX1",t.Xbox="xbox",t.Samsung="samsungTv"}(t||(t={}));var n=function(){function t(t){var e=this;this.listeners={},this.boundEmitters={},this.boundHandlerMap={},this.options=t,this.videoElement=document.createElement("video"),this.videoElement.id=t.playerId,this.videoElement.autoplay=!!t.autoplay,t.width&&(this.videoElement.width=t.width),t.height&&(this.videoElement.height=t.height),this.videoElement.style.display="block",this.videoElement.style.background="black";var n={play:this.onPlay,pause:this.onPause,ended:this.onEnded,timeupdate:this.onTimeupdate,error:this.onError,loadedmetadata:this.onLoadedmetadata,seeking:this.onSeeking,seeked:this.onSeeked,volumechange:this.onVolumechange};Object.keys(n).forEach(function(t){var i=n[t].bind(e);e.boundHandlerMap[t]=i,e.videoElement.addEventListener(t,i)})}return t.prototype.initialize=function(){return window.appMainConfig.apiBaseUrl,this.options.playerId,this.options.contentId,this.options.authToken,this.options.autoplay,this.options.profileId,this.options.deviceName,e(this.options.deviceName),window.appSettings.device,window.appMainConfig.internalName,!0},t.prototype.attachTo=function(t){t.appendChild(this.videoElement)},t.prototype.play=function(){this.videoElement.play()},t.prototype.pause=function(){this.videoElement.pause()},t.prototype.stop=function(){this.videoElement.pause(),this.videoElement.currentTime=0},t.prototype.destroy=function(){var t=this;this.videoElement.parentNode&&this.videoElement.parentNode.removeChild(this.videoElement),this.removeAllListeners(),Object.keys(this.boundHandlerMap).forEach(function(e){t.boundHandlerMap[e]&&(t.videoElement.removeEventListener(e,t.boundHandlerMap[e]),delete t.boundHandlerMap[e])})},Object.defineProperty(t.prototype,"element",{get:function(){return this.videoElement},enumerable:!1,configurable:!0}),t.prototype.onPlay=function(t){"function"==typeof this.options.onPlaybackSuccess&&this.options.onPlaybackSuccess()},t.prototype.onPause=function(t){},t.prototype.onEnded=function(t){"function"==typeof this.options.onPlaybackEnded&&this.options.onPlaybackEnded()},t.prototype.onTimeupdate=function(t){},t.prototype.onError=function(t){"function"==typeof this.options.onPlaybackError&&this.options.onPlaybackError(t)},t.prototype.onLoadedmetadata=function(t){},t.prototype.onSeeking=function(t){},t.prototype.onSeeked=function(t){},t.prototype.onVolumechange=function(t){},t.prototype.on=function(t,e){this.listeners[t]||(this.listeners[t]=[],this.boundEmitters[t]||(this.boundEmitters[t]=this.emitEvent(t),this.videoElement.addEventListener(t,this.boundEmitters[t]))),this.listeners[t].push(e)},t.prototype.off=function(t,e){this.listeners[t]&&(this.listeners[t]=this.listeners[t].filter(function(t){return t!==e}),0===this.listeners[t].length&&(this.boundEmitters[t]&&(this.videoElement.removeEventListener(t,this.boundEmitters[t]),delete this.boundEmitters[t]),delete this.listeners[t]))},t.prototype.once=function(t,e){var n=this,i=function(){for(var o=[],s=0;s<arguments.length;s++)o[s]=arguments[s];e.apply(void 0,o),n.off(t,i)};this.on(t,i)},t.prototype.emitEvent=function(t){var e=this;return function(n){e.listeners[t]&&e.listeners[t].forEach(function(t){return t(n)})}},t.prototype.removeAllListeners=function(){var t=this;Object.keys(this.listeners).forEach(function(e){t.boundEmitters[e]&&(t.videoElement.removeEventListener(e,t.boundEmitters[e]),delete t.boundEmitters[e])}),this.listeners={}},t}();exports.LightningVideoPlayer=n;
1
+ "use strict";var t=function(){return t=Object.assign||function(t){for(var e,n=1,i=arguments.length;n<i;n++)for(var s in e=arguments[n])Object.prototype.hasOwnProperty.call(e,s)&&(t[s]=e[s]);return t},t.apply(this,arguments)};"function"==typeof SuppressedError&&SuppressedError;var e=function(){function t(t){if(this.imgSrc=t.imgSrc||"",this.imgAltText=t.imgAltText||"",this.buttonText=t.buttonText||"",this.klassname=t.klassname||"default-button",this.width=t.width||100,this.height=t.height||50,this.focused=t.focused||!1,this.disabled=t.disabled||!1,this.handleClick=t.handleClick||function(){},"function"!=typeof t.handleClick)throw new Error("Button Class: handleClick must be a function");this.disabled&&(this.klassname+=" disabled"),this.focused&&(this.klassname+=" focused"),this.handleClick=this.handleClick.bind(this)}return t.prototype.mount=function(t){var e=this,n=document.createElement("button");if(n.className=this.klassname,n.style.width="".concat(this.width,"px"),n.style.height="".concat(this.height,"px"),n.disabled=this.disabled,n.tabIndex=0,this.imgSrc){var i=document.createElement("img");i.src=this.imgSrc,i.alt=this.imgAltText,n.appendChild(i)}else{var s=document.createElement("span");s.textContent=this.buttonText,n.appendChild(s)}n.addEventListener("click",this.handleClick),n.addEventListener("focus",function(){e.focused=!0,n.classList.add("focused")}),n.addEventListener("blur",function(){e.focused=!1,n.classList.remove("focused")}),this.buttonElement=n,t.appendChild(n)},t.prototype.unmount=function(){this.buttonElement&&(this.buttonElement.removeEventListener("click",this.handleClick),this.buttonElement.removeEventListener("focus",this.handleClick),this.buttonElement.removeEventListener("blur",this.handleClick),this.buttonElement=void 0)},t.prototype.focus=function(){this.buttonElement&&(this.buttonElement.focus(),this.buttonElement.classList.add("focused"),this.focused=!0)},t.prototype.blur=function(){this.buttonElement&&(this.buttonElement.blur(),this.buttonElement.classList.remove("focused"),this.focused=!1)},t}(),n=function(){function t(t){var e=this;this.isDragging=!1,this.focused=!1,this.video=t,this.container=document.createElement("div"),this.container.className="seekbar-container",this.container.tabIndex=0,this.buffer=document.createElement("div"),this.buffer.className="seekbar-buffer",this.progress=document.createElement("div"),this.progress.className="seekbar-progress",this.thumb=document.createElement("div"),this.thumb.className="seekbar-thumb",this.tooltip=document.createElement("div"),this.tooltip.className="seekbar-tooltip",this.tooltip.style.display="none",this.timeLabel=document.createElement("span"),this.timeLabel.className="seekbar-time-label",this.durationLabel=document.createElement("span"),this.durationLabel.className="seekbar-duration-label",this.container.appendChild(this.buffer),this.container.appendChild(this.progress),this.container.appendChild(this.thumb),this.container.appendChild(this.tooltip),this.container.appendChild(this.timeLabel),this.container.appendChild(this.durationLabel),this.video.addEventListener("timeupdate",function(){return e.update()}),this.video.addEventListener("progress",function(){return e.updateBuffer()}),this.video.addEventListener("durationchange",function(){return e.update()}),this.container.addEventListener("click",function(t){return e.seek(t)}),this.thumb.addEventListener("mousedown",function(t){return e.startDrag(t)}),this.container.addEventListener("mousemove",function(t){return e.showTooltip(t)}),this.container.addEventListener("mouseleave",function(){return e.hideTooltip()}),this.container.addEventListener("focus",function(){e.focused=!0,e.container.classList.add("focused")}),this.container.addEventListener("blur",function(){e.focused=!1,e.container.classList.remove("focused")})}return t.prototype.focus=function(){this.container.focus(),this.container.classList.add("focused"),this.focused=!0},t.prototype.blur=function(){this.container.blur(),this.container.classList.remove("focused"),this.focused=!1},t.prototype.formatTime=function(t){if(isNaN(t))return"0:00";var e=Math.floor(t/60),n=Math.floor(t%60);return"".concat(e,":").concat(String(n).padStart(2,"0"))},t.prototype.update=function(){var t=this.video.currentTime/this.video.duration*100;this.progress.style.width=t+"%",this.thumb.style.left=t+"%",this.timeLabel.textContent=this.formatTime(this.video.currentTime),this.durationLabel.textContent=" / "+this.formatTime(this.video.duration)},t.prototype.updateBuffer=function(){if(this.video.buffered.length){var t=this.video.buffered.end(this.video.buffered.length-1)/this.video.duration*100;this.buffer.style.width=t+"%"}},t.prototype.seek=function(t){if(!this.isDragging){var e=this.container.getBoundingClientRect(),n=(t.clientX-e.left)/e.width;this.video.currentTime=n*this.video.duration}},t.prototype.startDrag=function(t){var e=this;t.preventDefault(),this.isDragging=!0;var n=function(t){var n=e.container.getBoundingClientRect(),i=(t.clientX-n.left)/n.width;i=Math.max(0,Math.min(1,i)),e.progress.style.width=100*i+"%",e.thumb.style.left=100*i+"%",e.timeLabel.textContent=e.formatTime(i*e.video.duration)},i=function(t){var s=e.container.getBoundingClientRect(),o=(t.clientX-s.left)/s.width;o=Math.max(0,Math.min(1,o)),e.video.currentTime=o*e.video.duration,e.isDragging=!1,document.removeEventListener("mousemove",n),document.removeEventListener("mouseup",i)};document.addEventListener("mousemove",n),document.addEventListener("mouseup",i)},t.prototype.showTooltip=function(t){var e=this.container.getBoundingClientRect(),n=(t.clientX-e.left)/e.width,i=n*this.video.duration;this.tooltip.textContent=this.formatTime(i),this.tooltip.style.display="block",this.tooltip.style.left="".concat(100*n,"%")},t.prototype.hideTooltip=function(){this.tooltip.style.display="none"},t.prototype.mount=function(t){t.appendChild(this.container),this.update(),this.updateBuffer()},t.prototype.getElement=function(){return this.container},t}(),i=function(){function t(t){var e=t.player;this.player=e,this.container=document.createElement("div"),this.container.className="video-player-ui",this.createControls()}return t.prototype.createControls=function(){var t,i,s,o=this;this.playPauseBtn=new e({imgSrc:"",imgAltText:"Play/Pause",buttonText:"Play",width:80,height:40,klassname:"play-pause-btn",focused:!1,disabled:!1,handleClick:function(){o.player.video.paused?(o.player.play(),o.playPauseBtn&&o.playPauseBtn.buttonElement&&(o.playPauseBtn.buttonElement.textContent="Pause")):(o.player.pause(),o.playPauseBtn&&o.playPauseBtn.buttonElement&&(o.playPauseBtn.buttonElement.textContent="Play"))}}),this.playPauseBtn.mount(this.container),this.container.appendChild(this.player.video),this.seekbar=new n(this.player.video),this.seekbar.mount(this.container),(null===(t=this.playPauseBtn)||void 0===t?void 0:t.buttonElement)&&this.seekbar&&(this.playPauseBtn.buttonElement.addEventListener("keydown",function(t){var e;"ArrowDown"===t.key&&(t.preventDefault(),null===(e=o.seekbar)||void 0===e||e.focus())}),null===(s=null===(i=this.seekbar)||void 0===i?void 0:i.getElement())||void 0===s||s.addEventListener("keydown",function(t){var e;"ArrowUp"===t.key&&(t.preventDefault(),null===(e=o.playPauseBtn)||void 0===e||e.focus())}))},t.prototype.attachTo=function(t){t.appendChild(this.container)},t.prototype.getElement=function(){return this.container},t}();exports.createHlsPlayer=function(e,n){var s=document.createElement("video");s.controls=!1,s.style.width="100%",s.style.height="100%";var o=null;if(window.Hls&&window.Hls.isSupported())(o=new window.Hls).loadSource(n),o.attachMedia(s),o.on(window.Hls.Events.MANIFEST_PARSED,function(){s.play()});else{if(!s.canPlayType("application/vnd.apple.mpegurl"))throw new Error("HLS is not supported in this browser.");s.src=n,s.addEventListener("loadedmetadata",function(){s.play()})}var a={video:s,play:function(){return s.play()},pause:function(){return s.pause()}},r=new i({player:a});return r.attachTo(e),t(t({},a),{ui:r})};
package/dist/index.d.ts CHANGED
@@ -1,25 +1,12 @@
1
- import '@viewlift/player-backup/esm/bundle.css';
2
1
  export interface VideoPlayerOptions {
3
2
  onPlaybackSuccess?: () => void;
4
3
  onPlaybackEnded?: () => void;
5
4
  onPlaybackError?: (error?: any) => void;
6
- playerId: string;
7
- contentId: string;
8
- profileId: string;
9
- deviceId: string;
10
- authToken: string;
5
+ src: string;
11
6
  autoplay?: boolean;
12
7
  controls?: boolean;
13
8
  width?: number;
14
9
  height?: number;
15
- deviceName: DeviceType;
16
- }
17
- declare enum DeviceType {
18
- LG = "lgTv",
19
- Vizio = "vizioTv",
20
- XfinityX1 = "xfinityX1",
21
- Xbox = "xbox",
22
- Samsung = "samsungTv"
23
10
  }
24
11
  type EventHandler = (...args: any[]) => void;
25
12
  type VideoPlayerEvent = 'play' | 'pause' | 'ended' | 'timeupdate' | 'error' | 'loadedmetadata' | 'seeking' | 'seeked' | 'volumechange';
@@ -27,13 +14,13 @@ export declare class LightningVideoPlayer {
27
14
  /**
28
15
  * Reinitialize the current videoElement with a new set of options and handle autoplay.
29
16
  */
17
+ reinitialize(options: VideoPlayerOptions): void;
30
18
  private videoElement;
31
19
  private options;
32
20
  private listeners;
33
21
  private boundEmitters;
34
22
  private boundHandlerMap;
35
23
  constructor(options: VideoPlayerOptions);
36
- initialize(): boolean;
37
24
  attachTo(container: HTMLElement): void;
38
25
  play(): void;
39
26
  pause(): void;
@@ -0,0 +1,2 @@
1
+ .seekbar-container{background:#444;border-radius:6px;bottom:50px;cursor:pointer;height:12px;left:50%;margin:0;position:absolute;transform:translateX(-50%);user-select:none;width:90%;z-index:20}.seekbar-buffer{background:#888;z-index:1}.seekbar-buffer,.seekbar-progress{border-radius:6px;height:100%;position:absolute;width:0}.seekbar-progress{background:#4169e1;transition:width .1s linear;z-index:2}.seekbar-thumb{background:#fff;border:2px solid #4169e1;border-radius:50%;box-shadow:0 2px 8px rgba(0,0,0,.2);cursor:pointer;height:16px;position:absolute;top:50%;transform:translate(-50%,-50%);transition:background .2s;width:16px;z-index:3}.seekbar-thumb:hover{background:#ffeaea}.seekbar-tooltip{background:#222;border-radius:4px;bottom:24px;color:#fff;font-size:12px;left:0;padding:2px 8px;pointer-events:none;position:absolute;transform:translateX(-50%);white-space:nowrap;z-index:10}.seekbar-duration-label,.seekbar-time-label{color:#eee;font-size:13px;margin-right:4px;position:relative;top:18px;z-index:5}.play-pause-btn{left:50%;position:absolute!important;top:50%;transform:translate(-50%,-50%);z-index:30}
2
+ /*# sourceMappingURL=index.esm.css.map */
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["playerSeekbar.css","player-ui.css"],"names":[],"mappings":"AAAA,mBAME,eAAgB,CAGhB,iBAAkB,CALlB,WAAY,CAIZ,cAAe,CAHf,WAAY,CAHZ,QAAS,CAQT,QAAS,CATT,iBAAkB,CAElB,0BAA2B,CAQ3B,gBAAiB,CAJjB,SAAU,CAKV,UACF,CAEA,gBAGE,eAAgB,CAGhB,SACF,CAEA,kCAJE,iBAAkB,CAHlB,WAAY,CADZ,iBAAkB,CAGlB,OAaF,CARA,kBAGE,kBAAmB,CAInB,2BAA6B,CAD7B,SAEF,CAEA,eAME,eAAgB,CAEhB,wBAAyB,CADzB,iBAAkB,CAGlB,mCAAqC,CACrC,cAAe,CANf,WAAY,CAJZ,iBAAkB,CAClB,OAAQ,CACR,8BAAgC,CAShC,yBAA2B,CAR3B,UAAW,CAKX,SAIF,CACA,qBACE,kBACF,CAEA,iBAKE,eAAgB,CAGhB,iBAAkB,CANlB,WAAY,CAIZ,UAAW,CAGX,cAAe,CANf,MAAO,CAIP,eAAgB,CAIhB,mBAAoB,CAVpB,iBAAkB,CAGlB,0BAA2B,CAM3B,kBAAmB,CAEnB,UACF,CAEA,4CAIE,UAAW,CADX,cAAe,CAEf,gBAAiB,CAJjB,iBAAkB,CAClB,QAAS,CAIT,SACF,CCzEA,gBAEE,QAAS,CADT,2BAA6B,CAE7B,OAAQ,CACR,8BAAgC,CAChC,UACF","file":"index.esm.css","sourcesContent":[".seekbar-container {\n position: absolute;\n left: 50%;\n transform: translateX(-50%);\n bottom: 50px;\n height: 12px;\n background: #444;\n width: 90%;\n cursor: pointer;\n border-radius: 6px;\n margin: 0;\n user-select: none;\n z-index: 20;\n}\n\n.seekbar-buffer {\n position: absolute;\n height: 100%;\n background: #888;\n width: 0;\n border-radius: 6px;\n z-index: 1;\n}\n\n.seekbar-progress {\n position: absolute;\n height: 100%;\n background: #4169E1;\n width: 0;\n border-radius: 6px;\n z-index: 2;\n transition: width 0.1s linear;\n}\n\n.seekbar-thumb {\n position: absolute;\n top: 50%;\n transform: translate(-50%, -50%);\n width: 16px;\n height: 16px;\n background: #fff;\n border-radius: 50%;\n border: 2px solid #4169E1;\n z-index: 3;\n box-shadow: 0 2px 8px rgba(0,0,0,0.2);\n cursor: pointer;\n transition: background 0.2s;\n}\n.seekbar-thumb:hover {\n background: #ffeaea;\n}\n\n.seekbar-tooltip {\n position: absolute;\n bottom: 24px;\n left: 0;\n transform: translateX(-50%);\n background: #222;\n color: #fff;\n padding: 2px 8px;\n border-radius: 4px;\n font-size: 12px;\n white-space: nowrap;\n pointer-events: none;\n z-index: 10;\n}\n\n.seekbar-time-label, .seekbar-duration-label {\n position: relative;\n top: 18px;\n font-size: 13px;\n color: #eee;\n margin-right: 4px;\n z-index: 5;\n}\n","/* Center play/pause button absolutely in the middle of the player */\n.play-pause-btn {\n position: absolute !important;\n left: 50%;\n top: 50%;\n transform: translate(-50%, -50%);\n z-index: 30;\n} "]}
package/dist/index.esm.js CHANGED
@@ -1 +1 @@
1
- import"@viewlift/player-backup/esm/bundle.css";var t,e=function(t){return"lgTv"==t?"lg":"vizioTv"==t?"vizio":"xfinityX1"==t?"xfinityX1":"xbox"==t?"xBox":"samsung"};!function(t){t.LG="lgTv",t.Vizio="vizioTv",t.XfinityX1="xfinityX1",t.Xbox="xbox",t.Samsung="samsungTv"}(t||(t={}));var n=function(){function t(t){var e=this;this.listeners={},this.boundEmitters={},this.boundHandlerMap={},this.options=t,this.videoElement=document.createElement("video"),this.videoElement.id=t.playerId,this.videoElement.autoplay=!!t.autoplay,t.width&&(this.videoElement.width=t.width),t.height&&(this.videoElement.height=t.height),this.videoElement.style.display="block",this.videoElement.style.background="black";var n={play:this.onPlay,pause:this.onPause,ended:this.onEnded,timeupdate:this.onTimeupdate,error:this.onError,loadedmetadata:this.onLoadedmetadata,seeking:this.onSeeking,seeked:this.onSeeked,volumechange:this.onVolumechange};Object.keys(n).forEach(function(t){var i=n[t].bind(e);e.boundHandlerMap[t]=i,e.videoElement.addEventListener(t,i)})}return t.prototype.initialize=function(){return window.appMainConfig.apiBaseUrl,this.options.playerId,this.options.contentId,this.options.authToken,this.options.autoplay,this.options.profileId,this.options.deviceName,e(this.options.deviceName),window.appSettings.device,window.appMainConfig.internalName,!0},t.prototype.attachTo=function(t){t.appendChild(this.videoElement)},t.prototype.play=function(){this.videoElement.play()},t.prototype.pause=function(){this.videoElement.pause()},t.prototype.stop=function(){this.videoElement.pause(),this.videoElement.currentTime=0},t.prototype.destroy=function(){var t=this;this.videoElement.parentNode&&this.videoElement.parentNode.removeChild(this.videoElement),this.removeAllListeners(),Object.keys(this.boundHandlerMap).forEach(function(e){t.boundHandlerMap[e]&&(t.videoElement.removeEventListener(e,t.boundHandlerMap[e]),delete t.boundHandlerMap[e])})},Object.defineProperty(t.prototype,"element",{get:function(){return this.videoElement},enumerable:!1,configurable:!0}),t.prototype.onPlay=function(t){"function"==typeof this.options.onPlaybackSuccess&&this.options.onPlaybackSuccess()},t.prototype.onPause=function(t){},t.prototype.onEnded=function(t){"function"==typeof this.options.onPlaybackEnded&&this.options.onPlaybackEnded()},t.prototype.onTimeupdate=function(t){},t.prototype.onError=function(t){"function"==typeof this.options.onPlaybackError&&this.options.onPlaybackError(t)},t.prototype.onLoadedmetadata=function(t){},t.prototype.onSeeking=function(t){},t.prototype.onSeeked=function(t){},t.prototype.onVolumechange=function(t){},t.prototype.on=function(t,e){this.listeners[t]||(this.listeners[t]=[],this.boundEmitters[t]||(this.boundEmitters[t]=this.emitEvent(t),this.videoElement.addEventListener(t,this.boundEmitters[t]))),this.listeners[t].push(e)},t.prototype.off=function(t,e){this.listeners[t]&&(this.listeners[t]=this.listeners[t].filter(function(t){return t!==e}),0===this.listeners[t].length&&(this.boundEmitters[t]&&(this.videoElement.removeEventListener(t,this.boundEmitters[t]),delete this.boundEmitters[t]),delete this.listeners[t]))},t.prototype.once=function(t,e){var n=this,i=function(){for(var o=[],s=0;s<arguments.length;s++)o[s]=arguments[s];e.apply(void 0,o),n.off(t,i)};this.on(t,i)},t.prototype.emitEvent=function(t){var e=this;return function(n){e.listeners[t]&&e.listeners[t].forEach(function(t){return t(n)})}},t.prototype.removeAllListeners=function(){var t=this;Object.keys(this.listeners).forEach(function(e){t.boundEmitters[e]&&(t.videoElement.removeEventListener(e,t.boundEmitters[e]),delete t.boundEmitters[e])}),this.listeners={}},t}();export{n as LightningVideoPlayer};
1
+ var t=function(){return t=Object.assign||function(t){for(var e,n=1,i=arguments.length;n<i;n++)for(var o in e=arguments[n])Object.prototype.hasOwnProperty.call(e,o)&&(t[o]=e[o]);return t},t.apply(this,arguments)};"function"==typeof SuppressedError&&SuppressedError;var e=function(){function t(t){if(this.imgSrc=t.imgSrc||"",this.imgAltText=t.imgAltText||"",this.buttonText=t.buttonText||"",this.klassname=t.klassname||"default-button",this.width=t.width||100,this.height=t.height||50,this.focused=t.focused||!1,this.disabled=t.disabled||!1,this.handleClick=t.handleClick||function(){},"function"!=typeof t.handleClick)throw new Error("Button Class: handleClick must be a function");this.disabled&&(this.klassname+=" disabled"),this.focused&&(this.klassname+=" focused"),this.handleClick=this.handleClick.bind(this)}return t.prototype.mount=function(t){var e=this,n=document.createElement("button");if(n.className=this.klassname,n.style.width="".concat(this.width,"px"),n.style.height="".concat(this.height,"px"),n.disabled=this.disabled,n.tabIndex=0,this.imgSrc){var i=document.createElement("img");i.src=this.imgSrc,i.alt=this.imgAltText,n.appendChild(i)}else{var o=document.createElement("span");o.textContent=this.buttonText,n.appendChild(o)}n.addEventListener("click",this.handleClick),n.addEventListener("focus",function(){e.focused=!0,n.classList.add("focused")}),n.addEventListener("blur",function(){e.focused=!1,n.classList.remove("focused")}),this.buttonElement=n,t.appendChild(n)},t.prototype.unmount=function(){this.buttonElement&&(this.buttonElement.removeEventListener("click",this.handleClick),this.buttonElement.removeEventListener("focus",this.handleClick),this.buttonElement.removeEventListener("blur",this.handleClick),this.buttonElement=void 0)},t.prototype.focus=function(){this.buttonElement&&(this.buttonElement.focus(),this.buttonElement.classList.add("focused"),this.focused=!0)},t.prototype.blur=function(){this.buttonElement&&(this.buttonElement.blur(),this.buttonElement.classList.remove("focused"),this.focused=!1)},t}(),n=function(){function t(t){var e=this;this.isDragging=!1,this.focused=!1,this.video=t,this.container=document.createElement("div"),this.container.className="seekbar-container",this.container.tabIndex=0,this.buffer=document.createElement("div"),this.buffer.className="seekbar-buffer",this.progress=document.createElement("div"),this.progress.className="seekbar-progress",this.thumb=document.createElement("div"),this.thumb.className="seekbar-thumb",this.tooltip=document.createElement("div"),this.tooltip.className="seekbar-tooltip",this.tooltip.style.display="none",this.timeLabel=document.createElement("span"),this.timeLabel.className="seekbar-time-label",this.durationLabel=document.createElement("span"),this.durationLabel.className="seekbar-duration-label",this.container.appendChild(this.buffer),this.container.appendChild(this.progress),this.container.appendChild(this.thumb),this.container.appendChild(this.tooltip),this.container.appendChild(this.timeLabel),this.container.appendChild(this.durationLabel),this.video.addEventListener("timeupdate",function(){return e.update()}),this.video.addEventListener("progress",function(){return e.updateBuffer()}),this.video.addEventListener("durationchange",function(){return e.update()}),this.container.addEventListener("click",function(t){return e.seek(t)}),this.thumb.addEventListener("mousedown",function(t){return e.startDrag(t)}),this.container.addEventListener("mousemove",function(t){return e.showTooltip(t)}),this.container.addEventListener("mouseleave",function(){return e.hideTooltip()}),this.container.addEventListener("focus",function(){e.focused=!0,e.container.classList.add("focused")}),this.container.addEventListener("blur",function(){e.focused=!1,e.container.classList.remove("focused")})}return t.prototype.focus=function(){this.container.focus(),this.container.classList.add("focused"),this.focused=!0},t.prototype.blur=function(){this.container.blur(),this.container.classList.remove("focused"),this.focused=!1},t.prototype.formatTime=function(t){if(isNaN(t))return"0:00";var e=Math.floor(t/60),n=Math.floor(t%60);return"".concat(e,":").concat(String(n).padStart(2,"0"))},t.prototype.update=function(){var t=this.video.currentTime/this.video.duration*100;this.progress.style.width=t+"%",this.thumb.style.left=t+"%",this.timeLabel.textContent=this.formatTime(this.video.currentTime),this.durationLabel.textContent=" / "+this.formatTime(this.video.duration)},t.prototype.updateBuffer=function(){if(this.video.buffered.length){var t=this.video.buffered.end(this.video.buffered.length-1)/this.video.duration*100;this.buffer.style.width=t+"%"}},t.prototype.seek=function(t){if(!this.isDragging){var e=this.container.getBoundingClientRect(),n=(t.clientX-e.left)/e.width;this.video.currentTime=n*this.video.duration}},t.prototype.startDrag=function(t){var e=this;t.preventDefault(),this.isDragging=!0;var n=function(t){var n=e.container.getBoundingClientRect(),i=(t.clientX-n.left)/n.width;i=Math.max(0,Math.min(1,i)),e.progress.style.width=100*i+"%",e.thumb.style.left=100*i+"%",e.timeLabel.textContent=e.formatTime(i*e.video.duration)},i=function(t){var o=e.container.getBoundingClientRect(),s=(t.clientX-o.left)/o.width;s=Math.max(0,Math.min(1,s)),e.video.currentTime=s*e.video.duration,e.isDragging=!1,document.removeEventListener("mousemove",n),document.removeEventListener("mouseup",i)};document.addEventListener("mousemove",n),document.addEventListener("mouseup",i)},t.prototype.showTooltip=function(t){var e=this.container.getBoundingClientRect(),n=(t.clientX-e.left)/e.width,i=n*this.video.duration;this.tooltip.textContent=this.formatTime(i),this.tooltip.style.display="block",this.tooltip.style.left="".concat(100*n,"%")},t.prototype.hideTooltip=function(){this.tooltip.style.display="none"},t.prototype.mount=function(t){t.appendChild(this.container),this.update(),this.updateBuffer()},t.prototype.getElement=function(){return this.container},t}(),i=function(){function t(t){var e=t.player;this.player=e,this.container=document.createElement("div"),this.container.className="video-player-ui",this.createControls()}return t.prototype.createControls=function(){var t,i,o,s=this;this.playPauseBtn=new e({imgSrc:"",imgAltText:"Play/Pause",buttonText:"Play",width:80,height:40,klassname:"play-pause-btn",focused:!1,disabled:!1,handleClick:function(){s.player.video.paused?(s.player.play(),s.playPauseBtn&&s.playPauseBtn.buttonElement&&(s.playPauseBtn.buttonElement.textContent="Pause")):(s.player.pause(),s.playPauseBtn&&s.playPauseBtn.buttonElement&&(s.playPauseBtn.buttonElement.textContent="Play"))}}),this.playPauseBtn.mount(this.container),this.container.appendChild(this.player.video),this.seekbar=new n(this.player.video),this.seekbar.mount(this.container),(null===(t=this.playPauseBtn)||void 0===t?void 0:t.buttonElement)&&this.seekbar&&(this.playPauseBtn.buttonElement.addEventListener("keydown",function(t){var e;"ArrowDown"===t.key&&(t.preventDefault(),null===(e=s.seekbar)||void 0===e||e.focus())}),null===(o=null===(i=this.seekbar)||void 0===i?void 0:i.getElement())||void 0===o||o.addEventListener("keydown",function(t){var e;"ArrowUp"===t.key&&(t.preventDefault(),null===(e=s.playPauseBtn)||void 0===e||e.focus())}))},t.prototype.attachTo=function(t){t.appendChild(this.container)},t.prototype.getElement=function(){return this.container},t}();function o(e,n){var o=document.createElement("video");o.controls=!1,o.style.width="100%",o.style.height="100%";var s=null;if(window.Hls&&window.Hls.isSupported())(s=new window.Hls).loadSource(n),s.attachMedia(o),s.on(window.Hls.Events.MANIFEST_PARSED,function(){o.play()});else{if(!o.canPlayType("application/vnd.apple.mpegurl"))throw new Error("HLS is not supported in this browser.");o.src=n,o.addEventListener("loadedmetadata",function(){o.play()})}var a={video:o,play:function(){return o.play()},pause:function(){return o.pause()}},r=new i({player:a});return r.attachTo(e),t(t({},a),{ui:r})}export{o as createHlsPlayer};
@@ -0,0 +1,19 @@
1
+ interface VideoPlayerUIOptions {
2
+ player: {
3
+ video: HTMLVideoElement;
4
+ play: () => void;
5
+ pause: () => void;
6
+ };
7
+ width?: string;
8
+ height?: string;
9
+ }
10
+ declare class VideoPlayerUI {
11
+ private player;
12
+ private container;
13
+ private playPauseBtn?;
14
+ private seekbar?;
15
+ constructor({ player, width, height }: VideoPlayerUIOptions);
16
+ private createControls;
17
+ attachTo(parent: HTMLElement): void;
18
+ }
19
+ export default VideoPlayerUI;
@@ -0,0 +1,38 @@
1
+ import './playerButtons.css';
2
+ type EventHandler = (event?: any) => void;
3
+ type ButtonProps = {
4
+ imgSrc: string;
5
+ imgAltText: string;
6
+ width: number;
7
+ height: number;
8
+ klassname: string;
9
+ buttonText: string;
10
+ focused: boolean;
11
+ disabled: boolean;
12
+ handleClick: EventHandler;
13
+ };
14
+ export declare class Button {
15
+ private imgSrc;
16
+ private imgAltText;
17
+ private klassname;
18
+ private width;
19
+ private height;
20
+ private focused;
21
+ private disabled;
22
+ private handleClick;
23
+ private buttonText;
24
+ buttonElement?: HTMLButtonElement;
25
+ constructor(props: ButtonProps);
26
+ /**
27
+ * Mounts the button to the specified mount point
28
+ * @param mountPoint The HTML element to which the button will be appended
29
+ */
30
+ mount(mountPoint: HTMLElement): void;
31
+ /**
32
+ * Removes the click event listener from the button
33
+ */
34
+ unmount(): void;
35
+ focus(): void;
36
+ blur(): void;
37
+ }
38
+ export {};
@@ -0,0 +1,25 @@
1
+ import './playerSeekbar.css';
2
+ export declare class PlayerSeekbar {
3
+ private container;
4
+ private progress;
5
+ private buffer;
6
+ private thumb;
7
+ private tooltip;
8
+ private video;
9
+ private timeLabel;
10
+ private durationLabel;
11
+ private isDragging;
12
+ private focused;
13
+ constructor(video: HTMLVideoElement);
14
+ focus(): void;
15
+ blur(): void;
16
+ private formatTime;
17
+ private update;
18
+ private updateBuffer;
19
+ private seek;
20
+ private startDrag;
21
+ private showTooltip;
22
+ private hideTooltip;
23
+ mount(parent: HTMLElement): void;
24
+ getElement(): HTMLDivElement;
25
+ }
@@ -0,0 +1,18 @@
1
+ import './player-ui.css';
2
+ declare class VideoPlayerUI {
3
+ private player;
4
+ private container;
5
+ private playPauseBtn?;
6
+ private seekbar?;
7
+ constructor({ player }: {
8
+ player: {
9
+ video: HTMLVideoElement;
10
+ play: () => void;
11
+ pause: () => void;
12
+ };
13
+ });
14
+ private createControls;
15
+ attachTo(parent: HTMLElement): void;
16
+ getElement(): HTMLDivElement;
17
+ }
18
+ export default VideoPlayerUI;
@@ -0,0 +1,13 @@
1
+ import VideoPlayerUI from './player-ui/player-ui';
2
+ declare global {
3
+ interface Window {
4
+ Hls: any;
5
+ }
6
+ }
7
+ export interface PlayerInstance {
8
+ video: HTMLVideoElement;
9
+ play: () => void;
10
+ pause: () => void;
11
+ ui: VideoPlayerUI;
12
+ }
13
+ export declare function createHlsPlayer(mountPoint: HTMLElement, streamUrl: string): PlayerInstance;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@viewlift/player-backup",
3
- "version": "1.0.0-lighteningjs",
3
+ "version": "1.0.1-lighteningjs",
4
4
  "description": "A LightningJS video player component for Smart TV apps.",
5
5
  "main": "dist/index.cjs.js",
6
6
  "module": "dist/index.esm.js",
@@ -27,6 +27,7 @@
27
27
  "@rollup/plugin-typescript": "^11.1.6",
28
28
  "rollup": "^4.16.4",
29
29
  "tslib": "^2.6.2",
30
- "typescript": "^5.4.5"
30
+ "typescript": "^5.4.5",
31
+ "rollup-plugin-postcss": "^4.0.2"
31
32
  }
32
33
  }
package/rollup.config.mjs CHANGED
@@ -3,9 +3,10 @@ import commonjs from '@rollup/plugin-commonjs';
3
3
  import terser from '@rollup/plugin-terser';
4
4
  import typescript from '@rollup/plugin-typescript';
5
5
  import babel from '@rollup/plugin-babel';
6
+ import postcss from 'rollup-plugin-postcss';
6
7
 
7
8
  export default {
8
- input: 'src/index.ts',
9
+ input: 'src/playerInitializer.ts',
9
10
  output: [
10
11
  {
11
12
  file: 'dist/index.cjs.js',
@@ -26,6 +27,11 @@ export default {
26
27
  extensions: ['.js', '.ts'],
27
28
  exclude: 'node_modules/**',
28
29
  }),
30
+ postcss({
31
+ extract: true, // creates a separate CSS file
32
+ minimize: true,
33
+ sourceMap: true,
34
+ }),
29
35
  terser(),
30
36
  ],
31
37
  };
package/src/index.ts CHANGED
@@ -1,33 +1,18 @@
1
1
  // LightningJS-compatible Video Player Component (ES5 compatible)
2
2
 
3
- import '@viewlift/player-backup/esm/bundle.css'
4
- import { getDeviceFullName, getDeviceShortName,getMacros } from './utility';
5
3
  export interface VideoPlayerOptions {
6
4
  // Optional playback callbacks
7
5
  onPlaybackSuccess?: () => void;
8
6
  onPlaybackEnded?: () => void;
9
7
  onPlaybackError?: (error?: any) => void;
10
- playerId: string;
11
- contentId: string;
12
- profileId: string;
13
- deviceId:string;
14
- authToken: string
8
+ src: string;
15
9
  autoplay?: boolean;
16
10
  controls?: boolean;
17
11
  width?: number;
18
-
19
12
  height?: number;
20
- deviceName: DeviceType
21
13
  // Event callbacks
22
14
  }
23
15
 
24
- enum DeviceType {
25
- LG = 'lgTv',
26
- Vizio = 'vizioTv',
27
- XfinityX1 = 'xfinityX1',
28
- Xbox = 'xbox',
29
- Samsung = 'samsungTv'
30
- }
31
16
  type EventHandler = (...args: any[]) => void;
32
17
 
33
18
  type VideoPlayerEvent =
@@ -45,7 +30,39 @@ export class LightningVideoPlayer {
45
30
  /**
46
31
  * Reinitialize the current videoElement with a new set of options and handle autoplay.
47
32
  */
48
-
33
+ reinitialize(options: VideoPlayerOptions) {
34
+ this.options = options;
35
+ this.videoElement.src = options.src;
36
+ this.videoElement.autoplay = !!options.autoplay;
37
+ this.videoElement.controls = !!options.controls;
38
+ if (options.width) {
39
+ this.videoElement.width = options.width;
40
+ } else {
41
+ this.videoElement.removeAttribute('width');
42
+ }
43
+ if (options.height) {
44
+ this.videoElement.height = options.height;
45
+ } else {
46
+ this.videoElement.removeAttribute('height');
47
+ }
48
+ // Reset playback state
49
+ this.videoElement.currentTime = 0;
50
+ this.videoElement.pause();
51
+ // If autoplay is set, start playback
52
+ if (options.autoplay) {
53
+ // Wait for metadata to be loaded before playing (for some browsers)
54
+ const playOnLoaded = () => {
55
+ this.videoElement.play();
56
+ this.videoElement.removeEventListener('loadedmetadata', playOnLoaded);
57
+ };
58
+ this.videoElement.addEventListener('loadedmetadata', playOnLoaded);
59
+ // If already loaded, play immediately
60
+ if (this.videoElement.readyState >= 1) {
61
+ this.videoElement.play();
62
+ this.videoElement.removeEventListener('loadedmetadata', playOnLoaded);
63
+ }
64
+ }
65
+ }
49
66
  private videoElement: HTMLVideoElement;
50
67
  private options: VideoPlayerOptions;
51
68
  private listeners: { [event: string]: EventHandler[] } = {};
@@ -55,8 +72,9 @@ export class LightningVideoPlayer {
55
72
  constructor(options: VideoPlayerOptions) {
56
73
  this.options = options;
57
74
  this.videoElement = document.createElement('video');
58
- this.videoElement.id = options.playerId;
75
+ this.videoElement.src = options.src;
59
76
  this.videoElement.autoplay = !!options.autoplay;
77
+ this.videoElement.controls = !!options.controls;
60
78
  if (options.width) this.videoElement.width = options.width;
61
79
  if (options.height) this.videoElement.height = options.height;
62
80
  this.videoElement.style.display = 'block';
@@ -81,43 +99,6 @@ export class LightningVideoPlayer {
81
99
  });
82
100
  }
83
101
 
84
- initialize() {
85
- let configurationObject = {
86
- apiBaseUrl: (window as any).appMainConfig.apiBaseUrl,
87
- playerId: this.options.playerId,
88
- videoId: this.options.contentId,
89
- token: this.options.authToken,
90
- disableControls: true,
91
- autoplay:this.options.autoplay,
92
- watchHistory:{
93
- enable:false,
94
- interval:30,
95
- profileId:this.options.profileId,
96
- apiVersion:'v2'
97
- },
98
- customData: {
99
- entitlement: {
100
- deviceType: getDeviceFullName(this.options.deviceName),
101
- contentConsumption: getDeviceShortName(this.options.deviceName),
102
- // hba_status: localStorage?.getItem("hba_status")?JSON.stringify(localStorage?.getItem("hba_status")):false,
103
- // householdID: localStorage?.getItem(window?.appMainConfig?.internalName + "_householdID"),
104
- },
105
- beacon: {
106
- params: {
107
- pfm: (window as any).appSettings.device
108
- },
109
- url: (window as any).appMainConfig.internalName,
110
- },
111
- // macros:getMacros(videoPlayBackObject,1920,1080,this.options.deviceName,this.options.deviceId),
112
- overrideNative:true,
113
- nativeAudioTracks:false,
114
- nativeVideoTracks:false,
115
- onlyPlayReadyDRM:true,
116
- }
117
- };
118
- return true
119
- }
120
-
121
102
  attachTo(container: HTMLElement) {
122
103
  container.appendChild(this.videoElement);
123
104
  }
@@ -0,0 +1,65 @@
1
+ import { Button } from '../player-components/player-buttons/playerButtons';
2
+ import { PlayerSeekbar } from '../player-components/player-seekbar/playerSeekbar';
3
+
4
+ interface VideoPlayerUIOptions {
5
+ player: { video: HTMLVideoElement; play: () => void; pause: () => void };
6
+ width?: string;
7
+ height?: string;
8
+ }
9
+
10
+ class VideoPlayerUI {
11
+ private player: { video: HTMLVideoElement; play: () => void; pause: () => void };
12
+ private container: HTMLDivElement;
13
+ private playPauseBtn?: Button;
14
+ private seekbar?: PlayerSeekbar;
15
+
16
+ constructor({ player, width = '1280px', height = '720px' }: VideoPlayerUIOptions) {
17
+ this.player = player;
18
+ this.container = document.createElement('div');
19
+ this.container.className = 'video-player-ui';
20
+ if (width) this.container.style.width = width;
21
+ if (height) this.container.style.height = height;
22
+ this.createControls(width, height);
23
+ }
24
+
25
+ private createControls(width?: string, height?: string) {
26
+ // Play/Pause button using Button class
27
+ this.playPauseBtn = new Button({
28
+ imgSrc: '', // Optionally provide an image
29
+ imgAltText: 'Play/Pause',
30
+ buttonText: 'Play',
31
+ width: 80,
32
+ height: 40,
33
+ klassname: 'play-pause-btn',
34
+ focused: false,
35
+ disabled: false,
36
+ handleClick: () => {
37
+ if (this.player.video.paused) {
38
+ this.player.play();
39
+ if (this.playPauseBtn && this.playPauseBtn.buttonElement) {
40
+ this.playPauseBtn.buttonElement.textContent = 'Pause';
41
+ }
42
+ } else {
43
+ this.player.pause();
44
+ if (this.playPauseBtn && this.playPauseBtn.buttonElement) {
45
+ this.playPauseBtn.buttonElement.textContent = 'Play';
46
+ }
47
+ }
48
+ }
49
+ });
50
+ this.playPauseBtn.mount(this.container);
51
+ // Attach the video element
52
+ if (width) this.player.video.style.width = width;
53
+ if (height) this.player.video.style.height = height;
54
+ this.container.appendChild(this.player.video);
55
+ // Add the seekbar below the video
56
+ this.seekbar = new PlayerSeekbar(this.player.video);
57
+ this.seekbar.mount(this.container);
58
+ }
59
+
60
+ attachTo(parent: HTMLElement) {
61
+ parent.appendChild(this.container);
62
+ }
63
+ }
64
+
65
+ export default VideoPlayerUI;
@@ -0,0 +1,127 @@
1
+ import './playerButtons.css';
2
+
3
+ type EventHandler = (event?: any) => void;
4
+
5
+ type ButtonProps = {
6
+ imgSrc: string;
7
+ imgAltText: string;
8
+ width: number;
9
+ height: number;
10
+ klassname: string;
11
+ buttonText: string;
12
+ focused: boolean;
13
+ disabled: boolean;
14
+ handleClick: EventHandler
15
+ };
16
+
17
+ export class Button {
18
+
19
+ private imgSrc: string;
20
+ private imgAltText: string;
21
+ private klassname: string;
22
+ private width: number;
23
+ private height: number;
24
+ private focused: boolean;
25
+ private disabled: boolean;
26
+ private handleClick: EventHandler;
27
+ private buttonText: string;
28
+ public buttonElement?: HTMLButtonElement;
29
+
30
+
31
+
32
+ constructor(props: ButtonProps) {
33
+ this.imgSrc = props.imgSrc || '';
34
+ this.imgAltText = props.imgAltText || '';
35
+ this.buttonText = props.buttonText || '';
36
+ this.klassname = props.klassname || 'default-button';
37
+ this.width = props.width || 100;
38
+ this.height = props.height || 50;
39
+ this.focused = props.focused || false;
40
+ this.disabled = props.disabled || false;
41
+ this.handleClick = props.handleClick || (() => {});
42
+
43
+ if (typeof props.handleClick !== 'function') {
44
+ throw new Error('Button Class: handleClick must be a function');
45
+ }
46
+
47
+ if (this.disabled) {
48
+ this.klassname += ' disabled';
49
+ }
50
+
51
+ if (this.focused) {
52
+ this.klassname += ' focused';
53
+ }
54
+
55
+ this.handleClick = this.handleClick.bind(this);
56
+ }
57
+
58
+ /**
59
+ * Mounts the button to the specified mount point
60
+ * @param mountPoint The HTML element to which the button will be appended
61
+ */
62
+ mount(mountPoint: HTMLElement) {
63
+ // Create the button element
64
+ const button = document.createElement('button');
65
+ button.className = this.klassname;
66
+ button.style.width = `${this.width}px`;
67
+ button.style.height = `${this.height}px`;
68
+ button.disabled = this.disabled;
69
+ button.tabIndex = 0;
70
+
71
+ // Add image or text
72
+ if (this.imgSrc) {
73
+ const img = document.createElement('img');
74
+ img.src = this.imgSrc;
75
+ img.alt = this.imgAltText;
76
+ button.appendChild(img);
77
+ } else {
78
+ const span = document.createElement('span');
79
+ span.textContent = this.buttonText;
80
+ button.appendChild(span);
81
+ }
82
+
83
+ // Attach event listeners
84
+ button.addEventListener('click', this.handleClick);
85
+ button.addEventListener('focus', () => {
86
+ this.focused = true;
87
+ button.classList.add('focused');
88
+ });
89
+ button.addEventListener('blur', () => {
90
+ this.focused = false;
91
+ button.classList.remove('focused');
92
+ });
93
+
94
+ // Store reference and append
95
+ this.buttonElement = button;
96
+ mountPoint.appendChild(button);
97
+ }
98
+
99
+ /**
100
+ * Removes the click event listener from the button
101
+ */
102
+ unmount() {
103
+ if (this.buttonElement) {
104
+ this.buttonElement.removeEventListener('click', this.handleClick);
105
+ this.buttonElement.removeEventListener('focus', this.handleClick);
106
+ this.buttonElement.removeEventListener('blur', this.handleClick);
107
+ this.buttonElement = undefined;
108
+ }
109
+ }
110
+
111
+ focus() {
112
+ if (this.buttonElement) {
113
+ this.buttonElement.focus();
114
+ this.buttonElement.classList.add('focused');
115
+ this.focused = true;
116
+ }
117
+ }
118
+
119
+ blur() {
120
+ if (this.buttonElement) {
121
+ this.buttonElement.blur();
122
+ this.buttonElement.classList.remove('focused');
123
+ this.focused = false;
124
+ }
125
+ }
126
+
127
+ }
@@ -0,0 +1,75 @@
1
+ .seekbar-container {
2
+ position: absolute;
3
+ left: 50%;
4
+ transform: translateX(-50%);
5
+ bottom: 50px;
6
+ height: 12px;
7
+ background: #444;
8
+ width: 90%;
9
+ cursor: pointer;
10
+ border-radius: 6px;
11
+ margin: 0;
12
+ user-select: none;
13
+ z-index: 20;
14
+ }
15
+
16
+ .seekbar-buffer {
17
+ position: absolute;
18
+ height: 100%;
19
+ background: #888;
20
+ width: 0;
21
+ border-radius: 6px;
22
+ z-index: 1;
23
+ }
24
+
25
+ .seekbar-progress {
26
+ position: absolute;
27
+ height: 100%;
28
+ background: #4169E1;
29
+ width: 0;
30
+ border-radius: 6px;
31
+ z-index: 2;
32
+ transition: width 0.1s linear;
33
+ }
34
+
35
+ .seekbar-thumb {
36
+ position: absolute;
37
+ top: 50%;
38
+ transform: translate(-50%, -50%);
39
+ width: 16px;
40
+ height: 16px;
41
+ background: #fff;
42
+ border-radius: 50%;
43
+ border: 2px solid #4169E1;
44
+ z-index: 3;
45
+ box-shadow: 0 2px 8px rgba(0,0,0,0.2);
46
+ cursor: pointer;
47
+ transition: background 0.2s;
48
+ }
49
+ .seekbar-thumb:hover {
50
+ background: #ffeaea;
51
+ }
52
+
53
+ .seekbar-tooltip {
54
+ position: absolute;
55
+ bottom: 24px;
56
+ left: 0;
57
+ transform: translateX(-50%);
58
+ background: #222;
59
+ color: #fff;
60
+ padding: 2px 8px;
61
+ border-radius: 4px;
62
+ font-size: 12px;
63
+ white-space: nowrap;
64
+ pointer-events: none;
65
+ z-index: 10;
66
+ }
67
+
68
+ .seekbar-time-label, .seekbar-duration-label {
69
+ position: relative;
70
+ top: 18px;
71
+ font-size: 13px;
72
+ color: #eee;
73
+ margin-right: 4px;
74
+ z-index: 5;
75
+ }
@@ -0,0 +1,158 @@
1
+ import './playerSeekbar.css';
2
+
3
+ export class PlayerSeekbar {
4
+ private container: HTMLDivElement;
5
+ private progress: HTMLDivElement;
6
+ private buffer: HTMLDivElement;
7
+ private thumb: HTMLDivElement;
8
+ private tooltip: HTMLDivElement;
9
+ private video: HTMLVideoElement;
10
+ private timeLabel: HTMLSpanElement;
11
+ private durationLabel: HTMLSpanElement;
12
+ private isDragging: boolean = false;
13
+ private focused: boolean = false;
14
+
15
+ constructor(video: HTMLVideoElement) {
16
+ this.video = video;
17
+ this.container = document.createElement('div');
18
+ this.container.className = 'seekbar-container';
19
+ this.container.tabIndex = 0; // Make focusable
20
+
21
+ this.buffer = document.createElement('div');
22
+ this.buffer.className = 'seekbar-buffer';
23
+
24
+ this.progress = document.createElement('div');
25
+ this.progress.className = 'seekbar-progress';
26
+
27
+ this.thumb = document.createElement('div');
28
+ this.thumb.className = 'seekbar-thumb';
29
+
30
+ this.tooltip = document.createElement('div');
31
+ this.tooltip.className = 'seekbar-tooltip';
32
+ this.tooltip.style.display = 'none';
33
+
34
+ this.timeLabel = document.createElement('span');
35
+ this.timeLabel.className = 'seekbar-time-label';
36
+ this.durationLabel = document.createElement('span');
37
+ this.durationLabel.className = 'seekbar-duration-label';
38
+
39
+ this.container.appendChild(this.buffer);
40
+ this.container.appendChild(this.progress);
41
+ this.container.appendChild(this.thumb);
42
+ this.container.appendChild(this.tooltip);
43
+ this.container.appendChild(this.timeLabel);
44
+ this.container.appendChild(this.durationLabel);
45
+
46
+ // Update UI as video plays
47
+ this.video.addEventListener('timeupdate', () => this.update());
48
+ this.video.addEventListener('progress', () => this.updateBuffer());
49
+ this.video.addEventListener('durationchange', () => this.update());
50
+
51
+ // Seek on click
52
+ this.container.addEventListener('click', (e) => this.seek(e));
53
+ // Dragging
54
+ this.thumb.addEventListener('mousedown', (e) => this.startDrag(e));
55
+ // Tooltip on hover
56
+ this.container.addEventListener('mousemove', (e) => this.showTooltip(e));
57
+ this.container.addEventListener('mouseleave', () => this.hideTooltip());
58
+
59
+ // Focus/blur events for accessibility and visual feedback
60
+ this.container.addEventListener('focus', () => {
61
+ this.focused = true;
62
+ this.container.classList.add('focused');
63
+ });
64
+ this.container.addEventListener('blur', () => {
65
+ this.focused = false;
66
+ this.container.classList.remove('focused');
67
+ });
68
+ }
69
+
70
+ public focus() {
71
+ this.container.focus();
72
+ this.container.classList.add('focused');
73
+ this.focused = true;
74
+ }
75
+
76
+ public blur() {
77
+ this.container.blur();
78
+ this.container.classList.remove('focused');
79
+ this.focused = false;
80
+ }
81
+
82
+ private formatTime(seconds: number): string {
83
+ if (isNaN(seconds)) return '0:00';
84
+ const m = Math.floor(seconds / 60);
85
+ const s = Math.floor(seconds % 60);
86
+ return `${m}:${String(s).padStart(2, '0')}`;
87
+ }
88
+
89
+ private update() {
90
+ const percent = (this.video.currentTime / this.video.duration) * 100;
91
+ this.progress.style.width = percent + '%';
92
+ this.thumb.style.left = percent + '%';
93
+ this.timeLabel.textContent = this.formatTime(this.video.currentTime);
94
+ this.durationLabel.textContent = ' / ' + this.formatTime(this.video.duration);
95
+ }
96
+
97
+ private updateBuffer() {
98
+ if (this.video.buffered.length) {
99
+ const end = this.video.buffered.end(this.video.buffered.length - 1);
100
+ const percent = (end / this.video.duration) * 100;
101
+ this.buffer.style.width = percent + '%';
102
+ }
103
+ }
104
+
105
+ private seek(e: MouseEvent) {
106
+ if (this.isDragging) return;
107
+ const rect = this.container.getBoundingClientRect();
108
+ const percent = (e.clientX - rect.left) / rect.width;
109
+ this.video.currentTime = percent * this.video.duration;
110
+ }
111
+
112
+ private startDrag(e: MouseEvent) {
113
+ e.preventDefault();
114
+ this.isDragging = true;
115
+ const onMove = (moveEvent: MouseEvent) => {
116
+ const rect = this.container.getBoundingClientRect();
117
+ let percent = (moveEvent.clientX - rect.left) / rect.width;
118
+ percent = Math.max(0, Math.min(1, percent));
119
+ this.progress.style.width = percent * 100 + '%';
120
+ this.thumb.style.left = percent * 100 + '%';
121
+ this.timeLabel.textContent = this.formatTime(percent * this.video.duration);
122
+ };
123
+ const onUp = (upEvent: MouseEvent) => {
124
+ const rect = this.container.getBoundingClientRect();
125
+ let percent = (upEvent.clientX - rect.left) / rect.width;
126
+ percent = Math.max(0, Math.min(1, percent));
127
+ this.video.currentTime = percent * this.video.duration;
128
+ this.isDragging = false;
129
+ document.removeEventListener('mousemove', onMove);
130
+ document.removeEventListener('mouseup', onUp);
131
+ };
132
+ document.addEventListener('mousemove', onMove);
133
+ document.addEventListener('mouseup', onUp);
134
+ }
135
+
136
+ private showTooltip(e: MouseEvent) {
137
+ const rect = this.container.getBoundingClientRect();
138
+ const percent = (e.clientX - rect.left) / rect.width;
139
+ const time = percent * this.video.duration;
140
+ this.tooltip.textContent = this.formatTime(time);
141
+ this.tooltip.style.display = 'block';
142
+ this.tooltip.style.left = `${percent * 100}%`;
143
+ }
144
+
145
+ private hideTooltip() {
146
+ this.tooltip.style.display = 'none';
147
+ }
148
+
149
+ public mount(parent: HTMLElement) {
150
+ parent.appendChild(this.container);
151
+ this.update();
152
+ this.updateBuffer();
153
+ }
154
+
155
+ public getElement() {
156
+ return this.container;
157
+ }
158
+ }
@@ -0,0 +1,8 @@
1
+ /* Center play/pause button absolutely in the middle of the player */
2
+ .play-pause-btn {
3
+ position: absolute !important;
4
+ left: 50%;
5
+ top: 50%;
6
+ transform: translate(-50%, -50%);
7
+ z-index: 30;
8
+ }
@@ -0,0 +1,79 @@
1
+ import { Button } from '../player-components/player-buttons/playerButtons';
2
+ import { PlayerSeekbar } from '../player-components/player-seekbar/playerSeekbar';
3
+ import './player-ui.css';
4
+
5
+
6
+ class VideoPlayerUI {
7
+ private player: { video: HTMLVideoElement; play: () => void; pause: () => void };
8
+ private container: HTMLDivElement;
9
+ private playPauseBtn?: Button;
10
+ private seekbar?: PlayerSeekbar;
11
+
12
+ constructor({ player }: { player: { video: HTMLVideoElement; play: () => void; pause: () => void } }) {
13
+ this.player = player;
14
+ this.container = document.createElement('div');
15
+ this.container.className = 'video-player-ui';
16
+ this.createControls();
17
+ }
18
+
19
+ private createControls() {
20
+
21
+ this.playPauseBtn = new Button({
22
+ imgSrc: '',
23
+ imgAltText: 'Play/Pause',
24
+ buttonText: 'Play',
25
+ width: 80,
26
+ height: 40,
27
+ klassname: 'play-pause-btn',
28
+ focused: false,
29
+ disabled: false,
30
+ handleClick: () => {
31
+ if (this.player.video.paused) {
32
+ this.player.play();
33
+ if (this.playPauseBtn && this.playPauseBtn.buttonElement) {
34
+ this.playPauseBtn.buttonElement.textContent = 'Pause';
35
+ }
36
+ } else {
37
+ this.player.pause();
38
+ if (this.playPauseBtn && this.playPauseBtn.buttonElement) {
39
+ this.playPauseBtn.buttonElement.textContent = 'Play';
40
+ }
41
+ }
42
+ }
43
+ });
44
+ this.playPauseBtn.mount(this.container);
45
+ // Attach the video element
46
+ this.container.appendChild(this.player.video);
47
+ // Add the seekbar below the video
48
+ this.seekbar = new PlayerSeekbar(this.player.video);
49
+ this.seekbar.mount(this.container);
50
+
51
+ if (this.playPauseBtn?.buttonElement && this.seekbar) {
52
+ // Down arrow from play button focuses seekbar
53
+ this.playPauseBtn.buttonElement.addEventListener('keydown', (e: KeyboardEvent) => {
54
+ if (e.key === 'ArrowDown') {
55
+ e.preventDefault();
56
+ this.seekbar?.focus();
57
+ }
58
+ });
59
+
60
+ // Up arrow from seekbar focuses play button
61
+ this.seekbar?.getElement()?.addEventListener('keydown', (e: KeyboardEvent) => {
62
+ if (e.key === 'ArrowUp') {
63
+ e.preventDefault();
64
+ this.playPauseBtn?.focus();
65
+ }
66
+ });
67
+ }
68
+ }
69
+
70
+ attachTo(parent: HTMLElement) {
71
+ parent.appendChild(this.container);
72
+ }
73
+
74
+ public getElement() {
75
+ return this.container;
76
+ }
77
+ }
78
+
79
+ export default VideoPlayerUI;
@@ -0,0 +1,54 @@
1
+ import VideoPlayerUI from './player-ui/player-ui';
2
+
3
+ // Declare Hls type for CDN usage
4
+ declare global {
5
+ interface Window {
6
+ Hls: any;
7
+ }
8
+ }
9
+
10
+ export interface PlayerInstance {
11
+ video: HTMLVideoElement;
12
+ play: () => void;
13
+ pause: () => void;
14
+ ui: VideoPlayerUI;
15
+ }
16
+
17
+ export function createHlsPlayer(
18
+ mountPoint: HTMLElement,
19
+ streamUrl: string
20
+ ): PlayerInstance {
21
+ const video = document.createElement('video');
22
+ video.controls = false;
23
+ video.style.width = '100%';
24
+ video.style.height = '100%';
25
+
26
+ let hls: any = null;
27
+
28
+ if (window.Hls && window.Hls.isSupported()) {
29
+ hls = new window.Hls();
30
+ hls.loadSource(streamUrl);
31
+ hls.attachMedia(video);
32
+ hls.on(window.Hls.Events.MANIFEST_PARSED, function () {
33
+ video.play();
34
+ });
35
+ } else if (video.canPlayType('application/vnd.apple.mpegurl')) {
36
+ video.src = streamUrl;
37
+ video.addEventListener('loadedmetadata', function () {
38
+ video.play();
39
+ });
40
+ } else {
41
+ throw new Error('HLS is not supported in this browser.');
42
+ }
43
+
44
+ const player = {
45
+ video,
46
+ play: () => video.play(),
47
+ pause: () => video.pause(),
48
+ };
49
+
50
+ const ui = new VideoPlayerUI({ player });
51
+ ui.attachTo(mountPoint);
52
+
53
+ return { ...player, ui };
54
+ }
package/tsconfig.json CHANGED
@@ -4,10 +4,11 @@
4
4
  "module": "ESNext",
5
5
  "declaration": true,
6
6
  "outDir": "dist",
7
- "strict": false,
7
+ "strict": true,
8
8
  "esModuleInterop": true,
9
9
  "moduleResolution": "node",
10
- "skipLibCheck": true
10
+ "skipLibCheck": true,
11
+ "lib": ["dom", "es2017"]
11
12
  },
12
13
  "include": ["src/**/*"]
13
14
  }
package/dist/utility.d.ts DELETED
@@ -1,6 +0,0 @@
1
- export declare const getDeviceMaker: (deviceName: string) => "LG" | "Vizio" | "xfinityX1" | "Microsoft" | "Samsung";
2
- export declare const getUserAgent: (deviceName: string) => "xfinityX1" | "SmartTV_LG_WebOS" | "SmartTV_Vizio_SmartCast" | "xboxOne" | "SmartTV_Samsung_Tizen";
3
- export declare const getOSName: (deviceName: string) => "xfinityX1" | "WebOS" | "SmartCast" | "Windows" | "Tizen";
4
- export declare const getDeviceShortName: (deviceName: string) => "xfinityX1" | "lg" | "vizio" | "xBox" | "samsung";
5
- export declare const getDeviceFullName: (deviceName: string) => "xfinityX1" | "vizioTv" | "smart_tv_lg" | "windows_xbox" | "smart_tv_samsung";
6
- export declare const getMacros: (width: any, height: any, deviceName: any, deviceId: any) => {};
package/src/utility.ts DELETED
@@ -1,109 +0,0 @@
1
- export const getDeviceMaker = (deviceName:string) => {
2
- if (deviceName == "lgTv") {
3
- return "LG";
4
- } else if (deviceName == "vizioTv") {
5
- return "Vizio";
6
- } else if(deviceName == "xfinityX1"){
7
- return "xfinityX1"
8
- }else if(deviceName == "xbox"){
9
- return "Microsoft"
10
- }else {
11
- return "Samsung";
12
- }
13
- }
14
-
15
-
16
- export const getUserAgent = (deviceName:string) => {
17
- if (deviceName == "lgTv") {
18
- return "SmartTV_LG_WebOS";
19
- } else if (deviceName == "vizioTv") {
20
- return "SmartTV_Vizio_SmartCast";
21
- } else if(deviceName == "xfinityX1"){
22
- return "xfinityX1"
23
- }else if(deviceName == "xbox"){
24
- return "xboxOne"
25
- }else {
26
- return "SmartTV_Samsung_Tizen";
27
- }
28
- }
29
- export const getOSName = (deviceName:string) => {
30
- if (deviceName == "lgTv") {
31
- return "WebOS";
32
- } else if (deviceName == "vizioTv") {
33
- return "SmartCast";
34
- } else if(deviceName == "xfinityX1"){
35
- return "xfinityX1"
36
- }else if(deviceName == "xbox"){
37
- return "Windows"
38
- }else {
39
- return "Tizen";
40
- }
41
- }
42
- export const getDeviceShortName = (deviceName:string) => {
43
- if (deviceName == "lgTv") {
44
- return "lg";
45
- } else if (deviceName == "vizioTv") {
46
- return "vizio";
47
- } else if(deviceName == "xfinityX1"){
48
- return "xfinityX1"
49
- }else if(deviceName == "xbox"){
50
- return "xBox"
51
- }else {
52
- return "samsung";
53
- }
54
- }
55
- export const getDeviceFullName = (deviceName:string) => {
56
- if (deviceName == "lgTv") {
57
- return "smart_tv_lg";
58
- } else if (deviceName == "vizioTv") {
59
- return "vizioTv";
60
- } else if(deviceName == "xfinityX1"){
61
- return "xfinityX1"
62
- }else if(deviceName == "xbox"){
63
- return "windows_xbox"
64
- }else {
65
- return "smart_tv_samsung";
66
- }
67
- }
68
-
69
- export const getMacros=(width, height,deviceName,deviceId)=>{
70
- let objMacros = {};
71
- try{
72
- objMacros["VIEWLIFT_WIDTH"] = width;
73
- objMacros["VIEWLIFT_HEIGHT"] = height;
74
- objMacros["VIEWLIFT_SIZE"] = width + "x" + height;
75
- objMacros["VIEWLIFT_DOMAIN"] = (window as any).appMainConfig.domainName;
76
-
77
- objMacros["VIEWLIFT_CACHEBUSTER"] = (new Date()).getTime();
78
- objMacros["VIEWLIFT_TIMESTAMP"] = Math.floor((new Date()).getTime() % 1000);
79
- objMacros["VIEWLIFT_TIMESTAMP_MS"] = (new Date()).getTime();
80
- objMacros["VIEWLIFT_USER_AGENT"] = window.navigator.userAgent;
81
-
82
- // objMacros["VIEWLIFT_DURATION"] = time;
83
- objMacros["VIEWLIFT_MIN_DURATION"] = "0";
84
-
85
- objMacros["VIEWLIFT_AUTOPLAY"] = "1";
86
- objMacros["VIEWLIFT_DNT"] = "0";
87
- objMacros["VIEWLIFT_AD_POS"] = "1";
88
- objMacros["VIEWLIFT_MUTE"] = "0";
89
- objMacros["VIEWLIFT_DEVICE_MAKE"] = getDeviceMaker(deviceName);
90
- objMacros["VIEWLIFT_OS"] = getOSName(deviceName);
91
- objMacros["VIEWLIFT_LAT"] = (window as any).geoLocation?.latitude;
92
- objMacros["VIEWLIFT_LON"] = (window as any).geoLocation?.longitude;
93
- objMacros["VIEWLIFT_KEYWORDS"] = "720";
94
- objMacros["VIEWLIFT_CONSENT"] = "0";
95
- objMacros["VIEWLIFT_US_PRIVACY"] = "1";
96
- objMacros["VIEWLIFT_COPPA"] = "0";
97
- objMacros["VIEWLIFT_BRAND_NAME"] = getDeviceMaker(deviceName);
98
- objMacros["VIEWLIFT_IP"] = (window as any).geoLocation?.origip;
99
- objMacros["VIEWLIFT_MAX_POD_DURATION"] = "120";
100
- objMacros["VIEWLIFT_MAX_POD_DURATION_MS"] = "120000";
101
-
102
- // objMacros["VIEWLIFT_APP_ID"] = "";
103
- objMacros["VIEWLIFT_DEVICE_ID"] = deviceId;
104
- objMacros["VIEWLIFT_DID"] = deviceId;
105
- //objMacros["VIEWLIFT_APP_NAME"] = "";
106
- objMacros["VIEWLIFT_GDPR"] = "0";
107
- }catch(e){}
108
- return objMacros;
109
- }