diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000..37cfad78 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,12 @@ +root = true + +[*] +charset = utf-8 +end_of_line = lf +indent_size = 4 +indent_style = space +insert_final_newline = true +trim_trailing_whitespace = true + +[*.md] +trim_trailing_whitespace = false diff --git a/DevLauncher.js b/DevLauncher.js index 22d8f15c..c1e02a61 100644 --- a/DevLauncher.js +++ b/DevLauncher.js @@ -1,5 +1,8 @@ import {} from "./js/lib/lightning-web.js"; -import maf from "./js/src/maf.js"; +// MODIFICATION: removed this lib reference as it is making http calls to a metrological endpoint +// that is not needed by applications and it also presents potential security concerns +// additionall lib makes api call just by importing is which hamers testability +// import maf from "./js/src/maf.js"; import ux from "./js/src/ux.js"; export default class DevLauncher { @@ -28,7 +31,7 @@ export default class DevLauncher { }, targetTime - currentTime); }; } - + launch(appType, lightningOptions, options = {}) { this._appType = appType; this._options = options; @@ -68,6 +71,8 @@ export default class DevLauncher { _addStyles() { const style = document.createElement('style'); + // MODIFICATION - removeds hardcoded black background. + // This should be specified by applications not framework style.innerText = ` *,body{ margin:0; @@ -77,10 +82,6 @@ export default class DevLauncher { canvas { position: absolute; z-index: 2; -} - -body { - background: black; }`; document.head.appendChild(style); } @@ -100,7 +101,10 @@ body { } _getLightningOptions(customOptions = {}) { - let options = {stage: {w: 1920, h: 1080, clearColor: 0x00000000, canvas2d: false}, debug: false, keys: this._getNavigationKeys()}; + // MODIFICATION - dont need these default mappings - just need an empty array to make + // sure the web key event handler is registered properly - this should be changed to allow + // application to set the handlers if desired rather than hardcoding + let options = {stage: {w: 1920, h: 1080, clearColor: 0x00000000, canvas2d: false}, debug: false, keys: {}}; const config = options.stage; if (ux.Ui.hasOption("720") || window.innerHeight === 720) { @@ -122,30 +126,29 @@ body { } } - options = lng.tools.ObjMerger.merge(options, customOptions); return options; } - _getNavigationKeys() { - return { - 8: "Back", - 13: "Enter", - 27: "Menu", - 37: "Left", - 38: "Up", - 39: "Right", - 40: "Down", - 174: "ChannelDown", - 175: "ChannelUp", - 178: "Stop", - 250: "PlayPause", - 191: "Search", // Use "/" for keyboard - 409: "Search" - }; - } - + // MODIFICATION - no longer used. + // _getNavigationKeys() { + // return { + // 8: "Back", + // 13: "Enter", + // 27: "Menu", + // 37: "Left", + // 38: "Up", + // 39: "Right", + // 40: "Down", + // 174: "ChannelDown", + // 175: "ChannelUp", + // 178: "Stop", + // 250: "PlayPause", + // 191: "Search", // Use "/" for keyboard + // // 409: "Search" + // }; + // } } -DevLauncher._uxPath = "./node_modules/wpe-lightning-sdk/"; \ No newline at end of file +DevLauncher._uxPath = "./node_modules/wpe-lightning-sdk/"; diff --git a/dist/spark/DevLauncher.mjs b/dist/spark/DevLauncher.mjs index 1e9319d0..d6408844 100644 --- a/dist/spark/DevLauncher.mjs +++ b/dist/spark/DevLauncher.mjs @@ -1,11 +1,17 @@ import ux from "./src/ux.mjs"; import lng from 'wpe-lightning-spark'; import fetch from "node-fetch"; +// MODIFICATION - per direction from spark team - this script dependency is not needed +// import keyboard from "./src/keyboard.mjs"; export default class DevLauncher { - constructor() { - } + // MODIFICATION - per spark team keyboard is not needed by spark runtime + // constructor() { + // keyboard((event) => { + // this._handleKey(event); + // }); + // } launch(appType, lightningOptions, options = {}) { this._appType = appType; @@ -14,11 +20,29 @@ export default class DevLauncher { } _handleKey(event) { - this._ui._receiveKeydown(event); + this._ui._receiveKeydown( + // MODIFICATION: normalizes spark key event to the same structure + // as web keyboard event so that we can have "consistent" key handling code + // across platforms + this._normalizeKeyEvent(event)); + } + + // MODIFICATION: normalize key event to the same structure as web event + // so that we can have consistent key handling across platforms - this is + // as simple implementation for example purposes + _normalizeKeyEvent(keyEvent) { + const f = keyEvent.flags; + return { + keyCode: keyEvent.keyCode, + altKey: f === 48 || f === 56, + ctrlKey: f === 16 || f === 48 || f === 24 || f === 56, + shiftKey: f === 8 || f === 136 || f === 24 || f === 56, + }; } _start(lightningOptions = {}) { - this._openFirewall(); + // MODIFICATION - remove call to metro rest endpoint. + // this._openFirewall(); this._lightningOptions = this._getLightningOptions(lightningOptions); return this._startApp(); } @@ -30,55 +54,55 @@ export default class DevLauncher { this._ui.startApp(this._appType); } - _loadInspector() { - if (this._options.useInspector) { - /* Attach the inspector to create a fake DOM that shows where lightning elements can be found. */ - return this.loadScript(DevLauncher._uxPath + "../wpe-lightning/devtools/lightning-inspect.js"); - } else { - return Promise.resolve(); - } - } + // MODIFICATION - remove this code as inspector requires browser to work + // _loadInspector() { + // if (this._options.useInspector) { + // /* Attach the inspector to create a fake DOM that shows where lightning elements can be found. */ + // return this.loadScript(DevLauncher._uxPath + "../wpe-lightning/devtools/lightning-inspect.js"); + // } else { + // return Promise.resolve(); + // } + // } - _openFirewall() { - // Fetch app store to ensure that proxy/image servers firewall is opened. - //fetch(`http://widgets.metrological.com/${encodeURIComponent(ux.Ui.getOption('operator') || 'metrological')}/nl/test`).then(() => {}); - } + // MODIFICATION - no longer used + // _openFirewall() { + // Fetch app store to ensure that proxy/image servers firewall is opened. + // fetch(`http://widgets.metrological.com/${encodeURIComponent(ux.Ui.getOption('operator') || 'metrological')}/nl/test`).then(() => {}); + // } _getLightningOptions(customOptions = {}) { - let options = {stage: {w: 1920, h: 1080}, debug: false, keys: this._getNavigationKeys()}; - - const config = options.stage; - if (customOptions.h === 720) { - config['w'] = 1280; - config['h'] = 720; - config['precision'] = 0.6666666667; - } else { - config['w'] = 1920; - config['h'] = 1080; - - config.useImageWorker = true; - } - - options = lng.tools.ObjMerger.merge(options, customOptions); - - return options; - } - - _getNavigationKeys() { - return { - 8: "Back", - 13: "Enter", - 27: "Menu", - 37: "Left", - 38: "Up", - 39: "Right", - 40: "Down", - 174: "ChannelDown", - 175: "ChannelUp", - 178: "Stop", - 250: "PlayPause", - 191: "Search", // Use "/" for keyboard - 409: "Search" + // MODIFICATION - this file is spark aware - per spark team + // the resolution will always be 1280x720 - if not this should be externalized + // so applications can set accordingly + let options = { + stage: { + w: 1280, h: 720, + precision: 0.6666666667, + }, + debug: false, + // MODIFICATION - dont need these mappings, commenting out the property + // disables the confusing "no key handler registered" console message + // keys: this._getNavigationKeys(), }; + return lng.tools.ObjMerger.merge(options, customOptions); } + + // MODIFICATION - no longer referenced + // _getNavigationKeys() { + // return { + // 8: "Back", + // 13: "Enter", + // 27: "Menu", + // 37: "Left", + // 38: "Up", + // 39: "Right", + // 40: "Down", + // 174: "ChannelDown", + // 175: "ChannelUp", + // 178: "Stop", + // 250: "PlayPause", + // 191: "Search", // Use "/" for keyboard + // 409: "Search" + // }; + // } } diff --git a/dist/web/index.html b/dist/web/index.html index 6a7835e9..cb0ac0ad 100644 --- a/dist/web/index.html +++ b/dist/web/index.html @@ -1,9 +1,12 @@ + + + Lightning App @@ -17,10 +20,6 @@ position: absolute; z-index: 2; } - - body { - background: black; - } diff --git a/dist/web/js/init.js b/dist/web/js/init.js index 0565b7b8..b571f68d 100644 --- a/dist/web/js/init.js +++ b/dist/web/js/init.js @@ -18,22 +18,23 @@ function startApp() { }; } - var navigationKeys = { - 8: "Back", - 13: "Enter", - 27: "Back", - 10009: "Back", - 37: "Left", - 38: "Up", - 39: "Right", - 40: "Down", - 174: "ChannelDown", - 175: "ChannelUp", - 178: "Stop", - 250: "PlayPause", - 191: "Search", // Use "/" for keyboard - 409: "Search" - }; + // MODIFICATION - no longer used. + // var navigationKeys = { + // 8: "Back", + // 13: "Enter", + // 27: "Back", + // 10009: "Back", + // 37: "Left", + // 38: "Up", + // 39: "Right", + // 40: "Down", + // 174: "ChannelDown", + // 175: "ChannelUp", + // 178: "Stop", + // 250: "PlayPause", + // 191: "Search", // Use "/" for keyboard + // 409: "Search" + // }; const memoryPressure = parseInt(ux.Ui.getOption('memoryPressure')) || 16e6; console.log('GPU memory pressure: ' + memoryPressure); @@ -43,10 +44,14 @@ function startApp() { w: 1920, h: 1080, clearColor: ux.Ui.getOption('transparentBg') === "0" ? 0xFF000000 : 0x00000000, - defaultFontFace: 'RobotoRegular', + // MODIFICATION - default font face should be specified by applications + // defaultFontFace: 'RobotoRegular', memoryPressure: memoryPressure, canvas2d: ux.Ui.hasOption('c2d') - }, debug: false, keys: navigationKeys + // MODIFICATION - dont need these default mappings - just need an empty array to make + // sure the web key event handler is registered properly - this should be changed to allow + // application to set the handlers if desired rather than hardcoding + }, debug: false, keys: {} }; const config = options.stage; @@ -109,10 +114,10 @@ function loadScript(src) { }); } - +// MODIFICATION - removing call to metrological cause its a potentiual security issue // Fetch app store to ensure that proxy/image servers firewall is opened. -fetch('http://widgets.metrological.com/metrological/nl/test').then(function(){ -}); +// fetch('http://widgets.metrological.com/metrological/nl/test').then(function(){ +// }); const supportsEs6 = isSupportingES6(); const folder = supportsEs6 ? "src" : "src.es5"; @@ -134,4 +139,4 @@ loadPolyfill.then(function() { console.error(e); }).then(function() { startApp(); -}); \ No newline at end of file +}); diff --git a/js/src/Ui.js b/js/src/Ui.js index daaab80a..92a1fd98 100644 --- a/js/src/Ui.js +++ b/js/src/Ui.js @@ -1,18 +1,28 @@ -import Mediaplayer from "./Mediaplayer.js"; -import NoopMediaplayer from "./NoopMediaplayer.js"; +// MODIFICATION - not all applications need the media player. +// application should include this for themselves instead of hardcoded +// dependency in the framwework. +// import Mediaplayer from "./Mediaplayer.js"; +// import NoopMediaplayer from "./NoopMediaplayer.js"; import ScaledImageTexture from "./ScaledImageTexture.js"; export default class Ui extends lng.Application { constructor(options) { - options.defaultFontFace = options.defaultFontFace || "RobotoRegular"; + // MODIFICATION - removed reference to hardcoded Roboto font face + // application should be required to define it or it should fall back + // on system default + // + // RobotoRegular was being served from metrological endpoints which may + // present some security concerns for consuming applications + options.defaultFontFace = options.defaultFontFace; super(options); this._options = options; } static _template() { return { - Mediaplayer: {type: lng.Utils.isWeb ? Mediaplayer : NoopMediaplayer, textureMode: Ui.hasOption('texture')}, + // MODIFICATION - removed reference to media player. + // Mediaplayer: {type: lng.Utils.isWeb ? Mediaplayer : NoopMediaplayer, textureMode: Ui.hasOption('texture')}, AppWrapper: {} }; } @@ -25,12 +35,14 @@ export default class Ui extends lng.Application { return !Ui.hasOption("noImageServer"); } - get mediaplayer() { - return this.tag("Mediaplayer"); - } + // MODIFICATION - removed reference to media player. + // get mediaplayer() { + // return this.tag("Mediaplayer"); + // } _active() { - this.tag('Mediaplayer').skipRenderToTexture = this._options.skipRenderToTexture; + // MODIFICATION - removed reference to media player. + // this.tag('Mediaplayer').skipRenderToTexture = this._options.skipRenderToTexture; } startApp(appClass) { @@ -40,11 +52,19 @@ export default class Ui extends lng.Application { stopApp() { } - _handleBack() { - if (lng.Utils.isWeb) { - window.close(); - } - } + // MODIFICATION - window close doesnt work in all environemtns and + // can throw an unhandled error + // + // Also using _handleBack subtly requires clients of this class to register a back handler + // correctly which is not documented + // + // Additionally in our case the keycode that signifies + // application exit is context specific and may not map to keyCode 8 as hardcoded by framework + // _handleBack() { + // if (lng.Utils.isWeb) { + // window.close(); + // } + // } static loadFonts(fonts) { if (lng.Utils.isNode) { @@ -64,10 +84,13 @@ export default class Ui extends lng.Application { } static getFonts() { + // MODIFICATION - prevent loading of unneeded fonts + // need a way to let application's specify the fonts to use if specified at this level + return [ - {family: 'RobotoRegular', url: Ui.getPath('fonts/roboto-regular.ttf'), descriptors: {}}, - {family: 'Material-Icons', url: Ui.getPath('fonts/Material-Icons.ttf'), descriptors: {}} - ] + // {family: 'RobotoRegular', url: Ui.getPath('fonts/roboto-regular.ttf'), descriptors: {}}, + // {family: 'Material-Icons', url: Ui.getPath('fonts/Material-Icons.ttf'), descriptors: {}} + ]; } static _states() { @@ -121,12 +144,13 @@ export default class Ui extends lng.Application { _setFocusSettings(settings) { settings.clearColor = this.stage.getOption('clearColor'); - settings.mediaplayer = { - consumer: null, - stream: null, - hide: false, - videoPos: [0, 0, 1920, 1080] - }; + // MODIFICATION - removed reference to media player + // settings.mediaplayer = { + // consumer: null, + // stream: null, + // hide: false, + // videoPos: [0, 0, 1920, 1080] + // }; } _handleFocusSettings(settings) { @@ -135,13 +159,16 @@ export default class Ui extends lng.Application { this.stage.setClearColor(settings.clearColor); } - if (this.tag("Mediaplayer").attached) { - this.tag("Mediaplayer").updateSettings(settings.mediaplayer); - } + // MODIFICATION - removed reference to media player + // if (this.tag("Mediaplayer").attached) { + // this.tag("Mediaplayer").updateSettings(settings.mediaplayer); + // } } static getProxyUrl(url, opts = {}) { - return this._getCdnProtocol() + "://cdn.metrological.com/proxy" + this.getQueryString(url, opts); + throw new Error("DONT USE"); + // MODIFICATION - removing call out to a metrological cdn - security concerns + //return this._getCdnProtocol() + "://cdn.metrological.com/proxy" + this.getQueryString(url, opts); } static getImage(url, opts = {}) { @@ -153,12 +180,15 @@ export default class Ui extends lng.Application { } static getQrUrl(url, opts = {}) { - return this._getCdnProtocol() + "://cdn.metrological.com/qr" + this.getQueryString(url, opts, "q"); + throw new Error("DONT USE"); + // MODIFICATION - removing call out to a metrological cdn - security concerns + //return this._getCdnProtocol() + "://cdn.metrological.com/qr" + this.getQueryString(url, opts, "q"); } - static _getCdnProtocol() { - return lng.Utils.isWeb && location.protocol === "https:" ? "https" : "http"; - } + // MODIFICATION - unused code, no longer needed + // static _getCdnProtocol() { + // return lng.Utils.isWeb && location.protocol === "https:" ? "https" : "http"; + // } static hasOption(name) { if (lng.Utils.isNode) { @@ -176,15 +206,16 @@ export default class Ui extends lng.Application { return new URL(document.location.href).searchParams.get(name); } - static getQueryString(url, opts, key = "url") { - let str = `?operator=${encodeURIComponent(this.getOption('operator') || 'metrological')}`; - const keys = Object.keys(opts); - keys.forEach(key => { - str += "&" + encodeURIComponent(key) + "=" + encodeURIComponent("" + opts[key]); - }); - str += `&${key}=${encodeURIComponent(url)}`; - return str; - } + // MODIFICATION - unused code, no longer needed + // static getQueryString(url, opts, key = "url") { + // let str = `?operator=${encodeURIComponent(this.getOption('operator') || 'metrological')}`; + // const keys = Object.keys(opts); + // keys.forEach(key => { + // str += "&" + encodeURIComponent(key) + "=" + encodeURIComponent("" + opts[key]); + // }); + // str += `&${key}=${encodeURIComponent(url)}`; + // return str; + // } }