diff --git a/CHANGELOG.md b/CHANGELOG.md index de3f7df..12f0102 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,12 +4,85 @@ All notable changes to this project will be documented in this file. Dates are d Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). +#### [6.0.9](https://github.com/rdkcentral/rdke-refui/compare/6.0.8...6.0.9) + +- RDKEAPPRT-741: Upgrade the depends - wpe version [`#190`](https://github.com/rdkcentral/rdke-refui/pull/190) +- Merge tag '6.0.8' into develop [`2a946cc`](https://github.com/rdkcentral/rdke-refui/commit/2a946ccca509b994c18e36b96017cf5cdeaaa9d5) + +#### [6.0.8](https://github.com/rdkcentral/rdke-refui/compare/6.0.7...6.0.8) + +> 20 April 2026 + +- RDKMVE-1860 Guide page is not loading and RDKEAPPRT-693 Wakesrc LAN is not set by default [`#186`](https://github.com/rdkcentral/rdke-refui/pull/186) +- RDKEAPPRT-705 Changelog updates for 6.0.8 [`63623bc`](https://github.com/rdkcentral/rdke-refui/commit/63623bc846a83f068b17fea2c4d3772f5e8e5491) +- Merge tag '6.0.7' into develop [`6d2d811`](https://github.com/rdkcentral/rdke-refui/commit/6d2d811f9ae4e1532816ba83a151bd309c56ad0a) + +#### [6.0.7](https://github.com/rdkcentral/rdke-refui/compare/6.0.3...6.0.7) + +> 17 April 2026 + +- RDKEAPPRT-695 Incorrect IP address displayed on Network Info page after network reconnection and package version update for refui and wpe [`#183`](https://github.com/rdkcentral/rdke-refui/pull/183) +- RDKEAPPRT-684 Sleep Timer and Screen-Saver is not working [`#182`](https://github.com/rdkcentral/rdke-refui/pull/182) +- RDKEAPPRT-692 Handle Keycode 8 after Tatlow RCU pairing during FTI toavoid black screen and contain some fix for RCU pairing and powerstate [`#181`](https://github.com/rdkcentral/rdke-refui/pull/181) +- RDKMVE-2127 From Ref UI Home screen, Pressing Volume +/- leads to UI blank in the display [`#180`](https://github.com/rdkcentral/rdke-refui/pull/180) +- RDKEAPPRT-705 Changelog updates for 6.0.7 [`4b1d5be`](https://github.com/rdkcentral/rdke-refui/commit/4b1d5bef54924bfa99e6a8a62003e155db98b7b4) +- Merge tag '6.0.3' into develop [`c6030f2`](https://github.com/rdkcentral/rdke-refui/commit/c6030f2f54ffc42cd26e0e96688a41b460c13590) + +#### [6.0.3](https://github.com/rdkcentral/rdke-refui/compare/6.0.2...6.0.3) + +> 7 April 2026 + +- Updated the version for refui boltpackage [`#175`](https://github.com/rdkcentral/rdke-refui/pull/175) +- RDKEAPPRT-688 Changelog updates for 6.0.3 [`a64ad51`](https://github.com/rdkcentral/rdke-refui/commit/a64ad5142fef9c1341028d211ade283bb8d58f5b) +- Merge tag '6.0.2' into develop [`7d4582c`](https://github.com/rdkcentral/rdke-refui/commit/7d4582c752991e63442df51fecbaf152e355e4c5) + +#### [6.0.2](https://github.com/rdkcentral/rdke-refui/compare/6.0.1...6.0.2) + +> 7 April 2026 + +- RDKEAPPRT-683: RemoteControl plugin API align with MW APIv3.4.2 [`#171`](https://github.com/rdkcentral/rdke-refui/pull/171) +- RDKEAPPRT-683: Fix the RCU pairing trigger timers [`47df636`](https://github.com/rdkcentral/rdke-refui/commit/47df6367819c67c9bcab0a5ed99fa3007e976d99) +- RDKEAPPRT-683: fix the RCU re scanning logic leak. [`2610642`](https://github.com/rdkcentral/rdke-refui/commit/2610642a37e0d975cfb59ac9d5d4aa498ae4a115) +- /RDKEAPPRT-683: stop the scan triggers after RCU pairing [`34ee6be`](https://github.com/rdkcentral/rdke-refui/commit/34ee6bea00a1aba71dcbc2e969ef5a6d22f2e94c) + +#### [6.0.1](https://github.com/rdkcentral/rdke-refui/compare/6.0.0...6.0.1) + +> 31 March 2026 + +- Feature/rdkeapprt 680 :Update to new RDK logos [`#168`](https://github.com/rdkcentral/rdke-refui/pull/168) +- RDKEAPPRT-682 Changelog and package config version updates for 6.0.1 [`32bbba6`](https://github.com/rdkcentral/rdke-refui/commit/32bbba6f7cde97607cac613f80240a174073c6bf) +- RDKEAPPRT-680 :Update new logo [`83513d8`](https://github.com/rdkcentral/rdke-refui/commit/83513d8d0566d994927583ed7891c655660af97f) +- RDKEAPPRT-680:Update the new logo files [`c2b261f`](https://github.com/rdkcentral/rdke-refui/commit/c2b261ff1ea9e4e72a8750f77652d6f4261775ce) + +### [6.0.0](https://github.com/rdkcentral/rdke-refui/compare/5.0.24...6.0.0) + +> 31 March 2026 + +- To refresh the App store and main view when the authentication done [`#166`](https://github.com/rdkcentral/rdke-refui/pull/166) +- RDKEAPPRT-661 Add support for new authorization in App Catalog [`#165`](https://github.com/rdkcentral/rdke-refui/pull/165) +- RDKEAPPRT-621,606,648,644 fix for Language screen and powerstate issue [`#164`](https://github.com/rdkcentral/rdke-refui/pull/164) +- RDKEAPPRT-646 Create the Username, Password page and add it inside the settings route [`#163`](https://github.com/rdkcentral/rdke-refui/pull/163) +- RDKEAPPRT-645 Add default error overlay when user tries to enter VOD content [`#162`](https://github.com/rdkcentral/rdke-refui/pull/162) +- RDKEAPPRT-612 :Add dac store details via RFC [`#160`](https://github.com/rdkcentral/rdke-refui/pull/160) +- RDKEAPPRT-626,627,628,605,608,622 Fix error and uninstall overlay screen with bug fixes [`#161`](https://github.com/rdkcentral/rdke-refui/pull/161) +- RDKEAPPRT-601,602 App side loading and App side loading and closeApp() function [`#158`](https://github.com/rdkcentral/rdke-refui/pull/158) +- To merge the changes from Feature/app managers to develop [`#157`](https://github.com/rdkcentral/rdke-refui/pull/157) +- RDKEAPPRT-576 Improve focus management [`#155`](https://github.com/rdkcentral/rdke-refui/pull/155) +- RDKEAPPRT-341 App managers intake: abstractions, API migration and YouTube Launch Support [`#146`](https://github.com/rdkcentral/rdke-refui/pull/146) +- RDKEAPPRT-571 Create UI prototype with My Apps, Recommended Apps, VOD Rows and Appinfo (#156) [`eff1a86`](https://github.com/rdkcentral/rdke-refui/commit/eff1a864e55c28ed1c542e26f818d20f082a6dca) +- RDKEAPPRT-538 Add basic integration with the RDK Reference DAC 2.0 App Store (#152) [`82eda3d`](https://github.com/rdkcentral/rdke-refui/commit/82eda3d7b34b80be63bdf3d0cb39d6c3f7f1f681) +- Changes for the error and uninstall overlay screen then some bug fixes also part of this [`749f89d`](https://github.com/rdkcentral/rdke-refui/commit/749f89d0af61e7aab7d96cb70a392e4efb8f8020) + #### [5.0.24](https://github.com/rdkcentral/rdke-refui/compare/5.0.20...5.0.24) +> 12 February 2026 + +- RDKEAPPRT-575 [RDKUI] 5.0.24 Merge latest changes from develop to main, create release tag, and publish release. [`#154`](https://github.com/rdkcentral/rdke-refui/pull/154) - RDKEAPPRT-268 [RDK UI] Replace deprecated APIs for USB Media Device [`#153`](https://github.com/rdkcentral/rdke-refui/pull/153) - RDKEAPPRT-394 Adopt to New APIs for deprecated ones if not yet [`#151`](https://github.com/rdkcentral/rdke-refui/pull/151) - RDKEAPPRT-533-[RDK UI] Device is not discovered via DIAL after re-enabling Local Device Discovery option [`#150`](https://github.com/rdkcentral/rdke-refui/pull/150) - RDKEAPPRT-518 All SSIDs are not visible in FTI SSID selection screen [`#149`](https://github.com/rdkcentral/rdke-refui/pull/149) +- RDKEAPPRT-575 Changelog updates for 5.0.24 [`59d8252`](https://github.com/rdkcentral/rdke-refui/commit/59d8252ac9401f7882716fc5c055346653004996) - Merge tag '5.0.20' into develop [`4413c1c`](https://github.com/rdkcentral/rdke-refui/commit/4413c1cf7d14b54c8952299b291a44f311d7033e) #### [5.0.20](https://github.com/rdkcentral/rdke-refui/compare/5.0.17...5.0.20) diff --git a/accelerator-home-ui/settings.json b/accelerator-home-ui/settings.json index b73ffb3..273bba9 100644 --- a/accelerator-home-ui/settings.json +++ b/accelerator-home-ui/settings.json @@ -13,6 +13,6 @@ "log": true, "enableAppSuspended": true, "showVersion": false, - "version": "5.0.24" + "version": "6.0.16" } } diff --git a/accelerator-home-ui/src/App.js b/accelerator-home-ui/src/App.js index c86832c..2dccb06 100644 --- a/accelerator-home-ui/src/App.js +++ b/accelerator-home-ui/src/App.js @@ -35,6 +35,7 @@ import { import Keymap from './Config/Keymap'; import Menu from './views/Menu' import Failscreen from './screens/FailScreen'; +import FailAndOkScreen from './screens/FailAndOkScreen'; import { keyIntercept } from './keyIntercept/keyIntercept'; @@ -193,6 +194,9 @@ export default class App extends Router.App { Fail: { type: Failscreen, }, + FailOk: { + type: FailAndOkScreen, + }, Volume: { type: Volume }, @@ -251,13 +255,20 @@ export default class App extends Router.App { _captureKey(key) { this.LOG("Got keycode : " + JSON.stringify(key.keyCode)) this.LOG("powerState ===>" + JSON.stringify(GLOBALS.powerState)) - if (GLOBALS.powerState !== "ON") { - appApi.setPowerState("ON").then(res => { + if (GLOBALS.powerState === PowerState.POWER_STATE_DEEP_SLEEP || GLOBALS.powerState === PowerState.POWER_STATE_LIGHT_SLEEP) { + if (key.keyCode !== Keymap.Power) { + this.LOG("Ignoring non-power key press while device is in sleep state") + return true + } + this.initializeInactivityEngine(); + return this._performKeyPressOPerations(key) + } else if (GLOBALS.powerState !== PowerState.POWER_STATE_ON) { + appApi.setPowerState(PowerState.POWER_STATE_ON).then(res => { res ? this.LOG("successfully set the power state to ON from " + JSON.stringify(GLOBALS.powerState)) : this.LOG("Failure while turning ON the device") GLOBALS.powerState = PowerState.POWER_STATE_ON; this.LOG("powerState after ===>" + JSON.stringify(GLOBALS.powerState)) this.initializeInactivityEngine(); - }) + }) .catch(err => { this.ERR("Error waking device: " + JSON.stringify(err)); }) @@ -272,6 +283,12 @@ export default class App extends Router.App { if(GLOBALS.MiracastNotificationstatus && key.keyCode !== Keymap.Power && key.keyCode !== Keymap.Home ){ return false } else if ((key.keyCode == Keymap.Home || key.keyCode == Keymap.Escape) && !Router.isNavigating()) { + if (Router.getActiveHash().startsWith("splash")) { + if (Router.getActiveHash() !== "splash/language") { + Router.navigate("splash/language"); + } + return true; + } if (GLOBALS.topmostApp.includes("dac.native")) { this.jumpToRoute("apps"); } else if (GLOBALS.Miracastclientdevicedetails.state === "INITIATED" || GLOBALS.Miracastclientdevicedetails.state === "INPROGRESS ") { @@ -281,7 +298,7 @@ export default class App extends Router.App { } else if(GLOBALS.MiracastNotificationstatus){ this.jumpToRoute("menu"); miracast.acceptClientConnection("Reject").then(res=>{ - if(res.success){Router.focusPage()} + if(res.success){Router.focusPage()} }) } else { this.jumpToRoute("menu"); //method to exit the current app(if any) and route to home screen @@ -385,60 +402,27 @@ export default class App extends Router.App { // Remote power key and keyboard F1 key used for STANDBY and POWER_ON return this._powerKeyPressed() } else if (key.keyCode === Keymap.AudioVolumeMute && !Router.isNavigating()) { - if (GLOBALS.topmostApp === GLOBALS.selfClientName) { + if (GLOBALS.topmostApp === GLOBALS.selfclientAppName) { this.tag("Volume").onVolumeMute(); } else { this.LOG("muting on some app") - if (Router.getActiveHash() === "applauncher") { - this.LOG("muting on some app while route is app launcher") - RDKShellApis.moveToFront(GLOBALS.selfClientName) - RDKShellApis.setVisibility(GLOBALS.selfClientName, true) - this.tag("Volume").onVolumeMute(); - } else { - this.LOG("muting on some app while route is NOT app launcher") - RDKShellApis.moveToFront(GLOBALS.selfClientName) - RDKShellApis.setVisibility(GLOBALS.selfClientName, true) - Router.navigate("applauncher"); - this.tag("Volume").onVolumeMute(); - } + this.tag("Volume").onVolumeMute(); } return true } else if (key.keyCode == Keymap.AudioVolumeUp && !Router.isNavigating()) { - if (GLOBALS.topmostApp === GLOBALS.selfClientName) { + if (GLOBALS.topmostApp === GLOBALS.selfclientAppName) { this.tag("Volume").onVolumeKeyUp(); } else { - this.LOG("muting on some app") - if (Router.getActiveHash() === "applauncher") { - this.LOG("muting on some app while route is app launcher") - RDKShellApis.moveToFront(GLOBALS.selfClientName) - RDKShellApis.setVisibility(GLOBALS.selfClientName, true) - this.tag("Volume").onVolumeKeyUp(); - } else { - this.LOG("muting on some app while route is NOT app launcher") - RDKShellApis.moveToFront(GLOBALS.selfClientName) - RDKShellApis.setVisibility(GLOBALS.selfClientName, true) - Router.navigate("applauncher"); - this.tag("Volume").onVolumeKeyUp(); - } + this.LOG("increasing volume on some app") + this.tag("Volume").onVolumeKeyUp(); } return true } else if (key.keyCode == Keymap.AudioVolumeDown && !Router.isNavigating()) { - if (GLOBALS.topmostApp === GLOBALS.selfClientName) { + if (GLOBALS.topmostApp === GLOBALS.selfclientAppName) { this.tag("Volume").onVolumeKeyDown(); } else { - this.LOG("muting on some app") - if (Router.getActiveHash() === "applauncher") { - this.LOG("muting on some app while route is app launcher") - RDKShellApis.moveToFront(GLOBALS.selfClientName) - RDKShellApis.setVisibility(GLOBALS.selfClientName, true) - this.tag("Volume").onVolumeKeyDown(); - } else { - this.LOG("muting on some app while route is NOT app launcher") - RDKShellApis.moveToFront(GLOBALS.selfClientName) - RDKShellApis.setVisibility(GLOBALS.selfClientName, true) - Router.navigate("applauncher"); - this.tag("Volume").onVolumeKeyDown(); - } + this.LOG("decreasing volume on some app") + this.tag("Volume").onVolumeKeyDown(); } return true } else { @@ -513,8 +497,7 @@ export default class App extends Router.App { "Amazon": "n:2", "Prime": "n:2" } - this._getPowerStatebeforeReboot(); - this._registerFireboltListeners() + // this._registerFireboltListeners() Keyboard.provide('xrn:firebolt:capability:input:keyboard', new KeyboardUIProvider(this)) this.LOG("Keyboard provider registered") @@ -529,21 +512,6 @@ export default class App extends Router.App { Storage.set("deviceType", ((result.devicetype != null) ? result.devicetype : "IpTv")); }); UserSettingsApi.get().activate(); - thunder.Controller.activate({ - callsign: 'org.rdk.System' - }).then(result => { - this.LOG("App System plugin activation result: " + JSON.stringify(result)) - let param = { - //https://github.com/rdkcentral/entservices-apis/blob/1.15.11/docs/apis/PowerManagerPlugin.md#setWakeupSrcConfig - //By the above documentation we passed the Enum value sum to enable all wakeup sources expect WAKEUP_REASON_UNKNOWN - //Enum indicating bit position (bit counting starts at 1) - "wakeupSources": 262143 - } - appApi.setWakeupSrcConfiguration(param); - appApi.setPowerState(GLOBALS.powerState).then(res => {}); - }).catch(err => { - this.ERR("App System plugin activation error: " + JSON.stringify(err)); - }) appApi.getPluginStatus("org.rdk.DeviceDiagnostics").then(res => { this.LOG("App DeviceDiagnostics state:" + JSON.stringify(res[0].state)) if (res[0].state === "deactivated") { @@ -729,9 +697,13 @@ export default class App extends Router.App { appApi.getPluginStatus('org.rdk.PowerManager').then(result => { if (result && result.length > 0 && result[0].state === "activated") { console.log("org.rdk.PowerManager is already activated"); + this._getPowerStatebeforeReboot(); + this._setWakeupSourceConfig(); } else { PowerManagerApi.get().activate().then((res) => { this.LOG("activating the powermanager from app.js " + JSON.stringify(res)) + this._getPowerStatebeforeReboot(); + this._setWakeupSourceConfig(); }).catch((err) => this.ERR(JSON.stringify(err))) } }) @@ -839,28 +811,28 @@ export default class App extends Router.App { this._updateLanguageToDefault() // Initialize plugins using the abstraction this._activatePlugin( - "org.rdk.PackageManagerRDKEMS", - "PackageManagerRDKEMS", + "org.rdk.PackageManagerRDKEMS", + "PackageManagerRDKEMS", () => packagemangerRdkems.activate() ); - + this._activatePlugin( - "org.rdk.AppManager", - "AppManager", + "org.rdk.AppManager", + "AppManager", () => AppManager.get().activate(), () => this._SubscribeToAppManagerNotifications() ); - + this._activatePlugin( - "org.rdk.RDKWindowManager", - "RDKWindowManager", + "org.rdk.RDKWindowManager", + "RDKWindowManager", () => RDKWindowManager.get().activate(), () => this._SubscribeToRDKWindowManagerNotifications() ); - + this._activatePlugin( - "org.rdk.RuntimeManager", - "RuntimeManager", + "org.rdk.RuntimeManager", + "RuntimeManager", () => RuntimeManager.get().activate(), () => this._SubscribeToRuntimeManagerNotifications() ); @@ -961,7 +933,7 @@ export default class App extends Router.App { } else { GLOBALS.IsConnectedToInternet = false - } + } console.warn("onInternetStatusChange:", data); }); thunder.on('org.rdk.NetworkManager', 'onAvailableSSIDs', data => { @@ -1672,6 +1644,10 @@ export default class App extends Router.App { } _PowerStateHandlingWhileReboot() { + if (this._oldPowerStateWhileReboot === PowerState.POWER_STATE_STANDBY) { + this.LOG("_PowerStateHandlingWhileReboot: oldPowerStateWhileReboot is STANDBY, setting it to ON"); + this._oldPowerStateWhileReboot = PowerState.POWER_STATE_ON; + } this.LOG("_PowerStateHandlingWhileReboot: this._oldPowerStateWhileReboot , " + JSON.stringify(this._oldPowerStateWhileReboot) + " this._powerStateWhileReboot, " + JSON.stringify(this._powerStateWhileReboot) + " "); if (this._oldPowerStateWhileReboot != this._powerStateWhileReboot) { this.LOG("_PowerStateHandlingWhileReboot: old power state is not equal to powerstate while reboot " + JSON.stringify(this._oldPowerStateWhileReboot) + " " + JSON.stringify(this._powerStateWhileReboot)); @@ -1693,6 +1669,28 @@ export default class App extends Router.App { } } + _setWakeupSourceConfig() { + //https://jira.rdkcentral.com/jira/browse/RDKEAPPRT-693 + //by the above jira, we need to enable all wakeup sources in order to wake up the device from standby using any source. So enabling all the wakeup sources here. + let param = { + "wakeupSources": [ + {"wakeupSource": "VOICE", "enabled": true}, + {"wakeupSource": "IR", "enabled": true}, + {"wakeupSource": "CEC", "enabled": true}, + {"wakeupSource": "BLUETOOTH", "enabled": true}, + {"wakeupSource": "WIFI", "enabled": true}, + {"wakeupSource": "LAN", "enabled": true}, + {"wakeupSource": "POWERKEY", "enabled": true}, + ] + } + this.LOG("_setWakeupSourceConfig: Calling with param: " + JSON.stringify(param)) + appApi.setWakeupSourceConfig(param).then(res => { + this.LOG("_setWakeupSourceConfig: Successfully set wakeup source config: " + JSON.stringify(res)) + }).catch(err => { + this.ERR("_setWakeupSourceConfig: Error setting wakeup source config: " + JSON.stringify(err)) + }) + } + _getPowerStatebeforeReboot() { appApi.getPowerStateBeforeReboot().then(res => { this.LOG("_getPowerStatebeforeReboot: getpowerstate before reboot " + JSON.stringify(res)); @@ -1704,32 +1702,32 @@ export default class App extends Router.App { this._getPowerStateWhileReboot(); }); } - _registerFireboltListeners() { - FireBoltApi.get().deviceinfo.gettype() - FireBoltApi.get().lifecycle.ready() - - FireBoltApi.get().lifecycle.registerEvent('foreground', value => { - this.LOG("FireBoltApi[foreground] value:" + JSON.stringify(value) + ", launchResidentApp with:" + JSON.stringify(GLOBALS.selfClientName)); - // Ripple launches refui with this rdkshell client name. - GLOBALS.topmostApp = GLOBALS.selfClientName; - FireBoltApi.get().discovery.launch("refui", { - "action": "home", - "context": { - "source": "device" - } - }).then(() => { - AlexaApi.get().reportApplicationState("menu", true); - }) - }) - FireBoltApi.get().lifecycle.registerEvent('background', value => { - // Ripple changed app states; it will be a 'FireboltApp' - GLOBALS.topmostApp = "FireboltApp"; - this.LOG("FireBoltApi[foreground] value:" + JSON.stringify(value) + ", Updating top app as:" + JSON.stringify(GLOBALS.topmostApp)); - }) - FireBoltApi.get().lifecycle.state().then(res => { - this.LOG("Lifecycle.state result:" + JSON.stringify(res)) - }); - } + // _registerFireboltListeners() { + // FireBoltApi.get().deviceinfo.gettype() + // FireBoltApi.get().lifecycle.ready() + + // FireBoltApi.get().lifecycle.registerEvent('foreground', value => { + // this.LOG("FireBoltApi[foreground] value:" + JSON.stringify(value) + ", launchResidentApp with:" + JSON.stringify(GLOBALS.selfClientName)); + // // Ripple launches refui with this rdkshell client name. + // GLOBALS.topmostApp = GLOBALS.selfClientName; + // FireBoltApi.get().discovery.launch("refui", { + // "action": "home", + // "context": { + // "source": "device" + // } + // }).then(() => { + // AlexaApi.get().reportApplicationState("menu", true); + // }) + // }) + // FireBoltApi.get().lifecycle.registerEvent('background', value => { + // // Ripple changed app states; it will be a 'FireboltApp' + // GLOBALS.topmostApp = "FireboltApp"; + // this.LOG("FireBoltApi[foreground] value:" + JSON.stringify(value) + ", Updating top app as:" + JSON.stringify(GLOBALS.topmostApp)); + // }) + // FireBoltApi.get().lifecycle.state().then(res => { + // this.LOG("Lifecycle.state result:" + JSON.stringify(res)) + // }); + // } _firstEnable() { this.LOG("App Calling listenToVoiceControl method to activate VoiceControl Plugin") @@ -1759,7 +1757,7 @@ export default class App extends Router.App { if (!hasValidTimer) { this.LOG('No valid inactivity timers found. Disabling inactivity reporting.'); - RDKShellApis.enableInactivityReporting(false) + appApi.enableInactivityReporting(false) .catch(err => this.ERR('Error disabling inactivity: ' + JSON.stringify(err))); return; } @@ -1776,10 +1774,11 @@ export default class App extends Router.App { } } - registerOnUserInactivityListener() { - thunder.Controller.activate({ callsign: 'org.rdk.RDKShell.1' }).then(res => { - this.LOG("RDKShell activated, trying to set the inactivity listener; res = " + JSON.stringify(res)); - thunder.on("org.rdk.RDKShell.1", "onUserInactivity", async notification => { + async registerOnUserInactivityListener() { + try { + const res = await thunder.Controller.activate({ callsign: 'org.rdk.RDKWindowManager' }); + this.LOG("RDKWindowManager activated, trying to set the inactivity listener; res = " + JSON.stringify(res)); + thunder.on("org.rdk.RDKWindowManager", "onUserInactivity", async notification => { const { energySaver, screenSaver, sleepTimer } = inactivityHelper.getInactivityConfig(); const minutes = Math.floor(Number(notification.minutes)); @@ -1790,31 +1789,45 @@ export default class App extends Router.App { this.currentStage = 'ScreenSaver'; await this.triggerScreensaver(); } - // Sleep Timer Stage - if (inactivityHelper.isValidTimeout(sleepTimer) && minutes === sleepTimer) { - this.LOG('Sleep Timer triggered'); + // Sleep Timer + Energy Saver combined logic + const hasSleepTimer = inactivityHelper.isValidTimeout(sleepTimer); + const hasEnergySaver = inactivityHelper.isValidTimeout(energySaver); + + if (hasSleepTimer && hasEnergySaver && minutes === sleepTimer) { + // Both enabled: at sleep timer time, execute energy saver (deep sleep) + this.LOG('Sleep Timer + Energy Saver triggered together — entering deep sleep'); + this.currentStage = 'EnergySaver'; + if (GLOBALS.powerState === "ON" && GLOBALS.topmostApp === GLOBALS.selfclientAppName) { + this.LOG("Going to deep sleep due to inactivity (sleep timer + energy saver)"); + inactivityHelper._enterSleepMode(); + } + } else if (hasSleepTimer && !hasEnergySaver && minutes === sleepTimer) { + // Only sleep timer: standby as before + this.LOG('Sleep Timer triggered (no energy saver) — entering standby'); this.currentStage = 'SleepTimer'; - if (GLOBALS.powerState === "ON" && GLOBALS.topmostApp === GLOBALS.selfClientName) { + if (GLOBALS.powerState === "ON" && GLOBALS.topmostApp === GLOBALS.selfclientAppName) { inactivityHelper.standby('STANDBY'); } - } - // Energy Saver Stage - if (inactivityHelper.isValidTimeout(energySaver) && minutes === energySaver) { - this.LOG('Energy saver triggered'); + } else if (hasEnergySaver && !hasSleepTimer && minutes === energySaver) { + // Only energy saver (default 15 min): deep sleep + this.LOG('Energy Saver triggered (no sleep timer) — entering deep sleep'); this.currentStage = 'EnergySaver'; - if (GLOBALS.powerState === "ON" && GLOBALS.topmostApp === GLOBALS.selfClientName) { - this.LOG("Going to sleep due to inactivity"); + if (GLOBALS.powerState === "ON" && GLOBALS.topmostApp === GLOBALS.selfclientAppName) { + this.LOG("Going to deep sleep due to inactivity (energy saver only)"); inactivityHelper._enterSleepMode(); } } }, err => this.ERR("Listener error: " + JSON.stringify(err))); - }) + } catch (err) { + this.ERR("Failed to activate RDKWindowManager for inactivity listener: " + JSON.stringify(err)); + throw err; + } } async triggerScreensaver() { const result = await appApi.getAvCodeStatus(); if (["IDLE", "PAUSE"].includes(result.avDecoderStatus) && - GLOBALS.topmostApp === GLOBALS.selfClientName) { + GLOBALS.topmostApp === GLOBALS.selfclientAppName) { this.$hideImage(1); } return result; @@ -1835,15 +1848,19 @@ export default class App extends Router.App { this.currentInterval = screenSaver; } - RDKShellApis.enableInactivityReporting(true) - .then(() => RDKShellApis.setInactivityInterval(this.currentInterval)) - .then(() => { + appApi.enableInactivityReporting(true) + .then(() => appApi.setInactivityInterval(this.currentInterval)) + .then(async () => { this.LOG(`Inactivity interval set to ${this.currentInterval} for stage=${this.currentStage}`) if (!this.thunderListenerRegistered) { this.LOG("Registering listener for inactivity events..."); - this.registerOnUserInactivityListener(); - this.thunderListenerRegistered = true; + try { + await this.registerOnUserInactivityListener(); + this.thunderListenerRegistered = true; + } catch (err) { + this.ERR("Inactivity listener registration failed, will retry on next interval set: " + JSON.stringify(err)); + } } }) .catch(err => this.ERR("setInactivityIntervalStage error: " + JSON.stringify(err))); @@ -2081,13 +2098,19 @@ export default class App extends Router.App { appApi.getPowerState().then(res => { this.LOG("getPowerState: " + JSON.stringify(res)); if (res.currentState === "ON") { - this.LOG("current powerState is ON so setting power state to LIGHT_SLEEP/DEEP_SLEEP depending of preferred option"); - appApi.setPowerState(res.previousState).then(result => { - if (result) { - this.LOG("successfully set powerstate to: " + JSON.stringify(res.previousState)) - return result - } - }) + const { energySaver } = inactivityHelper.getInactivityConfig(); + if (inactivityHelper.isValidTimeout(energySaver)) { + this.LOG("Energy Saver is enabled — going to DEEP_SLEEP on power key press"); + inactivityHelper._enterSleepMode(); + } else { + this.LOG("current powerState is ON so setting power state to LIGHT_SLEEP"); + appApi.setPowerState(PowerState.POWER_STATE_LIGHT_SLEEP).then(result => { + if (result) { + this.LOG("successfully set powerstate to LIGHT_SLEEP") + return result + } + }) + } } else { this.LOG("current powerState is " + JSON.stringify(res.currentState) + " so setting power state to ON"); appApi.setPowerState("ON").then(result => { @@ -2124,7 +2147,7 @@ export default class App extends Router.App { appApi.getPowerState().then(res => { GLOBALS.powerState = res ? res.currentState : notification.newState }).catch(e => GLOBALS.powerState = notification.newState) - if (notification.newState !== "ON" && notification.currentState === "ON") { + if (notification.newState !== PowerState.POWER_STATE_ON && notification.currentState === PowerState.POWER_STATE_ON) { this.LOG("onPowerModeChanged Notification: power state was changed from ON to " + JSON.stringify(notification.newState)) //TURNING OFF THE DEVICE @@ -2134,11 +2157,34 @@ export default class App extends Router.App { appApi.exitApp(currentApp); //will suspend/destroy the app depending on the setting. } Router.navigate('menu'); - } else if (notification.newState === "ON" && notification.currentState !== "ON") { + } + else if(notification.newState === PowerState.POWER_STATE_LIGHT_SLEEP && notification.currentState === PowerState.POWER_STATE_DEEP_SLEEP){ + appApi.setPowerState(PowerState.POWER_STATE_ON).then(res => { + this.LOG("Device woke up from DEEP_SLEEP to LIGHT_SLEEP . setPowerState result: " + JSON.stringify(res)) + }).catch(err => { + this.ERR("Failed to set power state to ON when device woke up from DEEP_SLEEP to LIGHT_SLEEP. Error: " + JSON.stringify(err)) + }) + } + else if (notification.newState === PowerState.POWER_STATE_ON && notification.currentState !== PowerState.POWER_STATE_ON) { //TURNING ON THE DEVICE Storage.remove(SLEEP_STATE) } }) + // Catch up: if onPowerModeChanged fired before this listener was registered, + // sync GLOBALS.powerState and Storage(SLEEP_STATE) against live plugin state now. + appApi.getPowerState().then(res => { + if (!res) return; + const liveState = res.currentState; + this.LOG("subscribeToPowerChangeNotifications catch-up getPowerState: " + JSON.stringify(liveState)); + GLOBALS.powerState = liveState; + if (liveState !== PowerState.POWER_STATE_ON) { + Storage.set(SLEEP_STATE, liveState); + } else { + Storage.remove(SLEEP_STATE); + } + }).catch(err => { + this.ERR("subscribeToPowerChangeNotifications catch-up getPowerState error: " + JSON.stringify(err)); + }); } _moveApptoFront(appName, visibility) { @@ -2852,4 +2898,4 @@ export default class App extends Router.App { } } } -} \ No newline at end of file +} diff --git a/accelerator-home-ui/src/AppController.js b/accelerator-home-ui/src/AppController.js index 4ae3d35..5a4a564 100644 --- a/accelerator-home-ui/src/AppController.js +++ b/accelerator-home-ui/src/AppController.js @@ -175,25 +175,15 @@ export default class AppController { async addKeyIntercepts(appId, clientId) { if (appId === "com.rdkcentral.youtube") { try { + const intercepts = [ + { "keyCode": Keymap.AudioVolumeMute, "modifiers": [] }, + { "keyCode": Keymap.AudioVolumeDown, "modifiers": [] }, + { "keyCode": Keymap.AudioVolumeUp, "modifiers": [] }, + { "keyCode": Keymap.Youtube, "modifiers": [] } + ]; await RDKWindowManager.get().addKeyIntercepts({ - "intercepts": { - "intercepts": [{ - "keys": [{ - "keyCode": Keymap.AudioVolumeMute, - "modifiers": [] - }, { - "keyCode": Keymap.AudioVolumeDown, - "modifiers": [] - }, { - "keyCode": Keymap.AudioVolumeUp, - "modifiers": [] - }, { - "keyCode": Keymap.Youtube, - "modifiers": [] - }], - "client": clientId - }] - } + "clientId": clientId, + "intercepts": JSON.stringify(intercepts) }); } catch (err) { throw new ThunderError("RDKWindowManager.addKeyIntercepts()", err); diff --git a/accelerator-home-ui/src/Config/Config.js b/accelerator-home-ui/src/Config/Config.js index 74df182..c397b6d 100644 --- a/accelerator-home-ui/src/Config/Config.js +++ b/accelerator-home-ui/src/Config/Config.js @@ -59,7 +59,6 @@ export var CONFIG = { port: 9998, versions: { default: 1, - 'org.rdk.System': 2, ControlSettings: 2, 'org.rdk.UsbAccess': 2, 'org.rdk.DisplaySettings': 2, diff --git a/accelerator-home-ui/src/api/AppApi.js b/accelerator-home-ui/src/api/AppApi.js index 4b2bb9b..eb0005b 100644 --- a/accelerator-home-ui/src/api/AppApi.js +++ b/accelerator-home-ui/src/api/AppApi.js @@ -1607,7 +1607,7 @@ export default class AppApi { getRFCConfig(rfcParamsList) { return new Promise((resolve, reject) => { - thunder.call('org.rdk.System', 'getRFCConfig', rfcParamsList).then(result => { + thunder.call('org.rdk.System', 'getRFCConfig',{"rfcList":[rfcParamsList]}).then(result => { if (result.success) { resolve(result) } else { @@ -1623,8 +1623,8 @@ export default class AppApi { }) } - setWakeupSrcConfiguration(params) { - return PowerManagerApi.get().setWakeupSrcConfig(params) + setWakeupSourceConfig(params) { + return PowerManagerApi.get().setWakeupSourceConfig(params) } async sendAppState(value) { diff --git a/accelerator-home-ui/src/api/AppCatalog.js b/accelerator-home-ui/src/api/AppCatalog.js new file mode 100644 index 0000000..859c557 --- /dev/null +++ b/accelerator-home-ui/src/api/AppCatalog.js @@ -0,0 +1,453 @@ +/** + * If not stated otherwise in this file or this component's LICENSE + * file the following copyright and licenses apply: + * + * Copyright 2026 RDK Management + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +import PackageManager from './PackageManagerApi'; +import AppApi from './AppApi'; + +const APP_DEFAULT_ARCH = "arm"; +const APP_STORE_RFC_KEY = "Device.DeviceInfo.X_RDKCENTRAL-COM_RFC.DAC.ConfigURL"; + +const debug = false; + +let appCatalogHandler = null; + +export const eventTarget = new EventTarget(); + +export class AuthNeeded extends Event { + static eventName = 'authNeeded'; + + constructor() { + super(AuthNeeded.eventName); + } +} + +export class RefreshNeeded extends Event { + static eventName = 'refreshNeeded'; + + constructor() { + super(RefreshNeeded.eventName); + } +} + +class AuthExpiredError extends Error { + constructor(url) { + super(`Authentication expired (${url})`); + this.name = 'AuthExpiredError'; + } +} + +class PromiseQueue { + constructor() { + this.next = Promise.resolve(); + } + + enqueue(fn) { + let unlock; + const next = new Promise(resolve => { unlock = resolve; }); + const result = this.next.then(fn); + result.then(unlock, unlock); + this.next = next; + return result; + } +} + +async function getConfigUrlFromRFC() { + try { + const appApi = new AppApi(); + console.log("Resolving config URL from RFC "); + const result = await appApi.getRFCConfig(APP_STORE_RFC_KEY); + const rfcUrl = result?.RFCConfig?.[APP_STORE_RFC_KEY]; + if (typeof rfcUrl === "string" && rfcUrl.trim().length > 0) { + const resolvedConfigUrl = rfcUrl.trim(); + console.log("Resolved config URL from RFC "); + return resolvedConfigUrl; + } + console.warn("Config RFC URL empty or invalid"); + return null; + } catch (err) { + console.error("Failed to get config URL from RFC", err); + return null; + } +} + +async function getConfigUrlFromPackageManager() { + try { + console.log("Resolving config URL from PackageManager..."); + const config = await PackageManager.get().configuration(); + console.log("Resolved server config URL from PackageManager: "); + if (typeof config?.configUrl !== "string" || config.configUrl.trim().length === 0) { + throw new Error("Invalid config: " + JSON.stringify(config)); + } + + return config.configUrl.trim(); + } catch (err) { + console.error("Failed to resolve config URL from PackageManager", err); + throw err; + } +} + +let serverURL = null; +let serverURLPromise = null; + +async function getServerURL() { + if (!serverURL) { + if (!serverURLPromise) { + async function resolve() { + let url = await getConfigUrlFromRFC(); + + if (!url) { + url = await getConfigUrlFromPackageManager(); + } + console.log(`Server URL: ${url}`); + return url; + } + + serverURLPromise = resolve(); + } + + try { + serverURL = await serverURLPromise; + } catch (err) { + serverURLPromise = null; + throw err; + } + } + + return serverURL; +} + +class StubAppCatalogHandler { + getApps(offset, limit) { + return { applications: [] }; + } + + getAppDetails(id, version) { + throw new Error('getAppDetails() is not supported'); + } + + makeDownloadURL(url) { + throw new Error('makeDownloadURL() is not supported'); + } +} + +class LegacyAppCatalogHandler { + constructor(configURL) { + this.configURL = configURL; + this.storeConfig = null; + } + + async getStoreConfig() { + if (!this.storeConfig) { + let resolvedConfigUrl = this.configURL; + + const fetchResponse = await fetch(resolvedConfigUrl); + if (!fetchResponse.ok) { + throw new Error(`Unexpected response: ${fetchResponse.status}: ${fetchResponse.statusText}`); + } + const responseObject = await fetchResponse.json(); + + if (typeof responseObject?.["appstore-catalog"]?.url !== "string") { + throw new Error("Invalid response object: " + JSON.stringify(responseObject)); + } + const catalog = responseObject["appstore-catalog"]; + this.storeConfig = { url: catalog.url }; + + if (typeof catalog?.authentication?.user === "string" && + typeof catalog?.authentication?.password === "string") { + this.storeConfig.authHeader = + "Basic " + btoa(catalog.authentication.user + ':' + catalog.authentication.password); + } + } + + return this.storeConfig; + } + + async fetchStoreObject(request) { + let config = await this.getStoreConfig(); + let headers = new Headers(); + + if (config.authHeader) { + headers.append("Authorization", config.authHeader); + } + + let requestOptions = { + method: 'GET', + headers, + redirect: 'follow', + }; + + const fetchResponse = await fetch(config.url + request, requestOptions); + if (!fetchResponse.ok) { + throw new Error(`Unexpected response: ${fetchResponse.status}: ${fetchResponse.statusText}`); + } + + return fetchResponse.json(); + } + + getAppDetails(id, version) { + return this.fetchStoreObject("/apps/" + id + ":" + version + "?arch=" + APP_DEFAULT_ARCH); + } + + async getApps(offset, limit) { + const request = "/apps?arch=" + APP_DEFAULT_ARCH + "&offset=" + offset + "&limit=" + limit; + + try { + return await this.fetchStoreObject(request); + } catch (err) { + console.error(`fetchStoreObject(${request}) ${err}`); + throw err; + } + } + + makeDownloadURL(url) { + return url; + } +} + +class AppCatalogHandler { + constructor(serverURL) { + this.serverURL = serverURL; + this.authURL = this.serverURL + '/auth'; + this.appCatalogURL = this.serverURL + '/appcatalog'; + this.timerId = null; + this.queue = new PromiseQueue(); + } + + async fetch(url, options) { + const response = await this.queue.enqueue(() => fetch(url, { credentials: 'include', ...options })); + if (response.status === 401 || response.status === 403) { + this.cancelRefresh(); + throw new AuthExpiredError(url); + } + if (!response.ok) { + throw new Error(`Unexpected response: ${response.status}: ${response.statusText} (${url})`); + } + return response; + } + + async postAuthObject(request, obj) { + let options = { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + redirect: 'follow', + body: JSON.stringify(obj), + }; + + const url = this.authURL + request; + const response = await this.fetch(url, options); + const responseObj = await response.json(); + if (debug) { + console.log(`Auth response: ${JSON.stringify(responseObj, null, 2)}`); + } + return responseObj; + } + + calculateTimeout(expiresIn) { + const MIN = 60; + const MAX = 4 * 60 * 60; // 4 hours + + let timeout = Math.min(Math.max(expiresIn / 2, MIN), MAX); + + if (debug) { + console.log(`Calculated timeout: ${timeout}`); + } + + return timeout * 1000; + } + + scheduleRefresh(response, onAuthExpired) { + if (typeof response.expiresIn !== "number") { + return; + } + const expiresIn = response.expiresIn; + + this.cancelRefresh(); + + this.timerId = setTimeout(async () => { + this.timerId = null; + try { + const refreshResponse = await this.refresh(); + this.scheduleRefresh(refreshResponse, onAuthExpired); + } catch (err) { + console.warn(`Refresh failed: ${err}`); + onAuthExpired(); + } + }, this.calculateTimeout(expiresIn)); + } + + cancelRefresh() { + if (this.timerId) { + clearTimeout(this.timerId); + this.timerId = null; + } + } + + async refresh() { + return this.postAuthObject('/refresh', {}); + } + + async login(user, pass) { + this.cancelRefresh(); + return this.postAuthObject('/login', { username: user, password: pass }); + } + + async fetchAppCatalogObject(request) { + const url = this.appCatalogURL + request; + const fetchResponse = await this.fetch(url, { method: 'GET', redirect: 'follow' }); + const result = await fetchResponse.json(); + if (debug) { + console.log(`${url} : ${JSON.stringify(result, null, 2)}`); + } + return result; + } + + async getAppDetails(id, version) { + return this.fetchAppCatalogObject("/apps/" + id + ":" + version + "?arch=" + APP_DEFAULT_ARCH); + } + + async getApps(offset, limit) { + const request = "/apps?arch=" + APP_DEFAULT_ARCH + "&offset=" + offset + "&limit=" + limit; + + try { + return await this.fetchAppCatalogObject(request); + } catch (err) { + console.error(`fetchAppCatalogObject(${request}) ${err}`); + throw err; + } + } + + async getServiceToken(token) { + const url = this.authURL + "/servicetokens/" + token; + const response = await this.fetch(url, { method: 'GET', redirect: 'follow' }); + const result = await response.json(); + if (debug) { + console.log(`${url}: ${JSON.stringify(result, null, 2)}`); + } + return result; + } + + async makeDownloadURL(url) { + const token = await this.getServiceToken('download-manager'); + const downloadURL = new URL(url); + downloadURL.searchParams.set('token', token.token); + return downloadURL.toString(); + } +} + +let initPromise = null; + +function handleAuthExpired(handler) { + if (appCatalogHandler === handler) { + appCatalogHandler = new StubAppCatalogHandler(); + eventTarget.dispatchEvent(new AuthNeeded()); + } +} + +async function callAndHandleAuthExpired(handler, fn) { + try { + return await fn(); + } catch (err) { + if (err instanceof AuthExpiredError) { + handleAuthExpired(handler); + } + throw err; + } +} + +async function initAppCatalogHandler() { + if (!initPromise) { + async function init() { + appCatalogHandler = new StubAppCatalogHandler(); + + try { + const url = await getServerURL(); + + if (url.endsWith('/cpe.json')) { + appCatalogHandler = new LegacyAppCatalogHandler(url); + return; + } + + const handler = new AppCatalogHandler(url); + const refreshResponse = await handler.refresh(); + handler.scheduleRefresh(refreshResponse, () => handleAuthExpired(handler)); + appCatalogHandler = handler; + } catch (err) { + console.log(`initAppCatalogHandler() ${err}`); + if (err instanceof AuthExpiredError) { + eventTarget.dispatchEvent(new AuthNeeded()); + } else { + throw err; + } + } + } + + initPromise = init().catch(() => { + initPromise = null; + }); + } + return initPromise; +} + +export async function isLoggedIn() { + await initAppCatalogHandler(); + return appCatalogHandler instanceof AppCatalogHandler; +} + +export async function login(user, pass) { + await initAppCatalogHandler(); + + const handler = appCatalogHandler instanceof AppCatalogHandler + ? appCatalogHandler + : new AppCatalogHandler(await getServerURL()); + + try { + const loginResponse = await handler.login(user, pass); + appCatalogHandler = handler; + handler.scheduleRefresh(loginResponse, () => handleAuthExpired(handler)); + eventTarget.dispatchEvent(new RefreshNeeded()); + return true; + } catch (err) { + console.warn(`Login failed: ${err}`); + return false; + } +} + +export async function getApps(offset, limit) { + await initAppCatalogHandler(); + const handler = appCatalogHandler; + return callAndHandleAuthExpired(handler, () => handler.getApps(offset, limit)); +} + +export async function getAppDetails(id, version) { + await initAppCatalogHandler(); + const handler = appCatalogHandler; + return callAndHandleAuthExpired(handler, () => handler.getAppDetails(id, version)); +} + +export async function makeDownloadURL(url) { + await initAppCatalogHandler(); + const handler = appCatalogHandler; + return callAndHandleAuthExpired(handler, () => handler.makeDownloadURL(url)); +} + +export async function getCatalogServerURL() { + return getServerURL(); +} diff --git a/accelerator-home-ui/src/api/DACApi.js b/accelerator-home-ui/src/api/DACApi.js index d03afbf..ab0a7d2 100644 --- a/accelerator-home-ui/src/api/DACApi.js +++ b/accelerator-home-ui/src/api/DACApi.js @@ -17,6 +17,7 @@ * limitations under the License. **/ +import { Language } from '@lightningjs/sdk'; import DownloadManager from './DownloadManagerApi'; import PackageManager from './PackageManagerApi'; import AppManager from './AppManagerApi'; @@ -24,6 +25,7 @@ import AppController from '../AppController'; import { ThunderError } from './ThunderError'; import { Metrics } from '@firebolt-js/sdk' import { SIDELOADED_APP_DEFAULT_ICON, deriveNameFromPackageId } from '../helpers/DACAppPresentation' +import { getApps, getAppDetails, makeDownloadURL } from './AppCatalog'; // the size that is assumed if it is not possible to retrieve package size // from the server, according to server API this should never happen @@ -36,8 +38,6 @@ const APPS_REQUESTS_MAX = 5; const APP_DETAILS_KEY = "refui.details"; -const APP_DEFAULT_ARCH = "arm"; - function makeLogMessage(call, err) { return err.toString() + " <=> " + call; } @@ -69,73 +69,23 @@ class OperationLock { }; let packageLock = new OperationLock(); -let storeConfig = null; - -async function getStoreConfig() { - if (!storeConfig) { - const config = await PackageManager.get().configuration(); - if (typeof config?.configUrl !== "string") { - throw new Error("Invalid config: " + JSON.stringify(config)); - } - const fetchResponse = await fetch(config.configUrl); - if (!fetchResponse.ok) { - throw new Error(`Unexpected response: ${fetchResponse.status}: ${fetchResponse.statusText}`); - } - const responseObject = await fetchResponse.json(); - if (typeof responseObject?.["appstore-catalog"]?.url !== "string") { - throw new Error("Invalid response object: " + JSON.stringify(responseObject)); - } - storeConfig = responseObject["appstore-catalog"]; - } - - return storeConfig; -} - -async function fetchStoreObject(request) { - let config = await getStoreConfig(); - let headers = new Headers(); - - if (typeof config?.authentication?.user === "string" && - typeof config?.authentication?.password === "string") { - headers.append( - "Authorization", - "Basic " + btoa(config.authentication.user + ':' + config.authentication.password) - ); - } - - let requestOptions = { - method: 'GET', - headers, - redirect: 'follow', - }; - - const fetchResponse = await fetch(config.url + request, requestOptions); - if (!fetchResponse.ok) { - throw new Error(`Unexpected response: ${fetchResponse.status}: ${fetchResponse.statusText}`); - } - - return fetchResponse.json(); -} export async function getAppCatalogInfo() { let result = []; let offset = 0; for (let i = 0; i < APPS_REQUESTS_MAX; ++i) { - const request = "/apps?arch=" + APP_DEFAULT_ARCH + "&offset=" + offset + "&limit=" + APPS_REQUEST_LIMIT; - console.log(`Requesting: ${request}`); try { - const appsResponse = await fetchStoreObject(request); + const appsResponse = await getApps(offset, APPS_REQUEST_LIMIT); if (!Array.isArray(appsResponse?.applications)) { break; } result = result.concat(appsResponse.applications); - if (result.length >= appsResponse?.meta?.resultSet?.total ?? 0) { + if (result.length >= (appsResponse?.meta?.resultSet?.total ?? 0)) { break; } offset = result.length; } catch (err) { - console.error(`fetch(${request}) ${err}`); Metrics.error(Metrics.ErrorType.OTHER, "DACApiError", err.toString(), false, null); break; } @@ -144,10 +94,6 @@ export async function getAppCatalogInfo() { return result; } -function getAppDetails(id, version) { - return fetchStoreObject("/apps/" + id + ":" + version + "?arch=" + APP_DEFAULT_ARCH); -} - function retrieveURLAndSize(details) { if (typeof details?.header?.url === "string") { const url = details.header.url; @@ -181,10 +127,11 @@ async function downloadAndInstall(pkg, downloadedSize, totalSize, progress) { const downloadId = await new Promise(async (resolve, reject) => { try { - await DownloadManager.get().download(pkg.url, (downloadId, percent, failReason) => { + const downloadURL = await makeDownloadURL(pkg.url); + await DownloadManager.get().download(downloadURL, (downloadId, percent, failReason) => { if (!failReason) { if (percent !== 100) { - progress((downloadedSize + pkg.size * percent / 100) / totalSize, "Downloading"); + progress((downloadedSize + pkg.size * percent / 100) / totalSize, Language.translate("Downloading")); } else { resolve(downloadId); } diff --git a/accelerator-home-ui/src/api/PowerManagerApi.js b/accelerator-home-ui/src/api/PowerManagerApi.js index 744260e..9153fe2 100644 --- a/accelerator-home-ui/src/api/PowerManagerApi.js +++ b/accelerator-home-ui/src/api/PowerManagerApi.js @@ -85,15 +85,15 @@ export default class PowerManagerApi { }) } - setWakeupSrcConfig(params) { - this.LOG("setWakeupSrcConfiguration params:", JSON.stringify(params)); + setWakeupSourceConfig(params) { + this.LOG("setWakeupSourceConfig params:", JSON.stringify(params)); return new Promise((resolve, reject) => { - this.thunder.call(this.callsign, 'setWakeupSrcConfig', params).then(result => { - this.LOG(" setWakeupSrcConfiguration result:", JSON.stringify(result)) + this.thunder.call(this.callsign, 'setWakeupSourceConfig', params).then(result => { + this.LOG(" setWakeupSourceConfig result:", JSON.stringify(result)) resolve(result) }).catch(err => { - this.ERR(" setWakeupSrcConfiguration error:", JSON.stringify(err)) - Metrics.error(Metrics.ErrorType.OTHER, "PluginError", "Error in Thunder system setWakeupSrcConfiguration " + JSON.stringify(err), false, null) + this.ERR(" setWakeupSourceConfig error:", JSON.stringify(err)) + Metrics.error(Metrics.ErrorType.OTHER, "PluginError", "Error in Thunder system setWakeupSourceConfig " + JSON.stringify(err), false, null) reject(err) }) }) diff --git a/accelerator-home-ui/src/api/RemoteControl.js b/accelerator-home-ui/src/api/RemoteControl.js index 1caf9f1..0cb6978 100644 --- a/accelerator-home-ui/src/api/RemoteControl.js +++ b/accelerator-home-ui/src/api/RemoteControl.js @@ -92,21 +92,33 @@ export default class RCApi { }) } - startPairing(timeout = 30, netType ) { + startPairing(timeout = 30) { return new Promise((resolve, reject) => { - //this.INFO("RCApi: startPairing netType " + netType + " timeout " + timeout); - this.thunder.call('org.rdk.RemoteControl', 'startPairing', { netType: netType, timeout: timeout }).then(result => { - //this.INFO("RCApi: startPairing result: ", JSON.stringify(result)) + this.thunder.call('org.rdk.RemoteControl', 'startPairing', { timeout: timeout, screenBindEnable: false }).then(result => { + this.INFO("RCApi: startPairing result: " + JSON.stringify(result)) resolve(result.success); }).catch(err => { this.ERR("RCApi: startPairing error: " + JSON.stringify(err)); Metrics.error(Metrics.ErrorType.OTHER,"RemoteControlApiError", "Error in Thunder RemoteControl startPairing "+JSON.stringify(err), false, null) reject(err); }); - resolve(true); }) } + stopPairing() { + return new Promise((resolve, reject) => { + this.INFO("RCApi: stopPairing"); + this.thunder.call('org.rdk.RemoteControl', 'stopPairing', {scanDisable: true}).then(result => { + this.INFO("RCApi: stopPairing result: " + JSON.stringify(result)) + resolve(result.success); + }).catch(err => { + this.ERR("RCApi: stopPairing error: " + JSON.stringify(err)); + Metrics.error(Metrics.ErrorType.OTHER, "RemoteControlApiError", "Error in Thunder RemoteControl stopPairing " + JSON.stringify(err), false, null) + reject(err); + }); + }); + } + initializeIRDB() { return new Promise((resolve, reject) => { /*TODO: implement when requirement comes.*/ @@ -186,10 +198,10 @@ export default class RCApi { }) } - findMyRemote(netType = 1, level = "mid") { + findMyRemote(level = "mid") { return new Promise((resolve, reject) => { - this.INFO("RCApi: findMyRemote netType:" + JSON.stringify(netType) + " level:" + JSON.stringify(level)); - this.thunder.call('org.rdk.RemoteControl', 'findMyRemote', { netType: netType, level: level }).then(result => { + this.INFO("RCApi: findMyRemote level:" + JSON.stringify(level)); + this.thunder.call('org.rdk.RemoteControl', 'findMyRemote', { level: level }).then(result => { this.INFO("RCApi: findMyRemote result: " + JSON.stringify(result)) resolve(result.success); }).catch(err => { @@ -200,6 +212,8 @@ export default class RCApi { }) } + // This is to reset the remote control firmware; not to be confused with factory reset of the device. + // This will not erase user data or settings on the device. factoryReset() { return new Promise((resolve, reject) => { this.INFO("RCApi: factoryReset"); @@ -213,4 +227,18 @@ export default class RCApi { }); }) } + + unpair(macAddressList) { + return new Promise((resolve, reject) => { + this.INFO("RCApi: unpair macAddressList:" + JSON.stringify(macAddressList)); + this.thunder.call('org.rdk.RemoteControl', 'unpair', { macAddressList: macAddressList }).then(result => { + this.INFO("RCApi: unpair result: " + JSON.stringify(result)) + resolve(result.success); + }).catch(err => { + this.ERR("RCApi: unpair error: " + JSON.stringify(err)); + Metrics.error(Metrics.ErrorType.OTHER, "RemoteControlApiError", "Error in Thunder RemoteControl unpair " + JSON.stringify(err), false, null) + reject(err); + }); + }); + } } diff --git a/accelerator-home-ui/src/api/WarehouseApis.js b/accelerator-home-ui/src/api/WarehouseApis.js index 2c3ef90..43c4621 100644 --- a/accelerator-home-ui/src/api/WarehouseApis.js +++ b/accelerator-home-ui/src/api/WarehouseApis.js @@ -121,14 +121,17 @@ export default class Warehouse { }) } - resetDevice(resetType = "USERFACTORY", suppressReboot = "false") { + resetDevice(resetType = "WAREHOUSE_CLEAR", suppressReboot = false) { return new Promise((resolve, reject) => { let params = { resetType: resetType, suppressReboot: suppressReboot} this.INFO(this.callsign + " resetDevice params: " + JSON.stringify(params)); this.thunder.call(this.callsign, 'resetDevice', params).then(result => { this.INFO(this.callsign + " resetDevice result: " + JSON.stringify(result)) - if (result.success)resolve(result.success) - reject(false) + if (result.success) { + resolve(result.success) + } else { + reject(false) + } }).catch(err => { this.ERR(this.callsign + " resetDevice error: " + JSON.stringify(err)) Metrics.error(Metrics.ErrorType.OTHER,"WarehouseApiError", "Error while Thunder warehouseApi resetDevice "+JSON.stringify(err), false, null) diff --git a/accelerator-home-ui/src/helpers/InactivityHelper.js b/accelerator-home-ui/src/helpers/InactivityHelper.js index 53d6094..d9d3c91 100644 --- a/accelerator-home-ui/src/helpers/InactivityHelper.js +++ b/accelerator-home-ui/src/helpers/InactivityHelper.js @@ -18,9 +18,9 @@ **/ import { Router, Storage } from '@lightningjs/sdk'; import AppApi from '../api/AppApi.js'; -import RDKShellApis from '../api/RDKShellApis.js'; import { GLOBALS } from '../Config/Config.js'; import { PowerState } from '../api/PowerManagerApi.js'; +import AppManager from '../api/AppManagerApi.js'; var appApi = new AppApi(); @@ -70,7 +70,7 @@ export default class InactivityHelper { if (activeStages.length === 0) { this.LOG('No active timers left. Disabling inactivity reporting.'); - RDKShellApis.enableInactivityReporting(false) + appApi.enableInactivityReporting(false) .catch(err => this.ERR('Error disabling inactivity: ' + JSON.stringify(err))); } else { this.LOG(`Stage ${stage} cleared, but ${activeStages.join(', ')} still active.`); @@ -110,8 +110,23 @@ export default class InactivityHelper { if (res) { this.LOG("successfully set to standby"); GLOBALS.powerState = PowerState.POWER_STATE_STANDBY - if (GLOBALS.topmostApp !== GLOBALS.selfClientName) { - appApi.exitApp(GLOBALS.topmostApp); + if (GLOBALS.topmostApp !== GLOBALS.selfclientAppName) { + const targetApp = GLOBALS.topmostApp; + AppManager.get().closeApp(targetApp).then(() => { + this.LOG("closeApp success for: " + targetApp); + AppManager.get().terminateApp(targetApp).then(() => { + this.LOG("terminateApp success after closeApp for: " + targetApp); + }).catch(err => { + this.ERR("terminateApp err after closeApp: " + JSON.stringify(err)); + }); + }).catch(err => { + this.ERR("closeApp err for " + targetApp + ": " + JSON.stringify(err)); + AppManager.get().terminateApp(targetApp).then(() => { + this.LOG("terminateApp success after closeApp failure for: " + targetApp); + }).catch(termErr => { + this.ERR("terminateApp err after closeApp failure for " + targetApp + ": " + JSON.stringify(termErr)); + }); + }); } else { if (!Router.isNavigating()) { Router.navigate('menu') @@ -119,6 +134,9 @@ export default class InactivityHelper { } } }) + .catch(err => { + this.ERR("setPowerState error during standby: " + JSON.stringify(err)); + }); return true } } diff --git a/accelerator-home-ui/src/items/AppCard.js b/accelerator-home-ui/src/items/AppCard.js index 52d5582..a5badc6 100644 --- a/accelerator-home-ui/src/items/AppCard.js +++ b/accelerator-home-ui/src/items/AppCard.js @@ -64,17 +64,6 @@ class ActionButton extends Lightning.Component { this.tag('Label').text.text = text; } - set primary(isPrimary) { - this._isPrimary = isPrimary; - if (isPrimary) { - this.patch({ color: CONFIG.theme.hex }); - } - } - - get primary() { - return this._isPrimary || false; - } - set action(actionType) { this._action = actionType; } @@ -97,7 +86,7 @@ class ActionButton extends Lightning.Component { _unfocus() { this.tag('FocusIndicator').alpha = 0; this.patch({ - color: this._isPrimary ? CONFIG.theme.hex : 0xFF3D3D3D, + color: 0xFF3D3D3D, smooth: { scale: 1 } }); } @@ -193,7 +182,6 @@ export default class AppCard extends Lightning.Component { x: 0, type: ActionButton, label: Language.translate('Launch'), - primary: true, action: 'launch' }, UpdateButton: { diff --git a/accelerator-home-ui/src/items/AppCatalogItem.js b/accelerator-home-ui/src/items/AppCatalogItem.js index 5922135..af4fd2c 100644 --- a/accelerator-home-ui/src/items/AppCatalogItem.js +++ b/accelerator-home-ui/src/items/AppCatalogItem.js @@ -46,10 +46,12 @@ export const DACAppMixin = (Base) => class extends Base { if (this._app.isInstalling) { this._app.isInstalled = success this._app.isInstalling = false + const errorCode = this._app.errorCode ?? -1; if (Object.prototype.hasOwnProperty.call(this._app, "errorCode")) delete this._app.errorCode; this.updateDACStatus(statusProgressTag, overlayTag) if (!success) { this.tag(statusProgressTag).setProgress(1.0, 'Error: ' + msg) + this.fireAncestors('$showInstallError', { name: this._app.name, errorCode: errorCode }) } return true; // Installation operation completed } else if (this._app.isUnInstalling) { @@ -58,6 +60,7 @@ export const DACAppMixin = (Base) => class extends Base { this.updateDACStatus(statusProgressTag, overlayTag) if (!success) { this.tag(statusProgressTag).setProgress(1.0, 'Error: ' + msg) + this.fireAncestors('$showUninstallError', { name: this._app.name, error: msg }) } return true; // Uninstall operation completed } @@ -97,10 +100,12 @@ export const DACAppMixin = (Base) => class extends Base { } else { this.ERR("Failed to launch app: " + this._app.name) this.tag(overlayTag + '.OverlayText').text.text = Language.translate('Launch failed'); + this.fireAncestors('$showLaunchError', { name: this._app.name }); } } catch (err) { this.ERR("Error launching app: " + JSON.stringify(err)) this.tag(overlayTag + '.OverlayText').text.text = Language.translate('Launch failed'); + this.fireAncestors('$showLaunchError', { name: this._app.name, error: err.message || err }); } this.tag(overlayTag).setSmooth('alpha', 0, { duration: 5 }) return true; // Already installed @@ -114,13 +119,18 @@ export const DACAppMixin = (Base) => class extends Base { this.tag(overlayTag + '.OverlayText').alpha = 1; this.tag(overlayTag).setSmooth('alpha', 0, { duration: 5 }); + // Reset progress bar to clear any stale state from a previous install cycle + this.tag(statusProgressTag).reset(); + this._app.isInstalling = true; if (!await installDACApp(this._app, this.tag(statusProgressTag))) { this._app.isInstalling = false; - this.tag(overlayTag + '.OverlayText').text.text = Language.translate("Status") + ':' + (this._app.errorCode ?? -1); + const errorCode = this._app.errorCode ?? -1; + this.tag(overlayTag + '.OverlayText').text.text = Language.translate("Status") + ':' + errorCode; this.tag(overlayTag).alpha = 0.7 this.tag(overlayTag + '.OverlayText').alpha = 1 this.tag(overlayTag).setSmooth('alpha', 0, { duration: 5 }) + this.fireAncestors('$showInstallError', { name: this._app.name, errorCode: errorCode }); return false; } return true; diff --git a/accelerator-home-ui/src/items/DacAppItem.js b/accelerator-home-ui/src/items/DacAppItem.js index 006c604..28319c1 100644 --- a/accelerator-home-ui/src/items/DacAppItem.js +++ b/accelerator-home-ui/src/items/DacAppItem.js @@ -189,7 +189,14 @@ export default class DacAppItem extends DACAppMixin(Lightning.Component) { if (this._app.isInstalled) { this.LOG("App is already installed, launching...") // Launch the installed app - this._app.isRunning = await startDACApp(this._app); + try { + this._app.isRunning = await startDACApp(this._app); + if (!this._app.isRunning) { + this.fireAncestors('$showLaunchError', { name: this._app.name }); + } + } catch (err) { + this.fireAncestors('$showLaunchError', { name: this._app.name, error: err.message || err }); + } return } await this.performDACInstall('ImageWrapper.StatusProgress', 'ImageWrapper.Overlay'); @@ -244,6 +251,10 @@ export default class DacAppItem extends DACAppMixin(Lightning.Component) { async _handleEnter() { // Handle "More Apps" item - navigate to apps route if (this.data.applicationType === 'MoreApps') { + if (!GLOBALS.IsConnectedToInternet) { + this.fireAncestors('$showNetworkError') + return + } Router.navigate('apps'); return; } diff --git a/accelerator-home-ui/src/keyIntercept/keyIntercept.js b/accelerator-home-ui/src/keyIntercept/keyIntercept.js index d810cfb..f7ba8ba 100644 --- a/accelerator-home-ui/src/keyIntercept/keyIntercept.js +++ b/accelerator-home-ui/src/keyIntercept/keyIntercept.js @@ -26,29 +26,26 @@ const thunder = ThunderJS(CONFIG.thunderConfig); export function keyIntercept(clientName = GLOBALS.selfClientId) { return new Promise((resolve, reject) => { + const intercepts = [ + { "keyCode": Keymap.Home, "modifiers": [] }, + { "keyCode": Keymap.AudioVolumeDown, "modifiers": [] }, + { "keyCode": Keymap.AudioVolumeUp, "modifiers": [] }, + { "keyCode": Keymap.AudioVolumeMute, "modifiers": [] }, + { "keyCode": Keymap.Inputs_Shortcut, "modifiers": [] }, + { "keyCode": Keymap.Picture_Setting_Shortcut, "modifiers": [] }, + { "keyCode": Keymap.Youtube, "modifiers": [] }, + { "keyCode": Keymap.Power, "modifiers": [] }, + { "keyCode": Keymap.Amazon, "modifiers": [] }, + { "keyCode": Keymap.Netflix, "modifiers": [] }, + { "keyCode": Keymap.Settings_Shortcut, "modifiers": [] }, + { "keyCode": Keymap.Guide_Shortcut, "modifiers": [] }, + { "keyCode": Keymap.AppCarousel, "modifiers": [] }, + { "keyCode": Keymap.Escape, "modifiers": [] } + ]; RDKWindowManager.get().addKeyIntercepts( { - "intercepts":{ - "intercepts": [{ - "keys": [ - { "keyCode": Keymap.Home, "modifiers": [] }, - { "keyCode": Keymap.AudioVolumeDown, "modifiers": [] }, - { "keyCode": Keymap.AudioVolumeUp, "modifiers": [] }, - { "keyCode": Keymap.AudioVolumeMute, "modifiers": [] }, - { "keyCode": Keymap.Inputs_Shortcut, "modifiers": [] }, - { "keyCode": Keymap.Picture_Setting_Shortcut, "modifiers": [] }, - { "keyCode": Keymap.Youtube, "modifiers": [] }, - { "keyCode": Keymap.Power, "modifiers": [] }, - { "keyCode": Keymap.Amazon, "modifiers": [] }, - { "keyCode": Keymap.Netflix, "modifiers": [] }, - { "keyCode": Keymap.Settings_Shortcut, "modifiers": [] }, - { "keyCode": Keymap.Guide_Shortcut, "modifiers": [] }, - { "keyCode": Keymap.AppCarousel, "modifiers": [] }, - { "keyCode": Keymap.Escape, "modifiers": [] } - ], - "client": clientName, - }] - }, + "clientId": clientName, + "intercepts": JSON.stringify(intercepts) } ).then(result => { if (result.success) { diff --git a/accelerator-home-ui/src/overlays/NetworkScreens/NetworkInfoScreen.js b/accelerator-home-ui/src/overlays/NetworkScreens/NetworkInfoScreen.js index 5c6b251..40d59b7 100644 --- a/accelerator-home-ui/src/overlays/NetworkScreens/NetworkInfoScreen.js +++ b/accelerator-home-ui/src/overlays/NetworkScreens/NetworkInfoScreen.js @@ -290,55 +290,10 @@ export default class NetworkInfo extends Lightning.Component { this.tag("IPAddress.Value").text.text = `NA` this.tag("Gateway.Value").text.text = `NA` this.tag("MACAddress.Value").text.text = `NA` - if ("ResidentApp" === GLOBALS.selfClientName) - { - await NetworkManager.GetPrimaryInterface().then((defaultInterface) => { - console.log("defaultinterface"+defaultInterface) - NetworkManager.GetIPSettings(defaultInterface).then((result) => { - if (result.interface === "wlan0") { - this.tag("ConnectionType.Value").text.text = Language.translate("Wireless") - this.tag("SSID").alpha = 1 - this.tag("SignalStrength").alpha = 1 - NetworkManager.GetConnectedSSID().then((result) => { - if (parseInt(result.strength) >= -50) { - this.tag("SignalStrength.Value").text.text = `Excellent` - } - else if (parseInt(result.strength) >= -60) { - this.tag("SignalStrength.Value").text.text = `Good` - } - else if (parseInt(result.strength) >= -67) { - this.tag("SignalStrength.Value").text.text = `Fair` - } - else { - this.tag("SignalStrength.Value").text.text = `Poor` - } - this.tag("SSID.Value").text.text = `${result.ssid}` - }).catch((error) => console.log(error)); - } else if (result.interface === "eth0") { - this.tag("ConnectionType.Value").text.text = 'Ethernet' - this.tag("SSID").alpha = 0 - this.tag("SignalStrength").alpha = 0 - } - this.tag('InternetProtocol.Value').text.text = result.ipversion - this.tag('IPAddress.Value').text.text = result.ipaddress - this.tag("Gateway.Value").text.text = result.gateway - }).catch((err) => console.error(err)) - - NetworkManager.GetAvailableInterfaces().then((interfaces) => { - currentInterface = interfaces.filter((data) => data.name === defaultInterface) - if (currentInterface[0].connected) { - this.tag("Status.Value").text.text = Language.translate('Connected') - } - else { - this.tag('Status.Value').text.text = Language.translate('Disconnected') - } - this.tag('MACAddress.Value').text.text = currentInterface[0].mac - }).catch((error) => console.log(error)); - }).catch((error) => console.log(error)); - } - else{ - await FireBoltApi.get().deviceinfo.getnetwork().then(res=>{ - if (res.type === "wifi") { + await NetworkManager.GetPrimaryInterface().then((defaultInterface) => { + console.log("defaultinterface"+defaultInterface) + NetworkManager.GetIPSettings(defaultInterface).then((result) => { + if (result.interface === "wlan0") { this.tag("ConnectionType.Value").text.text = Language.translate("Wireless") this.tag("SSID").alpha = 1 this.tag("SignalStrength").alpha = 1 @@ -356,34 +311,32 @@ export default class NetworkInfo extends Lightning.Component { this.tag("SignalStrength.Value").text.text = `Poor` } this.tag("SSID.Value").text.text = `${result.ssid}` - }).catch((error) => { - this.ERR("WiFi.get().getConnectedSSID error: " + JSON.stringify(error)) - }); - } else if (res.type === "ethernet") { + }).catch((error) => this.ERR("GetConnectedSSID error: " + JSON.stringify(error))); + } else if (result.interface === "eth0") { this.tag("ConnectionType.Value").text.text = 'Ethernet' this.tag("SSID").alpha = 0 this.tag("SignalStrength").alpha = 0 } - if (res.state== "connected") { + this.tag('InternetProtocol.Value').text.text = result.ipversion + this.tag('IPAddress.Value').text.text = result.ipaddress + this.tag("Gateway.Value").text.text = result.gateway + }).catch((err) => this.ERR("GetIPSettings error: " + JSON.stringify(err))) + + NetworkManager.GetAvailableInterfaces().then((interfaces) => { + const matchedInterface = interfaces.find((data) => data.name === defaultInterface) + if (!matchedInterface) { + this.ERR("Interface not found for: " + defaultInterface) + return + } + if (matchedInterface.connected) { this.tag("Status.Value").text.text = Language.translate('Connected') } else { this.tag('Status.Value').text.text = Language.translate('Disconnected') } - NetworkManager.GetPrimaryInterface().then((defaultInterface) => { - NetworkManager.GetIPSettings(defaultInterface).then((result) => { - this.tag('InternetProtocol.Value').text.text = result.ipversion - this.tag('IPAddress.Value').text.text = result.ipaddress - this.tag("Gateway.Value").text.text = result.gateway - }) - NetworkManager.GetAvailableInterfaces().then((res) => { - currentInterface = res.interfaces.filter((data) => data.type === defaultInterface) - this.tag('MACAddress.Value').text.text = currentInterface[0].mac - }).catch((error) => console.log(error)); - }) - - }).catch((error) => console.log(error)); - } + this.tag('MACAddress.Value').text.text = matchedInterface.mac + }).catch((error) => this.ERR("GetAvailableInterfaces error: " + JSON.stringify(error))); + }).catch((error) => this.ERR("GetPrimaryInterface error: " + JSON.stringify(error))); } _focus() { diff --git a/accelerator-home-ui/src/overlays/OtherSettings/LanguageScreenOverlay.js b/accelerator-home-ui/src/overlays/OtherSettings/LanguageScreenOverlay.js index 19bcf30..b44ebf0 100644 --- a/accelerator-home-ui/src/overlays/OtherSettings/LanguageScreenOverlay.js +++ b/accelerator-home-ui/src/overlays/OtherSettings/LanguageScreenOverlay.js @@ -20,15 +20,10 @@ import { Language, Lightning } from '@lightningjs/sdk' import LanguageItem from '../../items/LanguageItem' import { availableLanguages, availableLanguageCodes } from '../../Config/Config' import AppApi from '../../api/AppApi'; -import RDKShellApis from '../../api/RDKShellApis'; -import thunderJS from 'ThunderJS'; -import { CONFIG, GLOBALS } from '../../Config/Config' -import { Metrics } from '@firebolt-js/sdk'; -import FireBoltApi from '../../api/firebolt/FireBoltApi'; + + const appApi = new AppApi() -const thunder = thunderJS(CONFIG.thunderConfig) -const loader = 'Loader' export default class LanguageScreen extends Lightning.Component { constructor(...args) { @@ -74,17 +69,6 @@ export default class LanguageScreen extends Lightning.Component { item: item, } }) - RDKShellApis.destroy(loader).catch(err => { - this.ERR("LanguageScreenOverlay: Error destroy loader: " + JSON.stringify(err)) - }); - RDKShellApis.setVisibility(GLOBALS.selfClientName, true); - RDKShellApis.moveToFront(GLOBALS.selfClientName); - RDKShellApis.setFocus(GLOBALS.selfClientName).then(() => { - this.LOG('LanguageScreenOverlay: ResidentApp moveToFront Success'); - }).catch(err => { - this.ERR('LanguageScreenOverlay: Error: ' + JSON.stringify(err)); - Metrics.error(Metrics.ErrorType.OTHER, "PluginError", "Thunder RDKShell Failed to moveToFront " + JSON.stringify(err), false, null) - }); } _focus() { @@ -109,20 +93,8 @@ export default class LanguageScreen extends Lightning.Component { //need to verify if (Language.get() !== availableLanguages[this._Languages.tag('List').index]) { let updatedLanguage = availableLanguageCodes[availableLanguages[this._Languages.tag('List').index]] - if ("ResidentApp" !== GLOBALS.selfClientName) { - FireBoltApi.get().localization.setlanguage(availableLanguages[this._Languages.tag('List').index]).then(res => this.LOG("language set successfully")) - } else { - appApi.setUILanguage(updatedLanguage) - } + appApi.setUILanguage(updatedLanguage) localStorage.setItem('Language',availableLanguages[this._Languages.tag('List').index]) - let path = location.pathname.split('index.html')[0] - let url = path.slice(-1) === '/' ? "static/loaderApp/index.html" : "/static/loaderApp/index.html" - let notification_url = location.origin + path + url - this.LOG(notification_url) - appApi.launchResident(notification_url, loader).catch(err => { - this.ERR("Error launchResident: " + JSON.stringify(err)) - }) - RDKShellApis.setVisibility(GLOBALS.selfClientName, false) location.reload(); } } diff --git a/accelerator-home-ui/src/overlays/StatusProgress.js b/accelerator-home-ui/src/overlays/StatusProgress.js index 532c27f..168e3f5 100644 --- a/accelerator-home-ui/src/overlays/StatusProgress.js +++ b/accelerator-home-ui/src/overlays/StatusProgress.js @@ -66,6 +66,7 @@ export default class Progress extends lng.Component { var ww = (this.w - 4) * pc if(pc != 1.0) { this.tag("BackgroundOverlay").alpha=0.6 + this.tag("Label").alpha = 1.0 this.tag("ProgressBar").setSmooth('alpha', 0.7, {duration: .1}) this.tag("Progress").setSmooth('w', ww, { duration: 1 }) } diff --git a/accelerator-home-ui/src/overlays/UninstallConfirmation.js b/accelerator-home-ui/src/overlays/UninstallConfirmation.js new file mode 100644 index 0000000..cc146d6 --- /dev/null +++ b/accelerator-home-ui/src/overlays/UninstallConfirmation.js @@ -0,0 +1,314 @@ +/** + * If not stated otherwise in this file or this component's LICENSE + * file the following copyright and licenses apply: + * + * Copyright 2020 RDK Management + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ +import { Lightning, Utils, Language } from "@lightningjs/sdk"; +import { CONFIG } from "../Config/Config"; + +/** + * Class for Uninstall Confirmation Overlay Component. + */ +export default class UninstallConfirmation extends Lightning.Component { + static _template() { + return { + rect: true, + w: 1920, + h: 1080, + color: 0xCC000000, // Semi-transparent black background + zIndex: 10, + UninstallDialog: { + x: 960, + y: 540, + mount: 0.5, + rect: true, + w: 620, + h: 320, + color: 0xFF1A1A1A, + shader: { + type: Lightning.shaders.RoundedRectangle, + radius: 16, + }, + DialogBorder: { + x: -2, + y: -2, + w: 624, + h: 324, + rect: true, + color: 0x00000000, + shader: { + type: Lightning.shaders.RoundedRectangle, + radius: 18, + stroke: 2, + strokeColor: 0xFF3D3D3D, + }, + }, + Title: { + x: 310, + y: 40, + mountX: 0.5, + text: { + text: Language.translate("Uninstall"), + fontFace: CONFIG.language.font, + fontSize: 36, + textColor: CONFIG.theme.hex, + fontStyle: "bold", + }, + }, + BorderTop: { + x: 30, + y: 90, + w: 560, + h: 2, + rect: true, + color: 0xFF3D3D3D, + }, + Info: { + x: 310, + y: 130, + mountX: 0.5, + text: { + text: Language.translate("Are you sure you want to uninstall this app?"), + fontFace: CONFIG.language.font, + fontSize: 24, + textColor: 0xFFCCCCCC, + textAlign: "center", + wordWrapWidth: 520, + }, + }, + AppName: { + x: 310, + y: 170, + mountX: 0.5, + text: { + text: "", + fontFace: CONFIG.language.font, + fontSize: 22, + textColor: 0xFFAAAAAA, + textAlign: "center", + wordWrapWidth: 520, + }, + }, + Buttons: { + x: 310, + y: 230, + mountX: 0.5, + w: 440, + h: 50, + Confirm: { + x: 0, + w: 200, + h: 50, + rect: true, + color: 0xFFFFFFFF, + shader: { + type: Lightning.shaders.RoundedRectangle, + radius: 8, + }, + Title: { + x: 100, + y: 25, + mount: 0.5, + text: { + text: Language.translate("Confirm"), + fontFace: CONFIG.language.font, + fontSize: 22, + textColor: 0xFF000000, + }, + }, + }, + Cancel: { + x: 220, + w: 200, + h: 50, + rect: true, + color: 0xFF7D7D7D, + shader: { + type: Lightning.shaders.RoundedRectangle, + radius: 8, + }, + Title: { + x: 100, + y: 25, + mount: 0.5, + text: { + text: Language.translate("Cancel"), + fontFace: CONFIG.language.font, + fontSize: 22, + textColor: 0xFF000000, + }, + }, + }, + }, + Loader: { + x: 310, + y: 160, + mountX: 0.5, + w: 90, + h: 90, + zIndex: 2, + src: Utils.asset("images/settings/Loading.png"), + visible: false, + }, + }, + }; + } + + /** + * Set the app info for the uninstall confirmation + * @param {Object} appInfo - App data (id, name, version, etc.) + */ + set appInfo(data) { + this._appInfo = data; + const appName = data.name || data.appName || "Unknown App"; + this.tag("UninstallDialog.AppName").text.text = `"${appName}"`; + } + + get appInfo() { + return this._appInfo; + } + + _focus() { + this._setState("Confirm"); + + this.loadingAnimation = this.tag("UninstallDialog.Loader").animation({ + duration: 3, + repeat: -1, + stopMethod: "immediate", + stopDelay: 0.2, + actions: [{ p: "rotation", v: { sm: 0, 0: 0, 1: 2 * Math.PI } }], + }); + } + + /** + * Safety-net cleanup when the overlay loses focus (e.g. parent hides or + * navigates away). Ensures the loader animation is stopped and the dialog + * UI is restored to its default state even if no explicit state transition + * (Uninstalling → Confirm) was triggered before dismissal. + */ + _unfocus() { + if (this.loadingAnimation && this.loadingAnimation.isActive()) { + this.loadingAnimation.stop(); + } + this.tag("UninstallDialog.Loader").visible = false; + this.tag("UninstallDialog.Title").text.text = Language.translate("Uninstall"); + this.tag("UninstallDialog.Buttons").visible = true; + this.tag("UninstallDialog.Info").visible = true; + this.tag("UninstallDialog.AppName").visible = true; + } + + static _states() { + return [ + class Confirm extends this { + $enter() { + this._focus(); + } + _handleEnter() { + this.fireAncestors("$confirmUninstall", this._appInfo); + } + _handleRight() { + this._setState("Cancel"); + } + _handleBack() { + this.fireAncestors("$cancelUninstall"); + } + _focus() { + this.tag("Buttons.Confirm").patch({ + color: CONFIG.theme.hex, + }); + this.tag("Buttons.Confirm.Title").patch({ + text: { textColor: 0xFFFFFFFF }, + }); + } + _unfocus() { + this.tag("Buttons.Confirm").patch({ + color: 0xFFFFFFFF, + }); + this.tag("Buttons.Confirm.Title").patch({ + text: { textColor: 0xFF000000 }, + }); + } + $exit() { + this._unfocus(); + } + }, + class Cancel extends this { + $enter() { + this._focus(); + } + _handleEnter() { + this.fireAncestors("$cancelUninstall"); + } + _handleLeft() { + this._setState("Confirm"); + } + _handleBack() { + this.fireAncestors("$cancelUninstall"); + } + _focus() { + this.tag("Buttons.Cancel").patch({ + color: CONFIG.theme.hex, + }); + this.tag("Buttons.Cancel.Title").patch({ + text: { textColor: 0xFFFFFFFF }, + }); + } + _unfocus() { + this.tag("Buttons.Cancel").patch({ + color: 0xFF7D7D7D, + }); + this.tag("Buttons.Cancel.Title").patch({ + text: { textColor: 0xFF000000 }, + }); + } + $exit() { + this._unfocus(); + } + }, + class Uninstalling extends this { + $enter() { + this.loadingAnimation.start(); + this.tag("UninstallDialog.Loader").visible = true; + this.tag("UninstallDialog.Title").text.text = Language.translate("Uninstalling") + "..."; + this.tag("UninstallDialog.Buttons").visible = false; + this.tag("UninstallDialog.Info").visible = false; + this.tag("UninstallDialog.AppName").visible = false; + } + $exit() { + this.loadingAnimation.stop(); + this.tag("UninstallDialog.Loader").visible = false; + this.tag("UninstallDialog.Title").text.text = Language.translate("Uninstall"); + this.tag("UninstallDialog.Buttons").visible = true; + this.tag("UninstallDialog.Info").visible = true; + this.tag("UninstallDialog.AppName").visible = true; + } + _handleEnter() { /* do nothing */ } + _handleLeft() { /* do nothing */ } + _handleRight() { /* do nothing */ } + _handleBack() { /* do nothing */ } + _handleUp() { /* do nothing */ } + _handleDown() { /* do nothing */ } + }, + ]; + } + + /** + * Show the uninstalling state with loader + */ + showUninstalling() { + this._setState("Uninstalling"); + } +} diff --git a/accelerator-home-ui/src/routes/networkRoutes.js b/accelerator-home-ui/src/routes/networkRoutes.js index 1f8e091..a262b47 100644 --- a/accelerator-home-ui/src/routes/networkRoutes.js +++ b/accelerator-home-ui/src/routes/networkRoutes.js @@ -26,6 +26,7 @@ import NetworkInterfaceScreen from "../screens/OtherSettingsScreens/NetworkInter import WifiPairingScreen from "../screens/WiFiPairingScreen" import WiFiScreen from "../screens/WifiScreen" import RCVolumeInfoScreen from '../screens/RcInformationScreen' +import AppCatalogLoginComponent from '../screens/AppCatalogLoginComponent' const networkRoutes = [ { @@ -72,6 +73,11 @@ const networkRoutes = [ path: 'settings/bluetooth/RCVolumeInfoScreen', component: RCVolumeInfoScreen, widgets: ["Menu",'Volume', "Fail","AppCarousel"] + }, + { + path: 'settings/appcataloglogin', + component: AppCatalogLoginComponent, + widgets: ['Volume', 'AppCarousel'] } ] diff --git a/accelerator-home-ui/src/routes/routes.js b/accelerator-home-ui/src/routes/routes.js index bafef6c..dd67e76 100644 --- a/accelerator-home-ui/src/routes/routes.js +++ b/accelerator-home-ui/src/routes/routes.js @@ -101,12 +101,12 @@ export default { { path: 'apps', component: AppStore, - widgets: ['Menu', 'Volume', "AppCarousel"] + widgets: ['Menu', 'FailOk', 'Volume', "AppCarousel"] }, { path: 'appinfo', component: AppInfoPage, - widgets: ['Menu', 'Volume', "AppCarousel"] + widgets: ['Menu', 'FailOk', 'Volume', "AppCarousel"] }, { path: 'usb/player', @@ -140,7 +140,7 @@ export default { } return Promise.resolve() }, - widgets: ['Menu', 'Fail', 'Volume','MiracastNotification', "AppCarousel", "VideoInfoChange"], + widgets: ['Menu', 'Fail', 'FailOk', 'Volume','MiracastNotification', "AppCarousel", "VideoInfoChange"], }, { path: 'tv-overlay/:type', @@ -207,7 +207,7 @@ export default { if ("ResidentApp" !== GLOBALS.selfClientName) { Metrics.page(request.hash) .then(success => { - console.log("successfully routed to page ==>", request.hash) + console.log("successfully routed to page ==>" + JSON.stringify(request.hash)) }) .catch(err => console.log("error in metrics.page", err)) } diff --git a/accelerator-home-ui/src/screens/AppCatalogLoginComponent.js b/accelerator-home-ui/src/screens/AppCatalogLoginComponent.js new file mode 100644 index 0000000..98a991b --- /dev/null +++ b/accelerator-home-ui/src/screens/AppCatalogLoginComponent.js @@ -0,0 +1,688 @@ +/** + * If not stated otherwise in this file or this component's LICENSE + * file the following copyright and licenses apply: + * + * Copyright 2020 RDK Management + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ +import { Language, Lightning, Router, Utils } from '@lightningjs/sdk' +import { CONFIG } from '../Config/Config'; +import { Keyboard } from '../ui-components/index' +import { KEYBOARD_FORMATS } from '../ui-components/components/Keyboard' +import PasswordSwitch from './PasswordSwitch'; +import { login, getCatalogServerURL } from '../api/AppCatalog'; + +export default class AppCatalogLoginComponent extends Lightning.Component { + + constructor(...args) { + super(...args); + this.INFO = console.info; + this.LOG = console.log; + this.ERR = console.error; + this.WARN = console.warn; + } + + pageTransition() { + return 'left' + } + + _active() { + this.hidePasswd = true + this.star = "" + this.catalogURL = null + this.catalogURLState = 'loading' + this.tag('CatalogURLValue').text.text = Language.translate('Loading...') + this.tag("Keyboard").visible = false + getCatalogServerURL() + .then(url => { + this.catalogURL = url || null + this.catalogURLState = url ? 'loaded' : 'not-set' + this.tag('CatalogURLValue').text.text = url || Language.translate('Unknown') + }) + .catch(() => { + this.catalogURL = null + this.catalogURLState = 'error' + this.tag('CatalogURLValue').text.text = Language.translate('Unavailable') + }) + } + + _firstEnable() { + this.spinnerAnimation = this.tag('LoadingOverlay.Spinner').animation({ + duration: 3, + repeat: -1, + stopMethod: 'immediate', + stopDelay: 0.2, + actions: [{ p: 'rotation', v: { sm: 0, 0: 0, 1: Math.PI * 2 } }], + }) + } + + _updateConnectButtonColor() { + if (this.textCollection && this.textCollection['EnterUsername'] && this.textCollection['EnterPassword']) { + this.tag('ConnectButton').color = 0xff00aa00 + } else { + this.tag('ConnectButton').color = 0xff444444 + } + } + + handleDone() { + this.tag("Keyboard").visible = false + if (!this.textCollection['EnterUsername']) { + this._setState("EnterUsername"); + } else if (!this.textCollection['EnterPassword']) { + this._setState("EnterPassword"); + } else { + this._setState("ConnectButton"); + } + } + + static _template() { + return { + Background: { + w: 1920, + h: 1080, + rect: true, + color: 0xCC000000, + }, + Text: { + x: 758, + y: 70, + text: { + text: Language.translate("Connect to the Application Catalog"), + fontFace: CONFIG.language.font, + fontSize: 35, + textColor: CONFIG.theme.hex, + }, + }, + BorderTop: { + x: 190, y: 130, w: 1488, h: 2, rect: true, + }, + CatalogURLLabel: { + x: 190, + y: 148, + text: { + text: Language.translate("App Catalog URL") + ": ", + fontFace: CONFIG.language.font, + fontSize: 22, + textColor: 0xff808080, + }, + }, + CatalogURLValue: { + x: 525, + y: 148, + text: { + text: Language.translate("Loading..."), + fontFace: CONFIG.language.font, + fontSize: 22, + textColor: 0xff808080, + wordWrapWidth: 1200, + wordWrap: false, + textOverflow: 'ellipsis', + }, + }, + Username: { + x: 190, + y: 230, + text: { + text: Language.translate("Username") + ": ", + fontFace: CONFIG.language.font, + fontSize: 25, + }, + }, + UsernameBox: { + x: 425, + y: 220, + texture: Lightning.Tools.getRoundRect(1248, 58, 0, 3, 0xffffffff, false) + }, + UsernameText: { + x: 445, + y: 230, + zIndex: 2, + text: { + text: '', + fontSize: 25, + fontFace: CONFIG.language.font, + textColor: 0xffffffff, + wordWrapWidth: 1225, + wordWrap: false, + textOverflow: 'ellipsis', + }, + }, + Password: { + x: 190, + y: 300, + text: { + text: Language.translate("Password") + ":", + fontFace: CONFIG.language.font, + fontSize: 25, + }, + }, + PasswordBox: { + x: 425, + y: 290, + texture: Lightning.Tools.getRoundRect(1248, 58, 0, 3, 0xffffffff, false) + }, + Pwd: { + x: 445, + y: 300, + zIndex: 2, + text: { + text: '', + fontSize: 25, + fontFace: CONFIG.language.font, + textColor: 0xffffffff, + wordWrapWidth: 1225, + wordWrap: false, + textOverflow: 'ellipsis', + }, + }, + BorderBottom: { + x: 190, y: 386, w: 1488, h: 2, rect: true, + }, + ExitButton: { + x: 740, + y: 410, + mountX: 0.5, + w: 200, + h: 50, + rect: true, + color: 0xff444444, + shader: { type: Lightning.shaders.RoundedRectangle, radius: 10 }, + ExitLabel: { + x: 100, + y: 25, + mount: 0.5, + text: { + text: Language.translate('Exit'), + fontFace: CONFIG.language.font, + fontSize: 22, + textColor: 0xffffffff, + }, + }, + }, + ConnectButton: { + x: 1180, + y: 410, + mountX: 0.5, + w: 200, + h: 50, + rect: true, + color: 0xff444444, + shader: { type: Lightning.shaders.RoundedRectangle, radius: 10 }, + ConnectLabel: { + x: 100, + y: 25, + mount: 0.5, + text: { + text: Language.translate('Connect'), + fontFace: CONFIG.language.font, + fontSize: 22, + textColor: 0xffffffff, + }, + }, + }, + Keyboard: { + y: 480, + x: 400, + type: Keyboard, + visible: false, + zIndex: 2, + formats: KEYBOARD_FORMATS.qwerty + }, + PasswrdSwitch: { + h: 45, + w: 66.9, + x: 1617, + y: 320, + zIndex: 2, + type: PasswordSwitch, + mount: 0.5, + visible: true + }, + ShowPassword: { + x: 1350, + y: 302, + w: 300, + h: 75, + zIndex: 2, + text: { text: Language.translate('Show Password'), fontSize: 25, fontFace: CONFIG.language.font, textColor: 0xffffffff, textAlign: 'left' }, + visible: true + }, + AuthFailedPopup: { + x: 960, + y: 540, + mount: 0.5, + w: 560, + h: 200, + rect: true, + color: 0xff222222, + shader: { type: Lightning.shaders.RoundedRectangle, radius: 12 }, + visible: false, + zIndex: 11, + PopupText: { + x: 280, + y: 60, + mountX: 0.5, + text: { + text: Language.translate('Authentication failed. Please try again.'), + fontFace: CONFIG.language.font, + fontSize: 26, + textColor: 0xffffffff, + textAlign: 'center', + wordWrapWidth: 500, + wordWrap: true, + }, + }, + OkButton: { + x: 280, + y: 145, + mountX: 0.5, + mountY: 0.5, + w: 150, + h: 46, + rect: true, + color: 0xff444444, + shader: { type: Lightning.shaders.RoundedRectangle, radius: 10 }, + OkLabel: { + x: 75, + y: 23, + mount: 0.5, + text: { + text: Language.translate('OK'), + fontFace: CONFIG.language.font, + fontSize: 22, + textColor: 0xffffffff, + }, + }, + }, + }, + URLNotSetPopup: { + x: 960, + y: 540, + mount: 0.5, + w: 560, + h: 200, + rect: true, + color: 0xff222222, + shader: { type: Lightning.shaders.RoundedRectangle, radius: 12 }, + visible: false, + zIndex: 11, + PopupText: { + x: 280, + y: 60, + mountX: 0.5, + text: { + text: Language.translate('App Catalog URL is not set'), + fontFace: CONFIG.language.font, + fontSize: 26, + textColor: 0xffffffff, + textAlign: 'center', + wordWrapWidth: 500, + wordWrap: true, + }, + }, + OkButton: { + x: 280, + y: 145, + mountX: 0.5, + mountY: 0.5, + w: 150, + h: 46, + rect: true, + color: 0xff444444, + shader: { type: Lightning.shaders.RoundedRectangle, radius: 10 }, + OkLabel: { + x: 75, + y: 23, + mount: 0.5, + text: { + text: Language.translate('OK'), + fontFace: CONFIG.language.font, + fontSize: 22, + textColor: 0xffffffff, + }, + }, + }, + }, + LoadingOverlay: { + w: 1920, + h: 1080, + rect: true, + color: 0xCC000000, + visible: false, + zIndex: 10, + Spinner: { + x: 920, + y: 490, + w: 80, + h: 80, + mount: 0.5, + src: Utils.asset('images/settings/Loading.png'), + }, + AuthText: { + x: 960, + y: 550, + mountX: 0.5, + text: { + text: Language.translate('Authenticating...'), + fontFace: CONFIG.language.font, + fontSize: 28, + textColor: 0xffffffff, + }, + }, + }, + } + } + + _focus() { + this._setState('EnterUsername'); + this.textCollection = { 'EnterUsername': '', 'EnterPassword': '' } + this.tag('Pwd').text.text = Language.translate("Press OK to enter Password"); + this.tag("UsernameText").text.text = Language.translate("Press OK to enter Username"); + this.tag('UsernameText').text.textColor = 0xff808080 + this.tag('Pwd').text.textColor = 0xff808080 + this._updateConnectButtonColor() + } + + encrypt() { + if (this.prevState === "EnterPassword" && this.hidePasswd) + return true + else + return false + } + + _updateText(txt) { + this.tag("Pwd").text.text = txt; + } + + _handleBack() { + if (!Router.isNavigating()) { + Router.back() + } + } + + static _states() { + return [ + class EnterUsername extends this { + $enter() { + this.tag('UsernameBox').texture = Lightning.Tools.getRoundRect(1248, 58, 0, 3, CONFIG.theme.hex, false) + } + _handleDown() { + this._setState("EnterPassword"); + } + _handleEnter() { + this._setState('Keyboard') + this.tag('UsernameText').text.text = this.textCollection['EnterUsername'] + this.tag('UsernameText').text.textColor = 0xffffffff + this.tag("Keyboard").visible = true + } + $exit() { + this.tag('UsernameBox').texture = Lightning.Tools.getRoundRect(1248, 58, 0, 3, 0xffffffff, false) + } + }, + class EnterPassword extends this { + $enter() { + this.tag('PasswordBox').texture = Lightning.Tools.getRoundRect(1248, 58, 0, 3, CONFIG.theme.hex, false) + } + _handleUp() { + this._setState("EnterUsername"); + } + _handleDown() { + this._setState("ExitButton"); + } + _handleRight() { + this._setState("PasswordSwitchState") + } + _handleEnter() { + this.tag("Keyboard").visible = true + this._setState('Keyboard') + this.tag('Pwd').text.text = this.hidePasswd ? this.star : this.textCollection['EnterPassword'] + this.tag('Pwd').text.textColor = 0xffffffff + } + $exit() { + this.tag('PasswordBox').texture = Lightning.Tools.getRoundRect(1248, 58, 0, 3, 0xffffffff, false); + } + }, + class PasswordSwitchState extends this { + $enter() { + this.tag("PasswordBox").texture = Lightning.Tools.getRoundRect(1248, 58, 0, 3, CONFIG.theme.hex, false) + this.tag('ShowPassword').text.textColor = CONFIG.theme.hex + } + _handleDown() { + this._setState("ExitButton"); + } + _handleUp() { + this._setState("EnterUsername"); + } + _handleLeft() { + this._setState("EnterPassword"); + } + _getFocused() { + return this.tag('PasswrdSwitch'); + } + + $handleEnter(bool) { + if (bool) { + this._updateText(this.textCollection['EnterPassword']) + this.hidePasswd = false; + } + else { + this._updateText(this.star); + this.hidePasswd = true; + } + this.isOn = bool; + } + + $exit() { + this.tag("PasswordBox").texture = Lightning.Tools.getRoundRect(1248, 58, 0, 3, 0xffffffff, false) + this.tag('ShowPassword').text.textColor = 0xffffffff + } + }, + class ExitButton extends this { + $enter() { + this.tag('ExitButton').color = CONFIG.theme.hex + } + $exit() { + this.tag('ExitButton').color = 0xff444444 + } + _handleUp() { + this._setState('EnterPassword') + } + _handleDown() { + this._setState('EnterUsername') + } + _handleRight() { + this._setState('ConnectButton') + } + _handleEnter() { + if (!Router.isNavigating()) { + Router.back() + } + } + }, + class ConnectButton extends this { + $enter() { + this.tag('ConnectButton').color = (this.textCollection['EnterUsername'] && this.textCollection['EnterPassword']) + ? 0xff00cc00 + : 0xff444444 + } + $exit() { + this._updateConnectButtonColor() + } + _handleUp() { + this._setState('EnterPassword') + } + _handleDown() { + this._setState('EnterUsername') + } + _handleLeft() { + this._setState('ExitButton') + } + _handleEnter() { + this.tag('Keyboard').visible = false + if (this.catalogURLState === 'loading') { + this.LOG('Catalog URL still loading, please wait...') + return + } + if (this.catalogURLState === 'error' || this.catalogURLState === 'not-set' || !this.catalogURL) { + this._setState('URLNotSetPopup') + return + } + if (!this.textCollection['EnterUsername']) { + this._setState('EnterUsername') + return + } + if (!this.textCollection['EnterPassword']) { + this._setState('EnterPassword') + return + } + this._setState('Authenticating') + login(this.textCollection['EnterUsername'], this.textCollection['EnterPassword']) + .then(result => { + if (result) { + this.LOG('Login successful - navigating to menu') + if (!Router.isNavigating()) { + Router.navigate('menu') + } + } else { + this.ERR('Login failed') + setTimeout(() => this._setState('AuthFailedPopup'), 0) + } + }) + .catch(err => { + this.ERR('Login error: ' + err) + setTimeout(() => this._setState('AuthFailedPopup'), 0) + }) + } + }, + class AuthFailedPopup extends this { + $enter() { + this.tag('AuthFailedPopup').visible = true + this.tag('AuthFailedPopup.OkButton').color = CONFIG.theme.hex + } + $exit() { + this.tag('AuthFailedPopup').visible = false + this.tag('AuthFailedPopup.OkButton').color = 0xff444444 + } + _handleEnter() { + this._setState('ConnectButton') + } + _handleBack() { + this._setState('ConnectButton') + } + _handleUp() {} + _handleDown() {} + _handleLeft() {} + _handleRight() {} + }, + class URLNotSetPopup extends this { + $enter() { + this.tag('URLNotSetPopup').visible = true + this.tag('URLNotSetPopup.OkButton').color = CONFIG.theme.hex + const msg = this.catalogURLState === 'error' + ? Language.translate('Unable to retrieve App Catalog URL') + : Language.translate('App Catalog URL is not set') + this.tag('URLNotSetPopup.PopupText').text.text = msg + } + $exit() { + this.tag('URLNotSetPopup').visible = false + this.tag('URLNotSetPopup.OkButton').color = 0xff444444 + } + _handleEnter() { + this._setState('ConnectButton') + } + _handleBack() { + this._setState('ConnectButton') + } + _handleUp() {} + _handleDown() {} + _handleLeft() {} + _handleRight() {} + }, + class Authenticating extends this { + $enter() { + this.tag('LoadingOverlay').visible = true + this.spinnerAnimation.start() + } + $exit() { + this.spinnerAnimation.stop() + this.tag('LoadingOverlay').visible = false + } + _handleEnter() {} + _handleBack() {} + _handleUp() {} + _handleDown() {} + _handleLeft() {} + _handleRight() {} + }, + class Keyboard extends this { + $enter(state) { + this.prevState = state.prevState + if (this.prevState === 'EnterUsername') { + this.element = 'UsernameText' + } + if (this.prevState === 'EnterPassword') { + this.element = 'Pwd' + } + } + _getFocused() { + return this.tag('Keyboard') + } + + $onSoftKey({ key }) { + if (this.prevState === 'PasswordSwitchState') { + this.prevState = "EnterPassword" + } + this.LOG("Prev state: " + JSON.stringify(this.prevState)) + if (key === 'Done') { + this.handleDone(); + } else if (key === 'Clear') { + this.textCollection[this.prevState] = this.textCollection[this.prevState].substring(0, this.textCollection[this.prevState].length - 1); + this.star = (this.prevState === "EnterPassword") ? this.star.substring(0, this.star.length - 1) : this.star + this.tag(this.element).text.text = this.encrypt() ? this.star : this.textCollection[this.prevState]; + } else if (key === '#@!' || key === 'abc' || key === 'áöû' || key === 'shift') { + this.LOG('no saving') + } else if (key === 'Space') { + this.textCollection[this.prevState] += ' ' + this.star += (this.prevState === "EnterPassword") ? '\u25CF' : '' + this.tag(this.element).text.text = this.encrypt() ? this.star : this.textCollection[this.prevState]; + } else if (key === 'Delete') { + this.textCollection[this.prevState] = '' + this.star = (this.prevState === "EnterPassword") ? '' : this.star + this.tag(this.element).text.text = this.encrypt() ? this.star : this.textCollection[this.prevState]; + } else { + this.textCollection[this.prevState] += key + this.star += (this.prevState === "EnterPassword") ? '\u25CF' : '' + this.tag(this.element).text.text = this.encrypt() ? this.star : this.textCollection[this.prevState]; + } + this._updateConnectButtonColor() + } + _handleUp() { + this._setState(this.prevState) + } + + _handleBack() { + this._setState(this.prevState) + } + } + ] + } + + _init() { + this.star = '' + this.textCollection = { 'EnterUsername': '', 'EnterPassword': '' } + this.tag("Pwd").text.text = this.textCollection['EnterPassword'] + this.tag("UsernameText").text.text = this.textCollection['EnterUsername'] + this.tag('ConnectButton').color = 0xff444444 + } +} diff --git a/accelerator-home-ui/src/screens/FailAndOkScreen.js b/accelerator-home-ui/src/screens/FailAndOkScreen.js new file mode 100644 index 0000000..1ccf42a --- /dev/null +++ b/accelerator-home-ui/src/screens/FailAndOkScreen.js @@ -0,0 +1,123 @@ +/** + * If not stated otherwise in this file or this component's LICENSE + * file the following copyright and licenses apply: + * + * Copyright 2020 RDK Management + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ +import { Language, Lightning, Router } from "@lightningjs/sdk"; +import { CONFIG } from '../Config/Config' + +const errorTitle = 'Error Title' +const errorMsg = 'Error Message' +export default class FailAndOkScreen extends Lightning.Component { + + constructor(...args) { + super(...args); + this.INFO = console.info; + this.LOG = console.log; + this.ERR = console.error; + this.WARN = console.warn; + } + + notify(args) { + this.LOG("notify args: " + JSON.stringify(args)) + if (args.title && args.msg) { + this.tag('FailScreen.Title').text.text = args.title + this.tag('FailScreen.Message').text.text = args.msg + } + } + + pageTransition() { + return 'left' + } + + _focus() { + this.LOG("FailAndOkScreen _focus() called, alpha before: " + this.alpha) + this.alpha = 1 + this.LOG("FailAndOkScreen _focus() alpha set to 1") + this.tag('FailScreen.OkButton').color = CONFIG.theme.hex + this.tag('FailScreen.OkButton.OkLabel').text.textColor = 0xFFFFFFFF + } + + _unfocus() { + this.alpha = 0 + this.tag('FailScreen.Title').text.text = errorTitle + this.tag('FailScreen.Message').text.text = errorMsg + this.tag('FailScreen.OkButton').color = 0xFFFFFFFF + this.tag('FailScreen.OkButton.OkLabel').text.textColor = 0xFF000000 + } + + static _template() { + return { + alpha: 0, + w: 1920, + h: 1080, + rect: true, + color: 0xcc000000, + FailScreen: { + x: 960, + y: 300, + Title: { + mountX: 0.5, + text: { + text: errorTitle, + fontFace: CONFIG.language.font, + fontSize: 40, + textColor: CONFIG.theme.hex, + }, + }, + BorderTop: { + x: 0, y: 75, w: 1558, h: 3, rect: true, mountX: 0.5, + }, + Message: { + x: 0, + y: 125, + mountX: 0.5, + text: { + text: errorMsg, + fontFace: CONFIG.language.font, + fontSize: 25, + }, + }, + OkButton: { + x: 0, y: 200, w: 200, mountX: 0.5, h: 50, rect: true, color: 0xFFFFFFFF, + OkLabel: { + x: 100, + y: 25, + mount: 0.5, + text: { + text: Language.translate("OK"), + fontFace: CONFIG.language.font, + fontSize: 25, + textColor: 0xFF000000, + }, + }, + }, + BorderBottom: { + x: 0, y: 300, w: 1558, h: 3, rect: true, mountX: 0.5, + }, + }, + }; + } + + _handleEnter() { + Router.focusPage() + } + + _handleBack() { + Router.focusPage() + } + +} diff --git a/accelerator-home-ui/src/screens/OtherSettingsScreens/FactoryResetConfirmationScreen.js b/accelerator-home-ui/src/screens/OtherSettingsScreens/FactoryResetConfirmationScreen.js index 730d7fb..2e0c760 100644 --- a/accelerator-home-ui/src/screens/OtherSettingsScreens/FactoryResetConfirmationScreen.js +++ b/accelerator-home-ui/src/screens/OtherSettingsScreens/FactoryResetConfirmationScreen.js @@ -18,16 +18,12 @@ **/ import { Lightning, Utils, Router, Language } from '@lightningjs/sdk' import AppApi from '../../api/AppApi' -import BluetoothApi from '../../api/BluetoothApi' import { CONFIG,GLOBALS } from '../../Config/Config' -import WiFi from '../../api/WifiApi' -import NetworkManager from '../../api/NetworkManagerAPI.js' import AlexaApi from '../../api/AlexaApi.js'; import RCApi from '../../api/RemoteControl' import Warehouse from '../../api/WarehouseApis.js' const appApi = new AppApi() -const _btApi = new BluetoothApi() /** * Class for Reboot Confirmation Screen. @@ -126,10 +122,6 @@ export default class RebootConfirmationScreen extends Lightning.Component { } } - _init() { - this.AppApi = new AppApi() - } - _focus() { this._setState('Confirm') this.loadingAnimation = this.tag('Loader').animation({ @@ -140,12 +132,16 @@ export default class RebootConfirmationScreen extends Lightning.Component { _firstEnable() { - this.AppApi.checkStatus(Warehouse.get().callsign).then(resp => { - this.LOG("FactoryReset: warehouse plugin status : " + JSON.stringify(resp[0].status)); - if (resp[0].status != 'activated') { - Warehouse.get().activate().catch(err => { - this.ERR("FactoryReset: warehouse plugin activation failed; feature may not work." + JSON.stringify(err)); - }); + appApi.checkStatus(Warehouse.get().callsign).then(resp => { + if (resp && resp[0] && resp[0].state) { + this.LOG("FactoryReset: warehouse plugin state: " + JSON.stringify(resp[0].state)); + if (resp[0].state !== 'activated') { + Warehouse.get().activate().catch(err => { + this.ERR("FactoryReset: warehouse plugin activation failed; feature may not work." + JSON.stringify(err)); + }); + } + } else { + this.WARN("FactoryReset: unexpected checkStatus response: " + JSON.stringify(resp)); } }); } @@ -161,62 +157,44 @@ export default class RebootConfirmationScreen extends Lightning.Component { AlexaApi.get().disableSmartScreen(); if(GLOBALS.AlexaAvsstatus){AlexaApi.get().resetAVSCredentials();} AlexaApi.get().setAlexaAuthStatus("AlexaAuthPending"); - let getsuportedmode = await appApi.getSupportedAudioPorts(); - for (let i = 0; i < getsuportedmode.supportedAudioPorts.length; i++) { - if(getsuportedmode.supportedAudioPorts[i] != 'SPDIF0'){ - let rsbass = await appApi.resetBassEnhancer(getsuportedmode.supportedAudioPorts[i]).catch((err) =>{ this.ERR("resetBassEnhancer" + JSON.stringify(err)) }); - if (rsbass.success != true) { this.LOG("resetBassEnhancer" + JSON.stringify(rsbass)) } - let rsDialog = await appApi.resetDialogEnhancement(getsuportedmode.supportedAudioPorts[i]).catch((err) =>{ this.ERR("resetDialogEnhancement" + JSON.stringify(err)) }) - if (rsDialog.success != true) { this.LOG("resetDialogEnhancement" + JSON.stringify(rsDialog)) } - let rsVirtualizer = await appApi.resetSurroundVirtualizer(getsuportedmode.supportedAudioPorts[i]).catch(err =>{ this.ERR("resetSurroundVirtualizer" + JSON.stringify(err)) }); - if (rsVirtualizer.success != true) { this.LOG("resetSurroundVirtualizer" + JSON.stringify(rsVirtualizer)) } - let rsvolumelvel = await appApi.resetVolumeLeveller(getsuportedmode.supportedAudioPorts[i]).catch(err =>{ this.ERR("resetVolumeLeveller" + JSON.stringify(err)) }); - if (rsvolumelvel.success != true) { this.LOG("resetVolumeLeveller" + JSON.stringify(rsvolumelvel)) } - } - } - let btActivate = await _btApi.btactivate().then(result => this.LOG("Btactivate" + JSON.stringify(result))).catch(err=> this.ERR("error while activating bluetooth")) - let getPairedDevices = await _btApi.getPairedDevices().then(res=>res).catch(err => 0) - this.LOG("getpairedDevices" + JSON.stringify(getPairedDevices)) - for(let i=0 ; i 0){ - let btunpair = await _btApi.unpair(getPairedDevices[i].deviceId).catch(err => { this.ERR("btunpair" + JSON.stringify(err)) }); - if(btunpair.success != true){ this.LOG("btunpair" + JSON.stringify(btunpair)) } - } - } - await RCApi.get().activate().then(()=>{ RCApi.get().factoryReset(); }).catch(err => this.ERR("error while resetting remote control" + JSON.stringify(err))); - let contollerStat = await appApi.checkStatus("Monitor") - for(let i=0; i< contollerStat[0].configuration.observables.length; i++){ - let monitorstat = await appApi.monitorStatus(contollerStat[0].configuration.observables[i].callsign).catch(err =>{ this.ERR("monitorStatus" + JSON.stringify(err)) }); - if(monitorstat.length < 0){ this.LOG("monitorStatus" + JSON.stringify(monitorstat)) } - } - await Warehouse.get().internalReset().catch(err => { this.ERR("internalReset" + JSON.stringify(err)) }); - await Warehouse.get().isClean().catch(err => { this.ERR("isClean" + JSON.stringify(err)) }); - await Warehouse.get().lightReset().catch(err => { this.ERR("lightReset" + JSON.stringify(err))}); - await Warehouse.get().resetDevice().catch(err => { this.ERR("resetDevice" + JSON.stringify(err)) }); - + await RCApi.get().activate().then(()=> RCApi.get().factoryReset()).catch(err => this.ERR("error while resetting remote control" + JSON.stringify(err))); let rsactivitytime = await appApi.resetInactivityTime().catch(err => { this.ERR("resetInactivityTime" + JSON.stringify(err)) }); if (rsactivitytime != null) { this.LOG("rsactivitytime" + JSON.stringify(rsactivitytime)) } - let GetKnownSSIDs = await NetworkManager.GetKnownSSIDs().then((ssids)=>{ssids}).catch(err => { console.error("GetKnownssids",err) }); - let clearSSID =false - if(GetKnownSSIDs && GetKnownSSIDs.length>0) - { - for(let i=0;i { this.ERR("clearSSID" + JSON.stringify(err)) });} - } - } - if (clearSSID != true) { this.LOG("clearSSID" + JSON.stringify(clearSSID)) } - let wifidisconnect = await NetworkManager.WiFiDisconnect().catch(err =>{ this.ERR("wifidisconnect" + JSON.stringify(err)) }); - if (wifidisconnect.success != true) { this.LOG("wifidisconnect" + JSON.stringify(wifidisconnect)) } try { localStorage.clear(); this.LOG("localStorage cleared successfully"); - } + } catch (err) { this.ERR("Error clearing localStorage: " + JSON.stringify(err)); } await appApi.clearCache().catch(err => { this.ERR("clearCache error: " + JSON.stringify(err)) }) - await appApi.reboot("User Trigger").then(result => { this.LOG('device rebooting' + JSON.stringify(result))}) + // Ensure Warehouse plugin is activated before calling resetDevice. + let warehouseStatus = await appApi.checkStatus(Warehouse.get().callsign); + let isActivated = warehouseStatus && warehouseStatus[0] && warehouseStatus[0].state === 'activated'; + if (!isActivated) { + if (!warehouseStatus || !warehouseStatus[0] || !warehouseStatus[0].state) { + this.WARN("FactoryReset: checkStatus returned unexpected response: " + JSON.stringify(warehouseStatus) + "; attempting activation."); + } else { + this.LOG("FactoryReset: Warehouse state is '" + warehouseStatus[0].state + "'; activating."); + } + let activationSuccess = await Warehouse.get().activate().then(() => true).catch(err => { + this.ERR("FactoryReset: warehouse activation failed: " + JSON.stringify(err)); + return false; + }); + if (!activationSuccess) { + this.ERR("FactoryReset: cannot proceed without Warehouse plugin."); + this.tag("Title").text.text = Language.translate("Factory Reset"); + this.tag("Info").text.text = Language.translate("Factory Reset failed. Please try again."); + this._setState('Confirm'); + return; + } + } + await Warehouse.get().resetDevice().catch(err => { + this.ERR("resetDevice" + JSON.stringify(err)); + this.tag("Title").text.text = Language.translate("Factory Reset"); + this.tag("Info").text.text = Language.translate("Factory Reset failed. Please try again."); + this._setState('Confirm'); + }); } static _states() { diff --git a/accelerator-home-ui/src/screens/OtherSettingsScreens/LanguageScreen.js b/accelerator-home-ui/src/screens/OtherSettingsScreens/LanguageScreen.js index ed150d5..322ca3f 100644 --- a/accelerator-home-ui/src/screens/OtherSettingsScreens/LanguageScreen.js +++ b/accelerator-home-ui/src/screens/OtherSettingsScreens/LanguageScreen.js @@ -20,16 +20,12 @@ import { Language, Lightning, Router } from '@lightningjs/sdk' import LanguageItem from '../../items/LanguageItem' import { availableLanguages, availableLanguageCodes, CONFIG } from '../../Config/Config' import AppApi from '../../api/AppApi'; -import RDKShellApis from '../../api/RDKShellApis'; import AlexaApi from '../../api/AlexaApi'; import thunderJS from 'ThunderJS'; -import { GLOBALS } from '../../Config/Config' -import FireBoltApi from '../../api/firebolt/FireBoltApi'; -import { Metrics } from '@firebolt-js/manage-sdk'; + const appApi = new AppApi() const thunder = thunderJS(CONFIG.thunderConfig) -const loader = 'Loader' export default class LanguageScreen extends Lightning.Component { @@ -77,11 +73,6 @@ export default class LanguageScreen extends Lightning.Component { } _active() { - if ("ResidentApp" !== GLOBALS.selfClientName) { - this.OnLanguageChangedfirebolt = FireBoltApi.get().localization.listen("languageChanged", value => { - this.LOG('language changed successfully' + JSON.stringify(value)) - }) - } this._Languages = this.tag('LanguageScreenContents.Languages') this._Languages.h = availableLanguages.length * 90 this._Languages.tag('List').h = availableLanguages.length * 90 @@ -94,17 +85,6 @@ export default class LanguageScreen extends Lightning.Component { item: item, } }) - appApi.deactivateResidentApp(loader) - RDKShellApis.moveToFront(GLOBALS.selfClientName) - RDKShellApis.setFocus(GLOBALS.selfClientName).then(result => { - this.LOG('LanguageScreen: ResidentApp moveToFront Success'); - RDKShellApis.getVisibility(GLOBALS.selfClientName).then(visible => { - if (!visible) RDKShellApis.setVisibility(GLOBALS.selfClientName, true); - }) - }).catch(err => { - this.ERR('LanguageScreen: Error' + JSON.stringify(err)); - Metrics.error(Metrics.ErrorType.OTHER, "AppLangugaeError", 'Thunder RDKShell setFocus Error' + JSON.stringify(err), false, null) - }); } _focus() { @@ -146,17 +126,8 @@ export default class LanguageScreen extends Lightning.Component { } }) } - if ("ResidentApp" === GLOBALS.selfClientName) { - appApi.setUILanguage(updatedLanguage) - } else { - FireBoltApi.get().localization.setlanguage(availableLanguages[this._Languages.tag('List').index]).then(res => this.LOG("sucess language set ::::" + JSON.stringify(res))) - } + appApi.setUILanguage(updatedLanguage) localStorage.setItem('Language',availableLanguages[this._Languages.tag('List').index]) - let path = location.pathname.split('index.html')[0] - let url = path.slice(-1) === '/' ? "static/loaderApp/index.html" : "/static/loaderApp/index.html" - let notification_url = location.origin + path + url - appApi.launchResident(notification_url, loader).catch(err => {this.ERR("error while launching loader url in resident app" + JSON.stringify(err)) }) - RDKShellApis.setVisibility(GLOBALS.selfClientName, false) location.reload(); } } diff --git a/accelerator-home-ui/src/screens/OtherSettingsScreens/NetworkInfoScreen.js b/accelerator-home-ui/src/screens/OtherSettingsScreens/NetworkInfoScreen.js index 568cdad..dcd58b7 100644 --- a/accelerator-home-ui/src/screens/OtherSettingsScreens/NetworkInfoScreen.js +++ b/accelerator-home-ui/src/screens/OtherSettingsScreens/NetworkInfoScreen.js @@ -309,55 +309,10 @@ export default class NetworkInfo extends Lightning.Component { this.tag("IPAddress.Value").text.text = `NA` this.tag("Gateway.Value").text.text = `NA` this.tag("MACAddress.Value").text.text = `NA` - if ("ResidentApp" === GLOBALS.selfClientName) - { - await NetworkManager.GetPrimaryInterface().then((defaultInterface) => { - console.log("defaultinterface"+defaultInterface) - NetworkManager.GetIPSettings(defaultInterface).then((result) => { - if (result.interface === "wlan0") { - this.tag("ConnectionType.Value").text.text = Language.translate("Wireless") - this.tag("SSID").alpha = 1 - this.tag("SignalStrength").alpha = 1 - NetworkManager.GetConnectedSSID().then((result) => { - if (parseInt(result.strength) >= -50) { - this.tag("SignalStrength.Value").text.text = `Excellent` - } - else if (parseInt(result.strength) >= -60) { - this.tag("SignalStrength.Value").text.text = `Good` - } - else if (parseInt(result.strength) >= -67) { - this.tag("SignalStrength.Value").text.text = `Fair` - } - else { - this.tag("SignalStrength.Value").text.text = `Poor` - } - this.tag("SSID.Value").text.text = `${result.ssid}` - }).catch((error) => this.ERR("Error: " + JSON.stringify(error))); - } else if (result.interface === "eth0") { - this.tag("ConnectionType.Value").text.text = 'Ethernet' - this.tag("SSID").alpha = 0 - this.tag("SignalStrength").alpha = 0 - } - this.tag('InternetProtocol.Value').text.text = result.ipversion - this.tag('IPAddress.Value').text.text = result.ipaddress - this.tag("Gateway.Value").text.text = result.gateway - }).catch((err) => this.ERR("Error: " + JSON.stringify(err))) - - NetworkManager.GetAvailableInterfaces().then((interfaces) => { - currentInterface = interfaces.filter((data) => data.name === defaultInterface) - if (currentInterface[0].connected) { - this.tag("Status.Value").text.text = Language.translate('Connected') - } - else { - this.tag('Status.Value').text.text = Language.translate('Disconnected') - } - this.tag('MACAddress.Value').text.text = currentInterface[0].mac - }).catch((error) => this.ERR("Error: " + JSON.stringify(error))); - }).catch((error) => this.ERR("Error: " + JSON.stringify(error))); - } - else{ - await FireBoltApi.get().deviceinfo.getnetwork().then(res=>{ - if (res.type === "wifi") { + await NetworkManager.GetPrimaryInterface().then((defaultInterface) => { + console.log("defaultinterface"+defaultInterface) + NetworkManager.GetIPSettings(defaultInterface).then((result) => { + if (result.interface === "wlan0") { this.tag("ConnectionType.Value").text.text = Language.translate("Wireless") this.tag("SSID").alpha = 1 this.tag("SignalStrength").alpha = 1 @@ -376,31 +331,31 @@ export default class NetworkInfo extends Lightning.Component { } this.tag("SSID.Value").text.text = `${result.ssid}` }).catch((error) => this.ERR("Error: " + JSON.stringify(error))); - } else if (res.type === "ethernet") { + } else if (result.interface === "eth0") { this.tag("ConnectionType.Value").text.text = 'Ethernet' this.tag("SSID").alpha = 0 this.tag("SignalStrength").alpha = 0 } - if (res.state== "connected") { + this.tag('InternetProtocol.Value').text.text = result.ipversion + this.tag('IPAddress.Value').text.text = result.ipaddress + this.tag("Gateway.Value").text.text = result.gateway + }).catch((err) => this.ERR("Error: " + JSON.stringify(err))) + + NetworkManager.GetAvailableInterfaces().then((interfaces) => { + const matchedInterface = interfaces.find((data) => data.name === defaultInterface) + if (!matchedInterface) { + this.ERR("Interface not found for: " + defaultInterface) + return + } + if (matchedInterface.connected) { this.tag("Status.Value").text.text = Language.translate('Connected') } else { this.tag('Status.Value').text.text = Language.translate('Disconnected') } - NetworkManager.GetPrimaryInterface().then((defaultInterface) => { - NetworkManager.GetIPSettings(defaultInterface).then((result) => { - this.tag('InternetProtocol.Value').text.text = result.ipversion - this.tag('IPAddress.Value').text.text = result.ipaddress - this.tag("Gateway.Value").text.text = result.gateway - }) - NetworkManager.GetAvailableInterfaces().then((res) => { - currentInterface = res.interfaces.filter((data) => data.type === defaultInterface) - this.tag('MACAddress.Value').text.text = currentInterface[0].mac - }).catch((error) => this.ERR("Error: " + JSON.stringify(error))); - }) - + this.tag('MACAddress.Value').text.text = matchedInterface.mac }).catch((error) => this.ERR("Error: " + JSON.stringify(error))); - } + }).catch((error) => this.ERR("Error: " + JSON.stringify(error))); } _focus() { diff --git a/accelerator-home-ui/src/screens/RcInformationScreen.js b/accelerator-home-ui/src/screens/RcInformationScreen.js index 03fe522..565303b 100644 --- a/accelerator-home-ui/src/screens/RcInformationScreen.js +++ b/accelerator-home-ui/src/screens/RcInformationScreen.js @@ -16,7 +16,7 @@ * See the License for the specific language governing permissions and * limitations under the License. **/ -import { Lightning, Language, Router } from '@lightningjs/sdk' +import { Lightning, Language, Registry, Router } from '@lightningjs/sdk' import { COLORS } from './../colors/Colors' import { CONFIG } from '../Config/Config' import ThunderJS from 'ThunderJS' @@ -228,6 +228,8 @@ export default class RCInformationScreen extends Lightning.Component { } async _active() { + this.scanTrigger = null; + this.findRemoteTrigger = true; await RCApi.get().activate().catch(err => { this.ERR("RCInformationScreen error: " + JSON.stringify(err)) }); await RCApi.get().getNetStatus().then(result => { this.INFO("RCInformationScreen getNetStatus: " + JSON.stringify(result)) @@ -244,16 +246,21 @@ export default class RCInformationScreen extends Lightning.Component { this.tag("SwVersion.Value").text.text = `N/A` this.tag("BatteryPercent.Value").text.text = `N/A` this.tag("RCUName.Value").text.text = `N/A` - //RCApi.get().deactivate().catch(err=> { console.error("RCInformationScreen error:", err)}); + if (this.scanTrigger) { + Registry.clearTimeout(this.scanTrigger); + this.scanTrigger = null; + } + this.findRemoteTrigger = false; } onStatusCB(cbData) { // getStatus response has 'success' property; notification payload does not have that. + // this.LOG("RCInformationScreen onStatusCB cbData:" + JSON.stringify(cbData)); if ((cbData !== undefined) && ("success" in cbData ? cbData.success : true)) { let cbDatastatus if (Array.isArray(cbData.status)) { cbDatastatus = cbData.status[0] || {}; - } + } else if (cbData.status && typeof cbData.status === 'object') { cbDatastatus = cbData.status; } @@ -262,6 +269,11 @@ export default class RCInformationScreen extends Lightning.Component { let RemoteName = []; let connectedStatus = []; let MacAddress = []; let swVersion = []; let BatteryPercent = []; + if (this.scanTrigger) { + Registry.clearTimeout(this.scanTrigger); + this.scanTrigger = null; + } + cbDatastatus.remoteData.map(item => { RemoteName.push(item.name) }) @@ -282,14 +294,43 @@ export default class RCInformationScreen extends Lightning.Component { this.tag("SwVersion.Value").text.text = swVersion this.tag("BatteryPercent.Value").text.text = BatteryPercent this.tag("RCUName.Value").text.text = RemoteName + if (this.findRemoteTrigger) { + this.findRemoteTrigger = false; + RCApi.get().findMyRemote().catch(err => { + this.ERR("RCInformationScreen findMyRemote error: " + JSON.stringify(err)) + }); + } } else { - if(cbDatastatus.pairingState != "SEARCHING" && cbDatastatus.pairingState != "PAIRING" ) { - for(let i=0;i { - this.ERR("RCInformationScreen startPairing error: " + JSON.stringify(err)); - }); + if (cbDatastatus.pairingState === "IDLE" || cbDatastatus.pairingState === "FAILED") { + // after 2 seconds, initiate pairing flow if status is IDLE, as there is no paired device. + if (!this.scanTrigger) { + this.scanTrigger = Registry.setTimeout(() => { + this.scanTrigger = null; + RCApi.get().getNetStatus().then(result => { + let latestStatus = {}; + if (Array.isArray(result.status)) { + latestStatus = result.status[0] || {}; + } else if (result.status && typeof result.status === 'object') { + latestStatus = result.status; + } + + const latestHasRemoteData = Array.isArray(latestStatus.remoteData) && latestStatus.remoteData.length; + const latestInRetryState = latestStatus.pairingState === "IDLE" || latestStatus.pairingState === "FAILED"; + + if (!latestHasRemoteData && latestInRetryState) { + RCApi.get().startPairing().catch(err => { + this.ERR("RCInformationScreen startPairing error: " + JSON.stringify(err)); + }); + } + }).catch(err => { + this.ERR("RCInformationScreen getNetStatus before startPairing error: " + JSON.stringify(err)); + }); + }, 2000); + } + } else { + if (this.scanTrigger) { + Registry.clearTimeout(this.scanTrigger); + this.scanTrigger = null; } } } diff --git a/accelerator-home-ui/src/screens/SettingsScreen.js b/accelerator-home-ui/src/screens/SettingsScreen.js index 9659e8f..34b766f 100644 --- a/accelerator-home-ui/src/screens/SettingsScreen.js +++ b/accelerator-home-ui/src/screens/SettingsScreen.js @@ -79,9 +79,33 @@ export default class SettingsScreen extends Lightning.Component { src: Utils.asset('images/settings/Arrow.png'), }, }, - Bluetooth: { + ApplicationCatalogueLogin: { y: 90, type: SettingsMainItem, + Title: { + x: 10, + y: 45, + mountY: 0.5, + text: { + text: Language.translate('Connect to the Application Catalog'), + textColor: COLORS.titleColor, + fontFace: CONFIG.language.font, + fontSize: 25, + } + }, + Button: { + h: 45, + w: 45, + x: 1600, + mountX: 1, + y: 45, + mountY: 0.5, + src: Utils.asset('images/settings/Arrow.png'), + }, + }, + Bluetooth: { + y: 180, + type: SettingsMainItem, Title: { x: 10, y: 45, @@ -104,7 +128,7 @@ export default class SettingsScreen extends Lightning.Component { }, }, Video: { - y: 180, + y: 270, type: SettingsMainItem, Title: { x: 10, @@ -128,7 +152,7 @@ export default class SettingsScreen extends Lightning.Component { }, }, Audio: { - y: 270, + y: 360, type: SettingsMainItem, Title: { x: 10, @@ -152,7 +176,7 @@ export default class SettingsScreen extends Lightning.Component { }, }, OtherSettings: { - y: 360, + y: 450, type: SettingsMainItem, Title: { x: 10, @@ -177,7 +201,7 @@ export default class SettingsScreen extends Lightning.Component { }, NFRStatus: { - y: 450, + y: 540, type: SettingsMainItem, Title: { x: 10, @@ -204,7 +228,7 @@ export default class SettingsScreen extends Lightning.Component { DTVSettings: { alpha: 0.3, - y: 630, + y: 720, type: SettingsMainItem, Title: { x: 10, @@ -229,7 +253,7 @@ export default class SettingsScreen extends Lightning.Component { }, VoiceRemoteControl: { - y: 540, + y: 630, type: SettingsMainItem, Title: { x: 10, @@ -300,7 +324,7 @@ export default class SettingsScreen extends Lightning.Component { this.tag('NetworkConfiguration')._unfocus() } _handleDown() { - this._setState('Bluetooth') + this._setState('ApplicationCatalogueLogin') } _handleEnter() { if (!Router.isNavigating()) { @@ -308,6 +332,25 @@ export default class SettingsScreen extends Lightning.Component { } } }, + class ApplicationCatalogueLogin extends this { + $enter() { + this.tag('ApplicationCatalogueLogin')._focus() + } + $exit() { + this.tag('ApplicationCatalogueLogin')._unfocus() + } + _handleUp() { + this._setState('NetworkConfiguration') + } + _handleDown() { + this._setState('Bluetooth') + } + _handleEnter() { + if (!Router.isNavigating()) { + Router.navigate('settings/appcataloglogin') + } + } + }, class Bluetooth extends this { $enter() { this.tag('Bluetooth')._focus() @@ -316,7 +359,7 @@ export default class SettingsScreen extends Lightning.Component { this.tag('Bluetooth')._unfocus() } _handleUp() { - this._setState('NetworkConfiguration') + this._setState('ApplicationCatalogueLogin') } _handleDown() { this._setState('Video') @@ -444,7 +487,7 @@ export default class SettingsScreen extends Lightning.Component { this.tag('DTVSettings')._unfocus() } _handleUp() { - this._setState('NFRStatus') + this._setState('VoiceRemoteControl') } _handleEnter() { if (this.dtvPlugin) { diff --git a/accelerator-home-ui/src/screens/SplashScreens/BluetoothScreen.js b/accelerator-home-ui/src/screens/SplashScreens/BluetoothScreen.js index 847e366..387485b 100644 --- a/accelerator-home-ui/src/screens/SplashScreens/BluetoothScreen.js +++ b/accelerator-home-ui/src/screens/SplashScreens/BluetoothScreen.js @@ -35,6 +35,7 @@ export default class BluetoothScreen extends Lightning.Component { this.LOG = console.log; this.ERR = console.error; this.WARN = console.warn; + this.scanTrigger = null; } static _template() { @@ -135,10 +136,6 @@ export default class BluetoothScreen extends Lightning.Component { } } - _active() { - this.timeout = 30; - } - _PairingApis() { //bluetoothApi.btactivate().then(enableResult =>{ // console.log('1') @@ -169,23 +166,22 @@ export default class BluetoothScreen extends Lightning.Component { Router.navigate('splash/language') } }) - }) - .catch(err => { - this.ERR(`SplashBluetoothScreen cant stopscan device : ${JSON.stringify(err)}`) - }) - }) .catch(err => { - this.ERR("SplashBluetoothScreen cant stopscan device : " + JSON.stringify(err)) + this.ERR(`SplashBluetoothScreen can't stop scan device : ${JSON.stringify(err)}`) }) }) .catch(err => { - this.ERR("SplashBluetoothScreen cant getpaired device : " + JSON.stringify(err)) + this.ERR("SplashBluetoothScreen getpairedDevices failed : " + JSON.stringify(err)) }) }) .catch(err => { - this.ERR(`SplashBluetoothScreen Can't pair device : ${JSON.stringify(err)}`) + this.ERR("SplashBluetoothScreen getConnectedDevices failed : " + JSON.stringify(err)) }) + }) + .catch(err => { + this.ERR(`SplashBluetoothScreen Can't pair device : ${JSON.stringify(err)}`) + }) }) }) }) @@ -196,43 +192,79 @@ export default class BluetoothScreen extends Lightning.Component { } onStatusCB(cbData) { - //console.log("BluetoothScreen cbData:", JSON.stringify(cbData)); + //console.log("BluetoothScreen cbData:" + JSON.stringify(cbData)); // getStatus response has 'success' property; notification payload does not have that. if ((cbData !== undefined) && (cbData.hasOwnProperty("success") ? cbData.success : true)) { - let cbDatastatus + let cbDatastatus = {}; if (Array.isArray(cbData.status)) { cbDatastatus = cbData.status[0] || {}; - } + } else if (cbData.status && typeof cbData.status === 'object') { cbDatastatus = cbData.status; - } - if (cbDatastatus.remoteData.length) { + } + const remoteData = Array.isArray(cbDatastatus.remoteData) ? cbDatastatus.remoteData : []; + if (remoteData.length > 0) { //console.log("BluetoothScreen rcPairingApis RemoteData Length ", cbData.status.remoteData.length) - cbDatastatus.remoteData.map(item => { + if (this.scanTrigger) { + Registry.clearTimeout(this.scanTrigger); + this.scanTrigger = null; + } + remoteData.forEach(item => { this.tag('Info').text.text = `paired with device ${item.name}` - // Do not clear this.RCTimeout if need to run this in background to reconnect on loss. - // if (this.RCTimeout) { - // console.log("SplashBluetoothScreen clearTimeout(this.RCTimeout)"); - // Registry.clearTimeout(this.RCTimeout) - // } - // To stop the display counter. - if (Router.getActiveHash() === "splash/bluetooth") { - if (this.timeInterval) { - Registry.clearInterval(this.timeInterval) - } - Registry.setTimeout(() => { - Router.navigate('splash/language') - }, 2000) - } }) + // To stop the display counter and navigate once. + if (Router.getActiveHash() === "splash/bluetooth") { + if (this.timeInterval) { + Registry.clearInterval(this.timeInterval) + } + if (this.navigateTimeout) { + Registry.clearTimeout(this.navigateTimeout); + } + this.navigateTimeout = Registry.setTimeout(() => { + this.navigateTimeout = null; + Router.navigate('splash/language') + }, 2000) + } } else { - if(cbDatastatus.pairingState != "SEARCHING" && cbDatastatus.pairingState != "PAIRING" ) { - for(let i=0;i { - this.ERR("RCInformationScreen startPairing error: " + JSON.stringify(err)); - }); + if (cbDatastatus.pairingState === "IDLE" || cbDatastatus.pairingState === "FAILED") { + // after 2 seconds, initiate pairing flow if status is IDLE, as there is no paired device. + if (!this.scanTrigger) { + this.scanTrigger = Registry.setTimeout(() => { + this.scanTrigger = null; + RCApi.get().getNetStatus().then(result => { + let latestStatus = {}; + if (Array.isArray(result.status)) { + latestStatus = result.status[0] || {}; + } else if (result.status && typeof result.status === 'object') { + latestStatus = result.status; + } + + const latestHasRemoteData = Array.isArray(latestStatus.remoteData) && latestStatus.remoteData.length; + const latestInRetryState = latestStatus.pairingState === "IDLE" || latestStatus.pairingState === "FAILED"; + if (!latestHasRemoteData && latestInRetryState) { + RCApi.get().startPairing().then(success => { + if (success === false && !this.scanTrigger) { + this.ERR("SplashBluetoothScreen startPairing returned false, retrying..."); + this.scanTrigger = Registry.setTimeout(() => { + this.scanTrigger = null; + RCApi.get().startPairing().catch(err => { + this.ERR("SplashBluetoothScreen startPairing retry error: " + JSON.stringify(err)); + }); + }, 2000); + } + }).catch(err => { + this.ERR("SplashBluetoothScreen startPairing error: " + JSON.stringify(err)); + }); + } + }).catch(err => { + this.ERR("SplashBluetoothScreen getNetStatus before startPairing error: " + JSON.stringify(err)); + }); + }, 2000); + } + } else { + if (this.scanTrigger) { + Registry.clearTimeout(this.scanTrigger); + this.scanTrigger = null; } } } @@ -248,7 +280,39 @@ export default class BluetoothScreen extends Lightning.Component { } _thunder.on('org.rdk.RemoteControl', 'onStatus', data => { this.onStatusCB(data) }); this.RCTimeout = Registry.setTimeout(() => { - RCApi.get().getNetStatus().then(result => { this.onStatusCB(result); }); + RCApi.get().getNetStatus().then(result => { + this.onStatusCB(result); + // onStatusCB only schedules startPairing on IDLE/FAILED. If the plugin + // auto-started a PAIRING session (state="PAIRING"), onStatusCB clears + // scanTrigger without scheduling anything, causing a ~30s delay until + // the session expires. If no device is paired and no scanTrigger was set, + // ensure startPairing is called within 5 seconds of page load. + if (!this.scanTrigger) { + let status = Array.isArray(result.status) ? (result.status[0] || {}) : + (result.status && typeof result.status === 'object' ? result.status : {}); + const hasRemote = Array.isArray(status.remoteData) && status.remoteData.length > 0; + const inRetryState = status.pairingState === "IDLE" || status.pairingState === "FAILED"; + if (!hasRemote && inRetryState) { + this.scanTrigger = Registry.setTimeout(() => { + this.scanTrigger = null; + RCApi.get().startPairing().catch(err => { + this.ERR("SplashBluetoothScreen startPairing error: " + JSON.stringify(err)); + }); + }, 3000); + } + } + }).catch(err => { + this.ERR("SplashBluetoothScreen getNetStatus error: " + JSON.stringify(err)); + // On failure, schedule startPairing as a recovery so pairing doesn't stall. + if (!this.scanTrigger) { + this.scanTrigger = Registry.setTimeout(() => { + this.scanTrigger = null; + RCApi.get().startPairing().catch(pairErr => { + this.ERR("SplashBluetoothScreen startPairing after getNetStatus failure error: " + JSON.stringify(pairErr)); + }); + }, 3000); + } + }); }, 5, true); } @@ -279,9 +343,18 @@ export default class BluetoothScreen extends Lightning.Component { } _active() { + this.timeout = 30; this.initTimer() + if (typeof this.scanTrigger === 'undefined') { + this.scanTrigger = null; + } } + _handleBack() { + // Block back navigation during splash setup to prevent black screen. + return true; + } + pageTransition() { return 'left' } @@ -302,6 +375,14 @@ export default class BluetoothScreen extends Lightning.Component { if (this.RCTimeout) { Registry.clearTimeout(this.RCTimeout) } + if (this.scanTrigger) { + Registry.clearTimeout(this.scanTrigger) + this.scanTrigger = null; + } + if (this.navigateTimeout) { + Registry.clearTimeout(this.navigateTimeout) + this.navigateTimeout = null; + } } static _states() { diff --git a/accelerator-home-ui/src/screens/SplashScreens/LanguageScreen.js b/accelerator-home-ui/src/screens/SplashScreens/LanguageScreen.js index 697d63b..f6cd056 100644 --- a/accelerator-home-ui/src/screens/SplashScreens/LanguageScreen.js +++ b/accelerator-home-ui/src/screens/SplashScreens/LanguageScreen.js @@ -17,16 +17,13 @@ * limitations under the License. **/ -import { Lightning, Router, Language, Storage } from '@lightningjs/sdk' -import { CONFIG, GLOBALS } from '../../Config/Config' +import { Lightning, Router, Language } from '@lightningjs/sdk' +import { CONFIG } from '../../Config/Config' import LanguageItem from '../../items/LanguageItem' import { availableLanguages, availableLanguageCodes } from '../../Config/Config' import AppApi from '../../api/AppApi' -import RDKShellApis from '../../api/RDKShellApis' -import FireBoltApi from '../../api/firebolt/FireBoltApi' const appApi = new AppApi() -const loader = 'Loader' export default class LanguageScreen extends Lightning.Component { constructor(...args) { @@ -122,17 +119,6 @@ export default class LanguageScreen extends Lightning.Component { } }) - appApi.deactivateResidentApp(loader) - RDKShellApis.moveToFront(GLOBALS.selfClientName) - RDKShellApis.setFocus(GLOBALS.selfClientName).then(result => { - this.LOG('LanguageScreen: ResidentApp moveToFront Success') - RDKShellApis.getVisibility(GLOBALS.selfClientName).then(visible => { - if (!visible) RDKShellApis.setVisibility(GLOBALS.selfClientName, true) - }) - }).catch(err => { - this.ERR('LanguageScreen: Error' + JSON.stringify(err)) - Metrics.error(Metrics.ErrorType.OTHER, "AppLangugaeError", 'Thunder RDKShell setFocus Error' + JSON.stringify(err), false, null) - }); } pageTransition() { @@ -148,11 +134,7 @@ export default class LanguageScreen extends Lightning.Component { } updateUILanguage(index) { - if ("ResidentApp" === GLOBALS.selfClientName) { - appApi.setUILanguage(availableLanguageCodes[availableLanguages[index]]) - } else { - FireBoltApi.get().localization.setlanguage(availableLanguages[index]).then(res => this.LOG("sucess language set ::::" + JSON.stringify(res))) - } + appApi.setUILanguage(availableLanguageCodes[availableLanguages[index]]) localStorage.setItem('Language',availableLanguages[index]) } @@ -181,12 +163,6 @@ export default class LanguageScreen extends Lightning.Component { const index = this._Languages.tag('List').index localStorage.setItem('LanguageSelectedIndex', index) this.updateUILanguage(index) - let path = location.pathname.split('index.html')[0] - let url = path.slice(-1) === '/' ? "static/loaderApp/index.html" : "/static/loaderApp/index.html" - let notification_url = location.origin + path + url - this.LOG("LanguageScreen notification_url: " + JSON.stringify(notification_url)) - appApi.launchResident(notification_url, loader).catch(err => { }) - RDKShellApis.setVisibility(GLOBALS.selfClientName, false) location.reload(); } } diff --git a/accelerator-home-ui/src/views/AppInfoPage.js b/accelerator-home-ui/src/views/AppInfoPage.js index 9070e46..7ef5a6d 100644 --- a/accelerator-home-ui/src/views/AppInfoPage.js +++ b/accelerator-home-ui/src/views/AppInfoPage.js @@ -23,6 +23,7 @@ import { CONFIG, GLOBALS } from "../Config/Config"; import AppCard from "../items/AppCard"; import { getInstalledDACApps, startDACApp, uninstallDACApp } from "../api/DACApi"; import { filterExcludedApps } from "../helpers/DACAppPresentation"; +import UninstallConfirmation from "../overlays/UninstallConfirmation"; export default class AppInfoPage extends Lightning.Component { @@ -137,7 +138,7 @@ export default class AppInfoPage extends Lightning.Component { y: 30, mount: 0.5, text: { - text: 'OK', + text: Language.translate('OK'), fontSize: 32, fontFace: CONFIG.language.font, textColor: 0xFF000000 @@ -158,6 +159,13 @@ export default class AppInfoPage extends Lightning.Component { } } } + }, + + // Uninstall Confirmation Overlay + UninstallConfirmationOverlay: { + type: UninstallConfirmation, + visible: false, + zIndex: 10 } } } @@ -247,7 +255,7 @@ export default class AppInfoPage extends Lightning.Component { break; case 'uninstall': console.log("Uninstall app:", appInfo.name); - this._uninstallApp(appInfo); + this._showUninstallConfirmation(appInfo); break; default: console.log("Unknown action:", action); @@ -291,13 +299,73 @@ export default class AppInfoPage extends Lightning.Component { const result = await uninstallDACApp({ id: appInfo.id, version: appInfo.version, name: appInfo.name }, this); if (result) { console.log(`${appInfo.name} uninstalled successfully`); - // Refresh the list after uninstall - await this._fetchInstalledApps(); + return true; } else { console.error(`Failed to uninstall ${appInfo.name}`); + return false; } } catch (error) { console.error(`Error uninstalling ${appInfo.name}:`, error); + return false; + } + } + + /** + * Show the uninstall confirmation overlay + */ + _showUninstallConfirmation(appInfo) { + this.tag('UninstallConfirmationOverlay').appInfo = appInfo; + this.tag('UninstallConfirmationOverlay').visible = true; + this._setState('UninstallConfirmation'); + } + + /** + * Hide the uninstall confirmation overlay. + * Only handles overlay cleanup; callers are responsible for + * setting the correct page state afterward. + */ + _hideUninstallConfirmation() { + // Reset overlay to its initial state so that Uninstalling.$exit() runs, + // stopping the loader animation and restoring hidden UI elements. + this.tag('UninstallConfirmationOverlay')._setState('Confirm'); + this.tag('UninstallConfirmationOverlay').visible = false; + } + + /** + * Signal handler: user confirmed uninstall + */ + async $confirmUninstall(appInfo) { + console.log('Uninstall confirmed for:', appInfo.name); + this.tag('UninstallConfirmationOverlay').showUninstalling(); + const success = await this._uninstallApp(appInfo); + // Dismiss overlay first, then let _fetchInstalledApps -> _loadAppData + // be the single source of truth for the next page state. + this._hideUninstallConfirmation(); + if (success) { + // _loadAppData will set AppList or EmptyState based on refreshed data + await this._fetchInstalledApps(); + } else { + // Uninstall failed — data hasn't changed, restore list focus + this._setState('AppList'); + this.widgets.failok.notify({ + title: Language.translate('Uninstall Failed'), + msg: Language.translate('Failed to uninstall') + ` "${appInfo.name}". ` + Language.translate('Please try again later.'), + }); + Router.focusWidget('FailOk'); + } + } + + /** + * Signal handler: user cancelled uninstall + */ + $cancelUninstall() { + console.log('Uninstall cancelled'); + this._hideUninstallConfirmation(); + // Data hasn't changed — restore previous page state + if (this._appData.length > 0) { + this._setState('AppList'); + } else { + this._setState('EmptyState'); } } @@ -378,6 +446,17 @@ export default class AppInfoPage extends Lightning.Component { return false; } }, + class UninstallConfirmation extends this { + $enter() { + this.tag('UninstallConfirmationOverlay').visible = true; + } + _getFocused() { + return this.tag('UninstallConfirmationOverlay'); + } + $exit() { + this.tag('UninstallConfirmationOverlay').visible = false; + } + }, class EmptyState extends this { $enter() { this.tag('EmptyState.OkButton').color = CONFIG.theme.hex; @@ -393,6 +472,8 @@ export default class AppInfoPage extends Lightning.Component { return this; } _focus() { + // Re-fetch installed apps in case new apps were installed while away + this._fetchInstalledApps(); this.tag('EmptyState.OkButton').color = CONFIG.theme.hex; this.tag('EmptyState.OkButton.OkLabel').text.textColor = 0xFFFFFFFF; this.tag('EmptyState.OkButton.FocusBorder').alpha = 1; diff --git a/accelerator-home-ui/src/views/AppStore.js b/accelerator-home-ui/src/views/AppStore.js index 083d1d5..47608ec 100644 --- a/accelerator-home-ui/src/views/AppStore.js +++ b/accelerator-home-ui/src/views/AppStore.js @@ -3,6 +3,7 @@ import { Grid } from "@lightningjs/ui"; import { CONFIG } from "../Config/Config"; import AppCatalogItem from "../items/AppCatalogItem"; import { getAppCatalogInfo } from "../api/DACApi" +import { eventTarget, RefreshNeeded } from '../api/AppCatalog' export default class AppStore extends Lightning.Component { @@ -44,19 +45,39 @@ export default class AppStore extends Lightning.Component { } } - async _firstEnable() { + _firstEnable() { + this._onRefreshNeeded = () => { + this.LOG('RefreshNeeded event received - reloading catalog') + this._loadCatalog() + } + eventTarget.addEventListener(RefreshNeeded.eventName, this._onRefreshNeeded) + } + + async _loadCatalog() { let Catalog = [] try { Catalog = await getAppCatalogInfo() } catch (error) { this.ERR("Failed to get App Catalog Info:" + JSON.stringify(error)) } + if (!Array.isArray(Catalog) || Catalog.length === 0) { + this.LOG('No apps available in catalog') + return + } + Catalog.sort((a, b) => (a.name || '').localeCompare(b.name || '')) + this.tag('Catalog').clear() this.tag('Catalog').add(Catalog.map((element) => { return { h: AppCatalogItem.height + 90, w: AppCatalogItem.width, info: element } })); this._setState('Catalog') } + _detach() { + if (this._onRefreshNeeded) { + eventTarget.removeEventListener(RefreshNeeded.eventName, this._onRefreshNeeded) + } + } + _handleLeft() { @@ -75,9 +96,37 @@ export default class AppStore extends Lightning.Component { } _focus() { + this._loadCatalog() this._setState('Catalog') } + $showInstallError({ name, errorCode }) { + const appName = name || Language.translate('App') + const msg = Language.translate('Something went wrong while installing') + ` "${appName}". ` + Language.translate('Error code') + `: ${errorCode}` + this.widgets.failok.notify({ title: Language.translate('Installation Failed'), msg: msg }) + Router.focusWidget('FailOk') + } + + $showUninstallError({ name, error }) { + const appName = name || Language.translate('App') + let msg = Language.translate('Failed to uninstall') + ` "${appName}". ` + Language.translate('Please try again later.') + if (error) { + msg += ' ' + Language.translate('Error') + `: ${error}` + } + this.widgets.failok.notify({ title: Language.translate('Uninstall Failed'), msg: msg }) + Router.focusWidget('FailOk') + } + + $showLaunchError({ name, error }) { + const appName = name || Language.translate('App') + let msg = Language.translate('Something went wrong while launching') + ` "${appName}". ` + Language.translate('Please check the internet and remaining setup.') + if (error) { + msg += ' ' + Language.translate('Error') + `: ${error}` + } + this.widgets.failok.notify({ title: Language.translate('Launch Failed'), msg: msg }) + Router.focusWidget('FailOk') + } + static _states() { return [ class Catalog extends this { diff --git a/accelerator-home-ui/src/views/MainView.js b/accelerator-home-ui/src/views/MainView.js index 27c258a..f73ebde 100644 --- a/accelerator-home-ui/src/views/MainView.js +++ b/accelerator-home-ui/src/views/MainView.js @@ -32,6 +32,7 @@ import NetworkManager from '../api/NetworkManagerAPI.js' import { getAppCatalogInfo, getInstalledDACApps, startDACApp } from '../api/DACApi.js' import { filterExcludedApps } from '../helpers/DACAppPresentation.js' import AppController from '../AppController.js' +import { eventTarget, RefreshNeeded } from '../api/AppCatalog.js' /** Class for main view component in home UI */ export default class MainView extends Lightning.Component { @@ -266,7 +267,7 @@ export default class MainView extends Lightning.Component { })) // Add "More Apps" item at the end apps.push({ - displayName: 'More Apps', + displayName: Language.translate('More Apps'), applicationType: 'MoreApps', uri: 'apps', url: '/images/sidePanel/moreapps.png', @@ -443,7 +444,7 @@ export default class MainView extends Lightning.Component { this._hideDacAppsLoader() // Clear stale cached apps (broken/default icons) and show only "More Apps" this.dacApps = [{ - displayName: 'More Apps', + displayName: Language.translate('More Apps'), applicationType: 'MoreApps', uri: 'apps', url: '/images/sidePanel/moreapps.png', @@ -458,6 +459,13 @@ export default class MainView extends Lightning.Component { } AppController.get().addPackageChangedListener(this._onPackageChanged) + // Refresh DAC apps row when app catalog authentication changes + this._onCatalogRefreshNeeded = () => { + this.LOG('RefreshNeeded event received - refreshing DAC apps row') + this.refreshSecondRow() + } + eventTarget.addEventListener(RefreshNeeded.eventName, this._onCatalogRefreshNeeded) + this.dacApps = dacCatalog this.fireAncestors("$mountEventConstructor", registerListener.bind(this)) @@ -469,6 +477,9 @@ export default class MainView extends Lightning.Component { _detach() { // Unsubscribe to avoid stale references to this MainView instance AppController.get().removePackageChangedListener(this._onPackageChanged) + if (this._onCatalogRefreshNeeded) { + eventTarget.removeEventListener(RefreshNeeded.eventName, this._onCatalogRefreshNeeded) + } } _firstActive() { @@ -718,8 +729,35 @@ export default class MainView extends Lightning.Component { } } $showNetworkError() { - this.widgets.fail.notify({ title: 'Network State', msg: 'Offline' }) - Router.focusWidget('Fail') + this.widgets.failok.notify({ title: Language.translate('No Internet'), msg: Language.translate('No internet connection. Please check your network and try again.') }) + Router.focusWidget('FailOk') + } + + $showInstallError({ name, errorCode }) { + const appName = name || Language.translate('App') + const msg = Language.translate('Something went wrong while installing') + ` "${appName}". ` + Language.translate('Error code') + `: ${errorCode}` + this.widgets.failok.notify({ title: Language.translate('Installation Failed'), msg: msg }) + Router.focusWidget('FailOk') + } + + $showUninstallError({ name, error }) { + const appName = name || Language.translate('App') + let msg = Language.translate('Failed to uninstall') + ` "${appName}". ` + Language.translate('Please try again later.') + if (error) { + msg += ' ' + Language.translate('Error') + `: ${error}` + } + this.widgets.failok.notify({ title: Language.translate('Uninstall Failed'), msg: msg }) + Router.focusWidget('FailOk') + } + + $showLaunchError({ name, error }) { + const appName = name || Language.translate('App') + let msg = Language.translate('Something went wrong while launching') + ` "${appName}". ` + Language.translate('Please check the internet and remaining setup.') + if (error) { + msg += ' ' + Language.translate('Error') + `: ${error}` + } + this.widgets.failok.notify({ title: Language.translate('Launch Failed'), msg: msg }) + Router.focusWidget('FailOk') } /** @@ -926,7 +964,8 @@ export default class MainView extends Lightning.Component { } else if (applicationType === 'DAC') { // Launch DAC app using startDACApp if (!GLOBALS.IsConnectedToInternet) { - this.fireAncestors('$showNetworkError') + console.log('No internet connection. Cannot launch DAC app.') + this.$showNetworkError() return } let dacApp = { @@ -937,7 +976,14 @@ export default class MainView extends Lightning.Component { url: uri } this.LOG('Launching DAC app from My Apps: ' + JSON.stringify(dacApp)) - startDACApp(dacApp) + try { + const launched = await startDACApp(dacApp) + if (!launched) { + this.$showLaunchError({ name: appData.displayName }) + } + } catch (err) { + this.$showLaunchError({ name: appData.displayName, error: err.message || err }) + } } } }, @@ -1031,14 +1077,10 @@ export default class MainView extends Lightning.Component { Router.focusWidget('Menu') } } - async _handleEnter() { + _handleEnter() { if (Router.isNavigating()) return; - this.LOG("MainView: internetConnectivity " + JSON.stringify(GLOBALS.IsConnectedToInternet)); - let params ={url: this.tag('TVShows').items[this.tag('TVShows').index].data.uri, - } - if (GLOBALS.IsConnectedToInternet) { - Router.navigate("player",params) - } + this.widgets.failok.notify({ title: Language.translate('Not Supported'), msg: Language.translate('VOD feature is not supported.') }) + Router.focusWidget('FailOk') } $exit() { this.tag('Text3').text.fontStyle = 'normal' diff --git a/accelerator-home-ui/src/views/Menu.js b/accelerator-home-ui/src/views/Menu.js index dadb6b8..deb481b 100644 --- a/accelerator-home-ui/src/views/Menu.js +++ b/accelerator-home-ui/src/views/Menu.js @@ -27,11 +27,11 @@ var route = { Router.navigate('menu') Router.focusPage() }, + // 1: () => { + // Router.navigate('epg') + // Router.focusPage() + // }, 1: () => { - Router.navigate('epg') - Router.focusPage() - }, - 2: () => { Router.navigate('appinfo') Router.focusPage() }, diff --git a/accelerator-home-ui/static/data/SidePanelInfo.js b/accelerator-home-ui/static/data/SidePanelInfo.js index 99f24e3..d39a43d 100644 --- a/accelerator-home-ui/static/data/SidePanelInfo.js +++ b/accelerator-home-ui/static/data/SidePanelInfo.js @@ -24,10 +24,10 @@ export var sidePanelInfo = [ title: 'Apps', url: '/images/sidePanel/menu.png', }, - { - title: 'EPG', - url: '/images/sidePanel/metro.png', - }, + // { + // title: 'EPG', + // url: '/images/sidePanel/metro.png', + // }, { title: 'AppInfo', url: '/images/sidePanel/settings.png', diff --git a/accelerator-home-ui/static/images/RDKLogo.png b/accelerator-home-ui/static/images/RDKLogo.png index 566bb3e..d73e152 100644 Binary files a/accelerator-home-ui/static/images/RDKLogo.png and b/accelerator-home-ui/static/images/RDKLogo.png differ diff --git a/accelerator-home-ui/static/images/Screensaver.mp4 b/accelerator-home-ui/static/images/Screensaver.mp4 new file mode 100644 index 0000000..a8176d6 Binary files /dev/null and b/accelerator-home-ui/static/images/Screensaver.mp4 differ diff --git a/accelerator-home-ui/static/images/splash/RDKLogo.png b/accelerator-home-ui/static/images/splash/RDKLogo.png index 63669f8..045d614 100644 Binary files a/accelerator-home-ui/static/images/splash/RDKLogo.png and b/accelerator-home-ui/static/images/splash/RDKLogo.png differ diff --git a/accelerator-home-ui/static/language/translations/en.json b/accelerator-home-ui/static/language/translations/en.json index 427ed25..aa9dbd9 100644 --- a/accelerator-home-ui/static/language/translations/en.json +++ b/accelerator-home-ui/static/language/translations/en.json @@ -1,6 +1,7 @@ { "en" : "English", "es": "Spanish", + "OK": "OK", "home": "Home", "click to launch": "click to launch", "wifi": "WiFi Settings", @@ -123,5 +124,16 @@ "INVALID_CREDENTIALS - The connection failed due to invalid credentials":"", "NO_SSID - The SSID does not exist":"", "UNKNOWN - Any other error":"", - "Configuring as default":"Configuring as default" + "Configuring as default":"Configuring as default", + "Loading...":"Loading...", + "Authenticating...":"Authenticating...", + "Unknown":"Unknown", + "Unavailable":"Unavailable", + "App Catalog URL is not set":"App Catalog URL is not set", + "Unable to retrieve App Catalog URL":"Unable to retrieve App Catalog URL", + "Authentication failed. Please try again.":"Authentication failed. Please try again.", + "Connect to the Application Catalog":"Connect to the Application Catalog", + "App Catalog URL":"App Catalog URL", + "Press OK to enter Username":"Press OK to enter Username", + "Exit":"Exit" } \ No newline at end of file diff --git a/accelerator-home-ui/static/language/translations/es.json b/accelerator-home-ui/static/language/translations/es.json index 49191c1..d856c63 100644 --- a/accelerator-home-ui/static/language/translations/es.json +++ b/accelerator-home-ui/static/language/translations/es.json @@ -282,5 +282,27 @@ "TTS Endpoint":"Punto final TTS", "WiFi Status":"Estado WiFi", "Error Code :":"Código de error:", - "Error Msg :":"Mensaje de error:" + "Error Msg :":"Mensaje de error:", + "Recommended Apps":"Aplicaciones recomendadas", + "More Apps":"Más aplicaciones", + "Installed Apps":"Aplicaciones instaladas", + "Launch":"Iniciar", + "Uninstall":"Desinstalar", + "Update":"Actualizar", + "Connect to the Application Catalog":"Conectar al Catálogo de Aplicaciones", + "No Apps Installed":"No hay aplicaciones instaladas", + "Manage your installed applications":"Administre sus aplicaciones instaladas", + "Are you sure you want to uninstall this app?":"¿Está seguro de que desea desinstalar esta aplicación?", + "Press OK to enter Username":"Presione OK para ingresar el nombre de usuario", + "Username":"Nombre de usuario", + "Downloading":"Descargando", + "Authentication failed. Please try again.":"Autenticación fallida. Por favor, inténtelo de nuevo.", + "Exit":"Salir", + "App Catalog URL":"URL del catálogo de aplicaciones", + "Loading...":"Cargando...", + "Authenticating...":"Autenticando...", + "Unknown":"Desconocido", + "Unavailable":"No disponible", + "App Catalog URL is not set":"La URL del catálogo de aplicaciones no está configurada", + "Unable to retrieve App Catalog URL":"No se pudo obtener la URL del catálogo de aplicaciones" } diff --git a/bolt/package-configs/CHANGELOG.md b/bolt/package-configs/CHANGELOG.md new file mode 100644 index 0000000..569d99a --- /dev/null +++ b/bolt/package-configs/CHANGELOG.md @@ -0,0 +1,348 @@ +### Changelog + +All notable changes to this project will be documented in this file. Dates are displayed in UTC. + +Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). + +#### [6.0.12](https://github.com/rdkcentral/rdke-refui/compare/6.0.9...6.0.12) + +- 708,2245 -[RefUI] Not all UI texts are translated to Spanish [`#195`](https://github.com/rdkcentral/rdke-refui/pull/195) +- RDKEAPPRT-875 Volume Overlay Missing and Volume Keys Unresponsive During Video Playback [`#194`](https://github.com/rdkcentral/rdke-refui/pull/194) +- RDKEAPPRT-713 Device enters Standby instead of Deep Sleep when EnergySaver is enabled in UI [`#192`](https://github.com/rdkcentral/rdke-refui/pull/192) +- Merge tag '6.0.9' into develop [`6a31619`](https://github.com/rdkcentral/rdke-refui/commit/6a316192865b993a7b14d5e8921e9a06fe1522e4) + +#### [6.0.9](https://github.com/rdkcentral/rdke-refui/compare/6.0.8...6.0.9) + +> 29 April 2026 + +- RDKEAPPRT-741: Upgrade the depends - wpe version [`#190`](https://github.com/rdkcentral/rdke-refui/pull/190) +- RDKEAPPRT-741 Changelog updates and refui version updates for 6.0.9 [`a8fdfeb`](https://github.com/rdkcentral/rdke-refui/commit/a8fdfebd0ec5e24d9507b1b13477ae966054e305) +- Merge tag '6.0.8' into develop [`2a946cc`](https://github.com/rdkcentral/rdke-refui/commit/2a946ccca509b994c18e36b96017cf5cdeaaa9d5) + +#### [6.0.8](https://github.com/rdkcentral/rdke-refui/compare/6.0.7...6.0.8) + +> 20 April 2026 + +- RDKMVE-1860 Guide page is not loading and RDKEAPPRT-693 Wakesrc LAN is not set by default [`#186`](https://github.com/rdkcentral/rdke-refui/pull/186) +- RDKEAPPRT-705 Changelog updates for 6.0.8 [`63623bc`](https://github.com/rdkcentral/rdke-refui/commit/63623bc846a83f068b17fea2c4d3772f5e8e5491) +- Merge tag '6.0.7' into develop [`6d2d811`](https://github.com/rdkcentral/rdke-refui/commit/6d2d811f9ae4e1532816ba83a151bd309c56ad0a) + +#### [6.0.7](https://github.com/rdkcentral/rdke-refui/compare/6.0.3...6.0.7) + +> 17 April 2026 + +- RDKEAPPRT-695 Incorrect IP address displayed on Network Info page after network reconnection and package version update for refui and wpe [`#183`](https://github.com/rdkcentral/rdke-refui/pull/183) +- RDKEAPPRT-684 Sleep Timer and Screen-Saver is not working [`#182`](https://github.com/rdkcentral/rdke-refui/pull/182) +- RDKEAPPRT-692 Handle Keycode 8 after Tatlow RCU pairing during FTI toavoid black screen and contain some fix for RCU pairing and powerstate [`#181`](https://github.com/rdkcentral/rdke-refui/pull/181) +- RDKMVE-2127 From Ref UI Home screen, Pressing Volume +/- leads to UI blank in the display [`#180`](https://github.com/rdkcentral/rdke-refui/pull/180) +- RDKEAPPRT-705 Changelog updates for 6.0.7 [`4b1d5be`](https://github.com/rdkcentral/rdke-refui/commit/4b1d5bef54924bfa99e6a8a62003e155db98b7b4) +- Merge tag '6.0.3' into develop [`c6030f2`](https://github.com/rdkcentral/rdke-refui/commit/c6030f2f54ffc42cd26e0e96688a41b460c13590) + +#### [6.0.3](https://github.com/rdkcentral/rdke-refui/compare/6.0.2...6.0.3) + +> 7 April 2026 + +- Updated the version for refui boltpackage [`#175`](https://github.com/rdkcentral/rdke-refui/pull/175) +- RDKEAPPRT-688 Changelog updates for 6.0.3 [`a64ad51`](https://github.com/rdkcentral/rdke-refui/commit/a64ad5142fef9c1341028d211ade283bb8d58f5b) +- Merge tag '6.0.2' into develop [`7d4582c`](https://github.com/rdkcentral/rdke-refui/commit/7d4582c752991e63442df51fecbaf152e355e4c5) + +#### [6.0.2](https://github.com/rdkcentral/rdke-refui/compare/6.0.1...6.0.2) + +> 7 April 2026 + +- RDKEAPPRT-683: RemoteControl plugin API align with MW APIv3.4.2 [`#171`](https://github.com/rdkcentral/rdke-refui/pull/171) +- RDKEAPPRT-683: Fix the RCU pairing trigger timers [`47df636`](https://github.com/rdkcentral/rdke-refui/commit/47df6367819c67c9bcab0a5ed99fa3007e976d99) +- RDKEAPPRT-683: fix the RCU re scanning logic leak. [`2610642`](https://github.com/rdkcentral/rdke-refui/commit/2610642a37e0d975cfb59ac9d5d4aa498ae4a115) +- /RDKEAPPRT-683: stop the scan triggers after RCU pairing [`34ee6be`](https://github.com/rdkcentral/rdke-refui/commit/34ee6bea00a1aba71dcbc2e969ef5a6d22f2e94c) + +#### [6.0.1](https://github.com/rdkcentral/rdke-refui/compare/6.0.0...6.0.1) + +> 31 March 2026 + +- Feature/rdkeapprt 680 :Update to new RDK logos [`#168`](https://github.com/rdkcentral/rdke-refui/pull/168) +- RDKEAPPRT-682 Changelog and package config version updates for 6.0.1 [`32bbba6`](https://github.com/rdkcentral/rdke-refui/commit/32bbba6f7cde97607cac613f80240a174073c6bf) +- RDKEAPPRT-680 :Update new logo [`83513d8`](https://github.com/rdkcentral/rdke-refui/commit/83513d8d0566d994927583ed7891c655660af97f) +- RDKEAPPRT-680:Update the new logo files [`c2b261f`](https://github.com/rdkcentral/rdke-refui/commit/c2b261ff1ea9e4e72a8750f77652d6f4261775ce) + +### [6.0.0](https://github.com/rdkcentral/rdke-refui/compare/5.0.24...6.0.0) + +> 31 March 2026 + +- To refresh the App store and main view when the authentication done [`#166`](https://github.com/rdkcentral/rdke-refui/pull/166) +- RDKEAPPRT-661 Add support for new authorization in App Catalog [`#165`](https://github.com/rdkcentral/rdke-refui/pull/165) +- RDKEAPPRT-621,606,648,644 fix for Language screen and powerstate issue [`#164`](https://github.com/rdkcentral/rdke-refui/pull/164) +- RDKEAPPRT-646 Create the Username, Password page and add it inside the settings route [`#163`](https://github.com/rdkcentral/rdke-refui/pull/163) +- RDKEAPPRT-645 Add default error overlay when user tries to enter VOD content [`#162`](https://github.com/rdkcentral/rdke-refui/pull/162) +- RDKEAPPRT-612 :Add dac store details via RFC [`#160`](https://github.com/rdkcentral/rdke-refui/pull/160) +- RDKEAPPRT-626,627,628,605,608,622 Fix error and uninstall overlay screen with bug fixes [`#161`](https://github.com/rdkcentral/rdke-refui/pull/161) +- RDKEAPPRT-601,602 App side loading and App side loading and closeApp() function [`#158`](https://github.com/rdkcentral/rdke-refui/pull/158) +- To merge the changes from Feature/app managers to develop [`#157`](https://github.com/rdkcentral/rdke-refui/pull/157) +- RDKEAPPRT-576 Improve focus management [`#155`](https://github.com/rdkcentral/rdke-refui/pull/155) +- RDKEAPPRT-341 App managers intake: abstractions, API migration and YouTube Launch Support [`#146`](https://github.com/rdkcentral/rdke-refui/pull/146) +- RDKEAPPRT-571 Create UI prototype with My Apps, Recommended Apps, VOD Rows and Appinfo (#156) [`eff1a86`](https://github.com/rdkcentral/rdke-refui/commit/eff1a864e55c28ed1c542e26f818d20f082a6dca) +- RDKEAPPRT-538 Add basic integration with the RDK Reference DAC 2.0 App Store (#152) [`82eda3d`](https://github.com/rdkcentral/rdke-refui/commit/82eda3d7b34b80be63bdf3d0cb39d6c3f7f1f681) +- Changes for the error and uninstall overlay screen then some bug fixes also part of this [`749f89d`](https://github.com/rdkcentral/rdke-refui/commit/749f89d0af61e7aab7d96cb70a392e4efb8f8020) + +#### [5.0.24](https://github.com/rdkcentral/rdke-refui/compare/5.0.20...5.0.24) + +> 12 February 2026 + +- RDKEAPPRT-575 [RDKUI] 5.0.24 Merge latest changes from develop to main, create release tag, and publish release. [`#154`](https://github.com/rdkcentral/rdke-refui/pull/154) +- RDKEAPPRT-268 [RDK UI] Replace deprecated APIs for USB Media Device [`#153`](https://github.com/rdkcentral/rdke-refui/pull/153) +- RDKEAPPRT-394 Adopt to New APIs for deprecated ones if not yet [`#151`](https://github.com/rdkcentral/rdke-refui/pull/151) +- RDKEAPPRT-533-[RDK UI] Device is not discovered via DIAL after re-enabling Local Device Discovery option [`#150`](https://github.com/rdkcentral/rdke-refui/pull/150) +- RDKEAPPRT-518 All SSIDs are not visible in FTI SSID selection screen [`#149`](https://github.com/rdkcentral/rdke-refui/pull/149) +- RDKEAPPRT-575 Changelog updates for 5.0.24 [`59d8252`](https://github.com/rdkcentral/rdke-refui/commit/59d8252ac9401f7882716fc5c055346653004996) +- Merge tag '5.0.20' into develop [`4413c1c`](https://github.com/rdkcentral/rdke-refui/commit/4413c1cf7d14b54c8952299b291a44f311d7033e) + +#### [5.0.20](https://github.com/rdkcentral/rdke-refui/compare/5.0.17...5.0.20) + +> 18 December 2025 + +- [RDKUI] 5.0.20 Merge latest changes from develop to main, create release tag, and publish release. [`#147`](https://github.com/rdkcentral/rdke-refui/pull/147) +- RDKEAPPRT-420: Unable to change Sleep timer and energy saver [`#143`](https://github.com/rdkcentral/rdke-refui/pull/143) +- RDKEAPPRT-344- Migrate the New powermanger plugin APIs in UI [`#142`](https://github.com/rdkcentral/rdke-refui/pull/142) +- RDKEAPPRT-358: Once disabled, not able to toggle Local Device Discovery radio to ON state [`#141`](https://github.com/rdkcentral/rdke-refui/pull/141) +- RDKEAPPRT-356 Incorrect behaviors seen after giving wrong credentials for WiFi SSID Or changing the password for a connected SSID [`#140`](https://github.com/rdkcentral/rdke-refui/pull/140) +- [RDKEAPPRT-328] - Use UserSettings instead of UserPreferences for storing currently set UI language [`#139`](https://github.com/rdkcentral/rdke-refui/pull/139) +- RDKEAPPRT-340: Ethernet interface stuck on “Configuring as default” with continuous loader [`#138`](https://github.com/rdkcentral/rdke-refui/pull/138) +- RDKEAPPRT-241 Remove Features Dependent on Deprecated System Plugin APIs and introduced Power manager APIs [`#137`](https://github.com/rdkcentral/rdke-refui/pull/137) +- RDKEAPPRT-262: [RDK UI] Sleep timer value is not reflected in UI [`#136`](https://github.com/rdkcentral/rdke-refui/pull/136) +- RDKEAPPRT-241 Remove Features Dependent on Deprecated System Plugin APIs [`c07106e`](https://github.com/rdkcentral/rdke-refui/commit/c07106edb648a0a7959bb8c4096f6b72041581ac) +- addressed the review comments [`27819d5`](https://github.com/rdkcentral/rdke-refui/commit/27819d567b4692be6ac2bc978fad7c68874d05c9) +- Addressed the review comments [`d0c5c60`](https://github.com/rdkcentral/rdke-refui/commit/d0c5c6055dd988c50bab309eee8b9906a1091617) + +#### [5.0.17](https://github.com/rdkcentral/rdke-refui/compare/5.0.12...5.0.17) + +> 30 October 2025 + +- RDKEAPPRT-356 Incorrect behaviors seen after giving wrong credentials for WiFi SSID Or changing the password for a connected SSID [`#140`](https://github.com/rdkcentral/rdke-refui/pull/140) +- RDKEAPPRT-377 Changelog updates for 5.0.17 [`c4087fe`](https://github.com/rdkcentral/rdke-refui/commit/c4087fe3a6c759fa4e1c5bad8675718346e2642d) + +#### [5.0.12](https://github.com/rdkcentral/rdke-refui/compare/5.0.9...5.0.12) + +> 17 October 2025 + +- RDKEAPPRT-331 [RDKUI] 5.0.12 Merge latest changes from develop to main, create release tag, and publish release. [`#135`](https://github.com/rdkcentral/rdke-refui/pull/135) +- RDKEAPPRT-319 [Netflix7] Verify and fix DIAL config for Netflix,Amazon [`#134`](https://github.com/rdkcentral/rdke-refui/pull/134) +- RDKEAPPRT-139 [RDK UI] DAC APPS Section UI Freeze - No Apps List & Remote Unresponsive, Requires Device Restart [`#133`](https://github.com/rdkcentral/rdke-refui/pull/133) +- RDKEAPPRT-298 Fix DIAL CORS setup for YouTube apps [`#132`](https://github.com/rdkcentral/rdke-refui/pull/132) +- RDKEAPPRT-319 [Netflix7] Verify and fix DIAL config for Netflix [`c6d7e7d`](https://github.com/rdkcentral/rdke-refui/commit/c6d7e7d8e55ee466165fba5aec5de7d5e99fc73c) +- RDKEAPPRT-331 Changelog updates for 5.0.12 [`fe0a0bc`](https://github.com/rdkcentral/rdke-refui/commit/fe0a0bc05f3957581c7d74c11cb73a4853d93360) +- RDKEAPPRT-298 [YT25][YTS] Several YouTube DIAL Protocol tests failed [`20f5e0f`](https://github.com/rdkcentral/rdke-refui/commit/20f5e0f65fb2234c826cd816158cfd0664f40ffe) + +#### [5.0.9](https://github.com/rdkcentral/rdke-refui/compare/5.0.7...5.0.9) + +> 9 October 2025 + +- RDKEAPPRT-315 [RDKUI] 5.0.9 Merge latest changes from develop to main, create release tag, and publish release. [`#131`](https://github.com/rdkcentral/rdke-refui/pull/131) +- RDKEAPPRT-312 [Netflix7][RTK] App state not reported to DIAL and Hide/stop fails [`#130`](https://github.com/rdkcentral/rdke-refui/pull/130) +- RDKEAPPRT-266-[YT25] Handle Netflix, YouTube and Prime Video buttons [`#129`](https://github.com/rdkcentral/rdke-refui/pull/129) +- RDKEAPPRT-315 Changelog updates for 5.0.9 [`d55c528`](https://github.com/rdkcentral/rdke-refui/commit/d55c528e0d2d7d64ecbcf7796f4e1ea1690bc17a) +- RDKEAPPRT-312 [Netflix7][RTK] App state not reported to DIAL and Hide/stop [`05c29e7`](https://github.com/rdkcentral/rdke-refui/commit/05c29e779631c6448cdfb022ccf30b3d366cfa2a) +- Merge tag '5.0.7' into develop [`21fa916`](https://github.com/rdkcentral/rdke-refui/commit/21fa916e0327babade062657691f38f6103f1b42) + +#### [5.0.7](https://github.com/rdkcentral/rdke-refui/compare/5.0.1...5.0.7) + +> 6 October 2025 + +- RDKEAPPRT-275 [RDKUI] 5.0.7 Merge latest changes from develop to main, create release tag, and publish release. [`#127`](https://github.com/rdkcentral/rdke-refui/pull/127) +- RDKEAPPRT-251 FTI Page – Ethernet Option Shows ‘Not Connected’ Error Despite Active Connection [`#126`](https://github.com/rdkcentral/rdke-refui/pull/126) +- RDKEAPPRT-221 [RDK UI] ResidentApp plugin crashes when try to start playback of some Featured Video on Demand assets00~[RDK UI] ResidentApp plugin crashes when try to start playback of some Featured Video on Demand assets [`#124`](https://github.com/rdkcentral/rdke-refui/pull/124) +- Deploy cla action [`#125`](https://github.com/rdkcentral/rdke-refui/pull/125) +- RDKEAPPRT-236 : Activate LISA plugin from residentapp.service [`#123`](https://github.com/rdkcentral/rdke-refui/pull/123) +- RDKEAPPRT-230-[RDK UI] [DIAL] Update Netflix name field in application params [`#122`](https://github.com/rdkcentral/rdke-refui/pull/122) +- RDKEAPPRT-225,226 [RDK UI][Miracast] Pressing any RCU button except OK on miracast connection acceptance screen deny connection,[RDK UI][Miracast] It is not possible to reconnect mobile device using miracast and fixed Minor dial fix [`#121`](https://github.com/rdkcentral/rdke-refui/pull/121) +- RDKEAPPRT-209,208 [REFUI][DIAL] Adopt to the XCast plugin's deeplink payload change,[REFUI][DIAL] The XCAST initializaion flow is incorrect [`#120`](https://github.com/rdkcentral/rdke-refui/pull/120) +- Updated the APP.js Ident [`6f2c44b`](https://github.com/rdkcentral/rdke-refui/commit/6f2c44b6f427b58ec124b2ed1186c1c4a6955816) +- Final Dial fix [`c2f6984`](https://github.com/rdkcentral/rdke-refui/commit/c2f6984e3bff937c07f41ad90f7cd01d59f81113) +- RDKEAPPRT-221 [RDK UI] ResidentApp plugin crashes when try to [`301ed96`](https://github.com/rdkcentral/rdke-refui/commit/301ed9655172434008d8f3fe59681b808b6062ab) + +### [5.0.1](https://github.com/rdkcentral/rdke-refui/compare/4.7.19...5.0.1) + +> 10 September 2025 + +- RDKEAPPRT-189 [RDKE] Prepare Release Refui 5.0.1 [`#119`](https://github.com/rdkcentral/rdke-refui/pull/119) +- RDKUI-114 [RDK UI] Replace legacy network APIs with networkmanager APIs [`#118`](https://github.com/rdkcentral/rdke-refui/pull/118) +- RDKUI -848 unable to debug refui, many console message in source code do not result in actual log line on journalctl [`#116`](https://github.com/rdkcentral/rdke-refui/pull/116) +- RDKUI-862,865 Clear Cookies and App Data option Failed to Remove App Data and Logins,In overlay unable to see the slider in clear cookies and app data row [`#115`](https://github.com/rdkcentral/rdke-refui/pull/115) +- RDKUI -744 [BCM][Rpi][AML][RTK]Unable to unmute the device after increasing the volume [`#114`](https://github.com/rdkcentral/rdke-refui/pull/114) +- RDKUI - 861 No proper error message shown for wrong WiFi password at FTI page [`#113`](https://github.com/rdkcentral/rdke-refui/pull/113) +- RDKUI-856, RDKUI-855: WiFi Error message to match current Language, adjust the TEXT overlap. [`#112`](https://github.com/rdkcentral/rdke-refui/pull/112) +- RDKUI-859 Title in Settings / Other Settings / Advanced Settings / TTS is not proper. Also text is not changed to Spanish [`#111`](https://github.com/rdkcentral/rdke-refui/pull/111) +- RDKUI -857 When switching from one ssid to another from CONNECION_LOST error message is seen [`#110`](https://github.com/rdkcentral/rdke-refui/pull/110) +- RDKUI-860: adopt devicetype ontology change - IpTv [`#109`](https://github.com/rdkcentral/rdke-refui/pull/109) +- Deploy cla action [`#104`](https://github.com/rdkcentral/rdke-refui/pull/104) +- RDKUI-854 Modify UI logic for Netflix URL Formation [`#108`](https://github.com/rdkcentral/rdke-refui/pull/108) +- RDKUI-838 [RDKE] After launching the app from UI, initial key press is not working [`#107`](https://github.com/rdkcentral/rdke-refui/pull/107) +- changes added for all screen and apis [`6a5e716`](https://github.com/rdkcentral/rdke-refui/commit/6a5e71680ee9b768d5988d211500ca205297aad4) +- Added console abstraction for Api folder and some of the screens [`b970307`](https://github.com/rdkcentral/rdke-refui/commit/b970307d12ae4c93e97cd5fe6f80a25ce1451236) +- Networkmanager APIs migrated to these pages [`c5389d5`](https://github.com/rdkcentral/rdke-refui/commit/c5389d5bdc85aba679cd540d617f4390f7822e03) + +#### [4.7.19](https://github.com/rdkcentral/rdke-refui/compare/4.7.18...4.7.19) + +> 25 June 2025 + +- RDKUI-853 [RDKE] Prepare Release Refui 4.7.19 [`#106`](https://github.com/rdkcentral/rdke-refui/pull/106) +- RDKUI-852: Correctly set language during FTI [`#105`](https://github.com/rdkcentral/rdke-refui/pull/105) +- RDKUI-853 Changelog updates for 4.7.19 [`6893995`](https://github.com/rdkcentral/rdke-refui/commit/68939952bd7dd06ea6f98a89e30d29da2c88a6ce) +- Merge tag '4.7.18' into develop [`9eec0fd`](https://github.com/rdkcentral/rdke-refui/commit/9eec0fdb9bf6ddeabc9034bc6b99050b0dd9e704) + +#### [4.7.18](https://github.com/rdkcentral/rdke-refui/compare/4.7.15...4.7.18) + +> 24 June 2025 + +- RDKUI -850 [RDKE] Prepare Release Refui 4.7.18 [`#103`](https://github.com/rdkcentral/rdke-refui/pull/103) +- FTI: Update UI langauge and localstorage with default selected value [`#102`](https://github.com/rdkcentral/rdke-refui/pull/102) +- RDKUI- 847 [RDKE][DAC] YouTube 2025 (RPI4) DAC App is not listed in the App Catalog Page [`#101`](https://github.com/rdkcentral/rdke-refui/pull/101) +- RDKUI-849: [RDKE][AVPK] Remove Amazon hibernation on HDMI plugin disconnection/change [`#100`](https://github.com/rdkcentral/rdke-refui/pull/100) +- RDKUI- 847 [RDKE][DAC] YouTube 2025 (RPI4) DAC App is not listed in the App Catalog [`b59090f`](https://github.com/rdkcentral/rdke-refui/commit/b59090f6f5e1697635cfdde81251184933c1b08b) +- RDKUI-850 Changelog updates for 4.7.18 [`da54e6c`](https://github.com/rdkcentral/rdke-refui/commit/da54e6c0532022ab347a07275dbd845e0a1c9faf) +- Update version [`b246c8a`](https://github.com/rdkcentral/rdke-refui/commit/b246c8a7242c780b229db57b46ff7f6d1ab4eceb) + +#### [4.7.15](https://github.com/rdkcentral/rdke-refui/compare/4.7.9...4.7.15) + +> 13 June 2025 + +- RDKUI-845 [RDKE] Prepare Release Refui 4.7.15 [`#97`](https://github.com/rdkcentral/rdke-refui/pull/97) +- RDKUI 844 [AVPPK] Incorrect app name in the appBundle.js and fix for FTI Wifi, language issue [`#96`](https://github.com/rdkcentral/rdke-refui/pull/96) +- RDKUI-806 [RDKE] FTI disappears after few seconds without any user interaction [`#95`](https://github.com/rdkcentral/rdke-refui/pull/95) +- RDKUI 822-[RDKE][YT25] Add handling of DAB KEY_EXIT event [`#94`](https://github.com/rdkcentral/rdke-refui/pull/94) +- RDKUI-829: add the missing WiFi error code [`#91`](https://github.com/rdkcentral/rdke-refui/pull/91) +- RDKUI-835: Create TTS Screen to toggle TTS support and input endpoint URL [`#86`](https://github.com/rdkcentral/rdke-refui/pull/86) +- RDKUI 833-Align UI with XCast naming update for Netflix [`#85`](https://github.com/rdkcentral/rdke-refui/pull/85) +- RDKUI-837 [RPI][AL] setVisibility API params from UI is wrong when triggered from 'onApplicationLaunched' event [`#84`](https://github.com/rdkcentral/rdke-refui/pull/84) +- Basic TTS screen and switch working. Started work on adding UserSettings API [`0680b3f`](https://github.com/rdkcentral/rdke-refui/commit/0680b3fb596fde3bb948f23a3805862427f238a9) +- Enable option to enter TTS endpoint from the UI [`c5fe5c1`](https://github.com/rdkcentral/rdke-refui/commit/c5fe5c1995a5adbbc744629ddeeee96c21d49e1a) +- RDKUI 806 -Refactored the storage.get logic for setup and [`bec2d73`](https://github.com/rdkcentral/rdke-refui/commit/bec2d731aaff3c2757ce107472a08cce605e023b) + +#### [4.7.9](https://github.com/rdkcentral/rdke-refui/compare/4.7.5...4.7.9) + +> 28 May 2025 + +- RDKUI-834 [RDKE] Prepare Release Refui 4.7.9 [`#83`](https://github.com/rdkcentral/rdke-refui/pull/83) +- RDKUI-832 [RDKE][YT25] Do not enter deep sleep when Fast Forward key is pressed [`#82`](https://github.com/rdkcentral/rdke-refui/pull/82) +- PREMIUMAPP-3286: Autostart TTS plugin [`#81`](https://github.com/rdkcentral/rdke-refui/pull/81) +- RDKUI-831 Unable to see the DAC apps by adding the configure URL in LISA.json [`#79`](https://github.com/rdkcentral/rdke-refui/pull/79) +- RDKUI-829 Getting Unexpected ErrorCode from the onError event from WIFI plugin [`#78`](https://github.com/rdkcentral/rdke-refui/pull/78) +- RDKUI-826 Miracast message language is not changed to Spanish [`#77`](https://github.com/rdkcentral/rdke-refui/pull/77) +- RDKUI-834 Changelog updates for 4.7.9 [`0c6397d`](https://github.com/rdkcentral/rdke-refui/commit/0c6397dd1b72a9b99076ab376008838d801937b1) +- Merge tag '4.7.5' into develop [`7b47d8d`](https://github.com/rdkcentral/rdke-refui/commit/7b47d8dd4f90e719909f456a70bf51cde3e9b9a8) + +#### [4.7.5](https://github.com/rdkcentral/rdke-refui/compare/4.7.1...4.7.5) + +> 14 May 2025 + +- RDKUI-828 [RDKE] Prepare Release Refui 4.7.5 [`#74`](https://github.com/rdkcentral/rdke-refui/pull/74) +- RDKUI-827 After installing DAC bundle, cobalt is still not displayed in UI and added functionality under ApplicationTerminated,ApplicationResumed,ApplicationLaunched [`#73`](https://github.com/rdkcentral/rdke-refui/pull/73) +- RDKUI 816-[RDKE] Remove deprecated plugin dependency [`#72`](https://github.com/rdkcentral/rdke-refui/pull/72) +- RDKUI-819 RDK UI Side Pane icon : Selectio indicator pointing to Incorrect UI Item [`#71`](https://github.com/rdkcentral/rdke-refui/pull/71) +- RDKUI-821 Unable to see the connected remote Details in the Vocie Remote Control Page [`#70`](https://github.com/rdkcentral/rdke-refui/pull/70) +- RDKUI-828: Changelog updates for 4.7.5 [`a17cb5a`](https://github.com/rdkcentral/rdke-refui/commit/a17cb5acad7be3b907f518bdd611826b48b87a83) +- To update the Line number in the template [`5c69324`](https://github.com/rdkcentral/rdke-refui/commit/5c693240b79f3b0d32b021d7be26ee03188b8635) +- Removed duplicate console warn [`68fd55c`](https://github.com/rdkcentral/rdke-refui/commit/68fd55cfbe0615fba3a24e83870961d549f1a66f) + +#### [4.7.1](https://github.com/rdkcentral/rdke-refui/compare/4.7.0...4.7.1) + +> 30 April 2025 + +- RefUI release 4.7.1 [`#67`](https://github.com/rdkcentral/rdke-refui/pull/67) +- RDKUI-820 [RDKE] [XCAST] Need to change the URL formation logic for Xcast [`#66`](https://github.com/rdkcentral/rdke-refui/pull/66) +- RDKUI-825: Changelog updates for 4.7.1 [`7e2b200`](https://github.com/rdkcentral/rdke-refui/commit/7e2b200a489ee3a7d8ad186a152d2322aafcb129) +- Merge tag '4.7.0' into develop [`d74d65d`](https://github.com/rdkcentral/rdke-refui/commit/d74d65de8f82c8e320100c07c5334766a8d720f4) + +#### [4.7.0](https://github.com/rdkcentral/rdke-refui/compare/4.6.6...4.7.0) + +> 25 April 2025 + +- RDKUI-817: update documentation userfriendly [`#63`](https://github.com/rdkcentral/rdke-refui/pull/63) +- RDKUI-817: update documentation userfriendly [`#62`](https://github.com/rdkcentral/rdke-refui/pull/62) +- RDKUI-817: refui v4.7.0 release [`#60`](https://github.com/rdkcentral/rdke-refui/pull/60) +- RDKUI-807 [RDKE] Analyze the impact of the unavailability of the "LocationSync" plugin [`#59`](https://github.com/rdkcentral/rdke-refui/pull/59) +- PREMIUMAPP-3280 Fix YouTube state synchronization in DIAL [`#58`](https://github.com/rdkcentral/rdke-refui/pull/58) +- 814-[RDKE][YT25] Enable network standby mode [`#57`](https://github.com/rdkcentral/rdke-refui/pull/57) +- RDKUI-805 [RDKE] Use result.status.netTypeSupported response payload in org.rdk.RemoteControl.startPairing instead of hardcoded value [`#56`](https://github.com/rdkcentral/rdke-refui/pull/56) +- RKUI-803 Wifi error is popping up even though ethernet is connected and set as the default interface [`#55`](https://github.com/rdkcentral/rdke-refui/pull/55) +- PREMIUMAPP-3220 [AMLS905X4-2040] : [RDKE][YT25] OCDM plugin is not activated in RDKE builds [`#54`](https://github.com/rdkcentral/rdke-refui/pull/54) +- RDKUI-798 Only 15 SSIDs are visible in the Wifi screen of User On boarding [`#53`](https://github.com/rdkcentral/rdke-refui/pull/53) +- [RDKE] Use result.status.netTypeSupported response payload in org.rdk.RemoteControl.startPairing instead of hardcoded value [`513bf49`](https://github.com/rdkcentral/rdke-refui/commit/513bf493841602da374a1e11cfcf9d503f737d54) +- RDKUI-817: Changelog updates for 4.7.0 [`7206146`](https://github.com/rdkcentral/rdke-refui/commit/720614690f09b2734b83fe28a9249f4d607108b5) +- Addressed Review comments [`5b45c77`](https://github.com/rdkcentral/rdke-refui/commit/5b45c77e6bbc0d10d898925ec8c3fc3e42e2a85b) + +#### [4.6.6](https://github.com/rdkcentral/rdke-refui/compare/4.6.5...4.6.6) + +> 7 April 2025 + +- To release UI version 4.6.6 [`#50`](https://github.com/rdkcentral/rdke-refui/pull/50) +- AMLS905X4-2052 : [RDKE][YT25] PlayerInfo and DisplayInfo plugin is not activated in RDKE builds [`#47`](https://github.com/rdkcentral/rdke-refui/pull/47) +- [RDKE][DIAL] Need to invoke addkeyintercepts api while launching YT and removekeyintercept on closing [`#48`](https://github.com/rdkcentral/rdke-refui/pull/48) +- RDKUI-799: refui v4.6.6 release [`831296b`](https://github.com/rdkcentral/rdke-refui/commit/831296bb46b2fed4dda722dd26ef6e80936533d5) +- 797-[RDKE][DIAL] Need to invoke addkeyintercepts api while launching YT and removekeyintercept on closing [`0bdc070`](https://github.com/rdkcentral/rdke-refui/commit/0bdc070e27ecdda0f94a942e6a98ccc66841fc76) +- RDKUI-797: do not invoke RDKShellApis.removeKeyIntercept on onApplicationDisconnected [`364a19a`](https://github.com/rdkcentral/rdke-refui/commit/364a19a065fe6ef964f0593f4b2bd6a1636cb008) + +#### [4.6.5](https://github.com/rdkcentral/rdke-refui/compare/4.6.2...4.6.5) + +> 18 March 2025 + +- RDKEMW-1766, RDKUI-789, RDKUI-784, RDKUI-785, RDKUI-786: UI v4.6.5 to main [`#42`](https://github.com/rdkcentral/rdke-refui/pull/42) +- RDKUI-793 [`#41`](https://github.com/rdkcentral/rdke-refui/pull/41) +- RDKUI-789 [`#40`](https://github.com/rdkcentral/rdke-refui/pull/40) +- 784,785,786 [`#38`](https://github.com/rdkcentral/rdke-refui/pull/38) +- RDKEMW-1766: add power related systemd service dependencies [`#36`](https://github.com/rdkcentral/rdke-refui/pull/36) +- 784-UI Issues in Join other network page [`2b8c667`](https://github.com/rdkcentral/rdke-refui/commit/2b8c6675f5f96dc2b3469de955529f947f5082f5) + +#### [4.6.2](https://github.com/rdkcentral/rdke-refui/compare/4.6.1...4.6.2) + +> 28 February 2025 + +- Intake UI focus lont fix and build time optimization [`#35`](https://github.com/rdkcentral/rdke-refui/pull/35) +- Update residentApp.sh to remove bash dependency [`#34`](https://github.com/rdkcentral/rdke-refui/pull/34) +- 769-Focus issues observed in RDK UI [`#33`](https://github.com/rdkcentral/rdke-refui/pull/33) + +#### [4.6.1](https://github.com/rdkcentral/rdke-refui/compare/4.6.0...4.6.1) + +> 13 February 2025 + +- RDKUI-766: Enable miracast support and optimize BT scan triggers [`#32`](https://github.com/rdkcentral/rdke-refui/pull/32) +- 776-Remove voice remote pairing from background and fix for the language screen [`#31`](https://github.com/rdkcentral/rdke-refui/pull/31) +- To Bringback the miracast changes [`#30`](https://github.com/rdkcentral/rdke-refui/pull/30) +- 776-Remove voice remote pairing from background and fix for the [`702628a`](https://github.com/rdkcentral/rdke-refui/commit/702628ae2e45134458773f49298e4972a2706892) + +#### [4.6.0](https://github.com/rdkcentral/rdke-refui/compare/4.5.7...4.6.0) + +> 5 February 2025 + +- RDKUI-774: UIv 4.6.0 to main and MaintenanceMgr activation support [`#27`](https://github.com/rdkcentral/rdke-refui/pull/27) +- Version Updated to 4.6.0 [`#29`](https://github.com/rdkcentral/rdke-refui/pull/29) +- To Revert Miracast related changes [`#28`](https://github.com/rdkcentral/rdke-refui/pull/28) +- 774-To Update URL links for Feature Video on demand row [`#25`](https://github.com/rdkcentral/rdke-refui/pull/25) +- RDKVREFPLT-4612: activate MaintenanceManager plugin [`#26`](https://github.com/rdkcentral/rdke-refui/pull/26) +- 771,772-Design and integrate notification screen for events and the player functionality [`#24`](https://github.com/rdkcentral/rdke-refui/pull/24) +- RDKUI-770: class abstraction of Miracast related plugins [`#23`](https://github.com/rdkcentral/rdke-refui/pull/23) +- Navigator UI base code v4.5.7 [`#7`](https://github.com/rdkcentral/rdke-refui/pull/7) +- 768-Alexa related implementation fine-tuning to reduce API failures [`#22`](https://github.com/rdkcentral/rdke-refui/pull/22) +- adding package-lock.json [`a14b2b9`](https://github.com/rdkcentral/rdke-refui/commit/a14b2b9cee850564ac2cfb1991eb80939a576c6c) +- Revert "Merge pull request #23 from rdkcentral/Miracast" [`1401f4d`](https://github.com/rdkcentral/rdke-refui/commit/1401f4dfd979a7169bb6a934574cfc3c6fa043c5) +- 766- As part of this ticket abstracted the API and Event Listners for [`e89e41a`](https://github.com/rdkcentral/rdke-refui/commit/e89e41a881e488f69beac1d761a8a21ab8feebb3) + +#### 4.5.7 + +> 13 January 2025 + +- RDKUI-753: Remove the dist bundle [`#20`](https://github.com/rdkcentral/rdke-refui/pull/20) +- REFPLTV-2593: Activate ocicontainer plugin for DAC apps [`#18`](https://github.com/rdkcentral/rdke-refui/pull/18) +- RDKUI-759: isolating functionality from UI [`#17`](https://github.com/rdkcentral/rdke-refui/pull/17) +- Feature/rdkvrefplt 4241 refui refactoring [`#16`](https://github.com/rdkcentral/rdke-refui/pull/16) +- 761-YouTube App lifecycle handling based on HDMI source input change … [`#15`](https://github.com/rdkcentral/rdke-refui/pull/15) +- RDKUI-739: change device powerstate to laskknown or ON [`#12`](https://github.com/rdkcentral/rdke-refui/pull/12) +- 749,748-[DAC Apps]Simultaneous downloads of apps didn't happen from UI and Same SSID is listed multiple times in the UI [`#10`](https://github.com/rdkcentral/rdke-refui/pull/10) +- RDKUI-758 : UI stuck at RDK logo for platforms built without bluetooth [`#9`](https://github.com/rdkcentral/rdke-refui/pull/9) +- Addressed RDKUI-750,746 [`#8`](https://github.com/rdkcentral/rdke-refui/pull/8) +- RDKUI-747 : Deactivate/DIAL stop app after a DIAL Hide [`#6`](https://github.com/rdkcentral/rdke-refui/pull/6) +- RDKUI-755: update ReadMe with App Status [`#4`](https://github.com/rdkcentral/rdke-refui/pull/4) +- Update README.md [`#2`](https://github.com/rdkcentral/rdke-refui/pull/2) +- RDKUI-755: add COPYING support [`#3`](https://github.com/rdkcentral/rdke-refui/pull/3) +- Integrating the source code of opensource/RDK_apps into RDKE-refui repo [`#1`](https://github.com/rdkcentral/rdke-refui/pull/1) +- Remove the dist bundle [`4f4b829`](https://github.com/rdkcentral/rdke-refui/commit/4f4b829052450b9cde89f028682c474f6d7607ae) +- RDKVREFPLT-4378: add ermgr.service dependency for UI [`214f26b`](https://github.com/rdkcentral/rdke-refui/commit/214f26ba7a9f42aa2ad8a9b85cc0ac97369348cb) +- Removing the unwanted folders [`4ac1fc4`](https://github.com/rdkcentral/rdke-refui/commit/4ac1fc4ce91acfde8e09062f7b02fb3891cfd501) diff --git a/bolt/package-configs/com.rdkcentral.refui.json b/bolt/package-configs/com.rdkcentral.refui.json index 6e1a209..d611e07 100644 --- a/bolt/package-configs/com.rdkcentral.refui.json +++ b/bolt/package-configs/com.rdkcentral.refui.json @@ -1,12 +1,12 @@ { "id": "com.rdkcentral.refui", - "version": "0.0.1", - "versionName": "develop", + "version": "6.0.16", + "versionName": "6.0.16", "name": "RDK Ref UI Home Screen", "packageType": "application", - "entryPoint": "file:///usr/share/refui/index.html", + "entryPoint": "--lightning --dev file:///usr/share/refui/index.html", "dependencies": { - "com.rdkcentral.wpe-develop": "0.0.1" + "com.rdkcentral.wpe": "~0.3.1" }, "permissions": [ "urn:rdk:permission:home-app",