diff --git a/app/AppViews.js b/app/AppViews.js index c4b334801..0e11da23b 100644 --- a/app/AppViews.js +++ b/app/AppViews.js @@ -45,6 +45,7 @@ SDL.AppViews = Em.ContainerView.extend( SDL.HomeView, SDL.MediaView, SDL.NavigationAppView, + SDL.WebEngineView, SDL.InfoView, SDL.PhoneView, SDL.ClimateView, @@ -69,6 +70,7 @@ SDL.AppViews = Em.ContainerView.extend( SDL.BottomControls, SDL.TTSPopUp, SDL.AlertPopUp, + SDL.SubtleAlertPopUp, SDL.ServiceUpdatePopUp, SDL.AlertManeuverPopUp, SDL.AudioPassThruPopUp, diff --git a/app/Flags.js b/app/Flags.js index c84a50fdc..0fe90c956 100644 --- a/app/Flags.js +++ b/app/Flags.js @@ -54,7 +54,6 @@ FLAGS = Em.Object.create( Navigation: null, CAN: null, RC: null, - steeringWheelLocation: 'LEFT', /** * 0 - G * 1 - R diff --git a/app/StateManager.js b/app/StateManager.js index a0bbfd3de..9430d0861 100644 --- a/app/StateManager.js +++ b/app/StateManager.js @@ -173,6 +173,13 @@ var StateManager = Em.StateManager.extend( ); this._super(); }, + rpccontrol: Em.State.create({ + rpcconfig: Em.State.create({}), + rpcwaypointconfig: Em.State.create({}), + rpcvehicledataconfig: Em.State.create({}), + rpcgetivdconfig: Em.State.create({}) + } + ), policies: Em.State.create( { statisticsInfo: Em.State.create({}), @@ -191,6 +198,14 @@ var StateManager = Em.StateManager.extend( } } ), + ccpuEditor: Em.State.create( + { + enter: function() { + this._super(); + SDL.SettingsController.set('editedCcpuVersionValue', SDL.SDLModel.data.ccpuVersion); + } + } + ), deviceConfig: Em.State.create( { enter: function() { @@ -475,6 +490,24 @@ var StateManager = Em.StateManager.extend( } } ), + webViewApp: Em.State.create( + { + modelBinding: 'SDL.RCModulesController', + enter: function() { + this._super(); + SDL.SDLController.onEventChanged('player', false); + SDL.SDLController.onEventChanged(this.name, true); + SDL.SDLController.showWebViewApp(SDL.SDLController.model.appID); + }, + exit: function() { + this._super(); + SDL.SDLController.onEventChanged(this.name, false); + SDL.SDLModel.data.set('limitedExist', false); + SDL.SDLController.hideWebApps(); + SDL.SDLController.deactivateApp(); + } + } + ), /** Navigation state */ navigation: Em.State.create( { diff --git a/app/controller/ClimateController.js b/app/controller/ClimateController.js index 9b04a4e2e..7e4cf712c 100644 --- a/app/controller/ClimateController.js +++ b/app/controller/ClimateController.js @@ -46,15 +46,6 @@ SDL.ClimateController = Em.Object.create( return (data.unit == 'CELSIUS' ? data.value : Math.round((data.value - 32) * 5 / 9)); - }, - getClimateControlData: function() { - var properties = this.model.getDataForSending(); - var climateControlData = this.model.getClimateControlData(); - var data = SDL.SDLController.filterObjectProperty(climateControlData, properties); - if(!climateControlData.climateEnable) { - data['currentTemperature'] = this.model.getClimateControlData().currentTemperature; - } - return data; - }, + } } ); diff --git a/app/controller/InfoController.js b/app/controller/InfoController.js index 3e0e05a67..97ae0470e 100644 --- a/app/controller/InfoController.js +++ b/app/controller/InfoController.js @@ -158,38 +158,51 @@ SDL.InfoController = Em.Object.create( setAppProperties: function(old_properties, new_properties) { this.set('editedAppPropertiesToApply', new_properties); - if ((!'enabled' in old_properties || old_properties['enabled'] == false) && - new_properties['enabled'] === true) { - let that = this; - const policyAppID = new_properties['policyAppID']; + let is_app_installation_required = function() { + const old_app_id = old_properties['policyAppID']; + const new_app_id = new_properties['policyAppID']; - let get_app_title = function() { - let title = policyAppID; - if ('nicknames' in new_properties && new_properties['nicknames'].length > 0) { - title = new_properties['nicknames'][0]; - } - return title; - }; + const old_enabled_state = ('enabled' in old_properties) ? old_properties['enabled'] : false; + const new_enabled_state = ('enabled' in new_properties) ? new_properties['enabled'] : false; - let on_installation_failed = function() { - SDL.PopUp.create().appendTo('body').popupActivate( - `Can't install "${get_app_title()}" app from applications store...`, null, false - ); - SDL.WebAppSettingsView.editorAppSettings = old_properties; - SDL.WebAppSettingsView.showProperties(); - FFW.RPCSimpleClient.disconnect(); - }; + if (old_app_id != new_app_id) { + return new_enabled_state; + } - that.downloadAppBundle(policyAppID) - .then( function() { - Em.Logger.log(`App store: app installed successfully`); - FFW.BasicCommunication.SetAppProperties(new_properties); - FFW.RPCSimpleClient.disconnect(); - }, on_installation_failed); - return; + return new_enabled_state && !old_enabled_state; } - FFW.BasicCommunication.SetAppProperties(new_properties); + if (!is_app_installation_required()) { + FFW.BasicCommunication.SetAppProperties(new_properties); + return; + } + + let that = this; + const policyAppID = new_properties['policyAppID']; + + let get_app_title = function() { + let title = policyAppID; + if ('nicknames' in new_properties && new_properties['nicknames'].length > 0) { + title = new_properties['nicknames'][0]; + } + return title; + }; + + let on_installation_failed = function() { + SDL.PopUp.create().appendTo('body').popupActivate( + `Can't install "${get_app_title()}" app from applications store...`, null, false + ); + SDL.WebAppSettingsView.editorAppSettings = old_properties; + SDL.WebAppSettingsView.showProperties(); + FFW.RPCSimpleClient.disconnect(); + }; + + that.downloadAppBundle(policyAppID) + .then( function() { + Em.Logger.log(`App store: app installed successfully`); + FFW.BasicCommunication.SetAppProperties(new_properties); + FFW.RPCSimpleClient.disconnect(); + }, on_installation_failed); }, /** @@ -325,15 +338,23 @@ SDL.InfoController = Em.Object.create( if (policyAppID in SDL.SDLModel.webApplicationFramesMap) { let frame = SDL.SDLModel.webApplicationFramesMap[policyAppID]; - document.body.removeChild(frame); + const web_engine_view = document.getElementById("webEngineView"); + if (web_engine_view) { + web_engine_view.removeChild(frame); + } } const frame_name = `web_app_frame_${policyAppID}`; let web_app_frame = document.createElement("iframe"); web_app_frame.name = frame_name; web_app_frame.id = frame_name; - web_app_frame.className = "InvisibleFrame"; - document.body.appendChild(web_app_frame); + web_app_frame.className = 'WebEngineFrame'; + web_app_frame.hidden = false; + + const web_engine_view = document.getElementById("webEngineView"); + if (web_engine_view) { + web_engine_view.appendChild(web_app_frame); + } SDL.SDLModel.webApplicationFramesMap[policyAppID] = web_app_frame; @@ -400,9 +421,9 @@ SDL.InfoController = Em.Object.create( */ downloadAppBundle: function(policyAppID) { return new Promise( (resolve, reject) => { - if (!policyAppID in SDL.InfoController.appPackageDownloadUrlsMap) { - Em.Logger.log(`App store: download URL for ${policyAppID} was not found`); - reject(); + if (!(policyAppID in SDL.InfoController.appPackageDownloadUrlsMap)) { + Em.Logger.log(`App store: download URL for ${policyAppID} was not found. Assume bundle was installed manually.`); + return resolve(); } let download_url = SDL.InfoController.appPackageDownloadUrlsMap[policyAppID]; @@ -422,7 +443,7 @@ SDL.InfoController = Em.Object.create( if (params.success == false) { Em.Logger.log('App store: Bundle downloading was not successful'); - reject(); + return reject(); } Em.Logger.log('App store: Bundle was downloaded successfully'); @@ -468,7 +489,7 @@ SDL.InfoController = Em.Object.create( if (params.success == false) { Em.Logger.log('App store: Manifest loading was not successful'); - reject(); + return reject(); } Em.Logger.log('App store: Manifest was loaded successfully'); @@ -503,13 +524,13 @@ SDL.InfoController = Em.Object.create( } catch { Em.Logger.log(`App store: failed to parse JSON content`); - reject(); + return reject(); } Em.Logger.log(`App store: manifest parsed successfully`); if (!('entrypoint' in bundle_json)) { Em.Logger.log(`App store: entrypoint is not specified - use default`); - resolve("index.html"); + return resolve("index.html"); } resolve(bundle_json['entrypoint']); @@ -558,21 +579,6 @@ SDL.InfoController = Em.Object.create( if (SDL.SDLController.model) { SDL.SDLController.model.set('active', true); } - /** - * Go to SDL state - */ - if (SDL.SDLController.model.appType) { - for (var i = 0; i < SDL.SDLController.model.appType.length; i++) { - if (SDL.SDLController.model.appType[i] == 'NAVIGATION' || - SDL.SDLController.model.appType[i] == 'PROJECTION') { - SDL.BaseNavigationView.update(); - SDL.States.goToStates('navigationApp.baseNavigation'); - return; - } - } - } - SDL.States.goToStates('info.nonMedia'); - //SDL.States.goToStates('media.sdlmedia'); } } ); diff --git a/app/controller/NavigationController.js b/app/controller/NavigationController.js index 87000dbd2..76eb8ab57 100644 --- a/app/controller/NavigationController.js +++ b/app/controller/NavigationController.js @@ -49,7 +49,7 @@ SDL.NavigationController = Em.Object.create( * @param {Object} request */ sendLocation: function(request) { - this.model.LocationDetails.push( + this.model.LocationDetails.pushObject( { coordinate: { latitudeDegrees: request.params.latitudeDegrees, @@ -63,11 +63,24 @@ SDL.NavigationController = Em.Object.create( searchAddress: request.params.address } ); - FFW.Navigation.sendNavigationResult( - SDL.SDLModel.data.resultCode.SUCCESS, - request.id, - request.method - ); + + imageList = []; + if(request.params.locationImage) { + imageList.push(request.params.locationImage.value); + } + + var callback = function(failed) { + var WARNINGS = SDL.SDLModel.data.resultCode.WARNINGS; + var SUCCESS = SDL.SDLModel.data.resultCode.SUCCESS; + + FFW.Navigation.sendNavigationResult( + failed ? WARNINGS : SUCCESS, + request.id, + request.method, + failed ? "Requested image(s) not found" : null + ); + } + SDL.SDLModel.validateImages(request.id, callback, imageList); }, /** * Navigation view List Button action handler @@ -128,19 +141,35 @@ SDL.NavigationController = Em.Object.create( * @param {Object} request */ subscribeWayPoints: function(request) { - if (!this.model.isSubscribedOnWayPoints) { - this.model.set('isSubscribedOnWayPoints', true); - FFW.Navigation.sendNavigationResult( - SDL.SDLModel.data.resultCode.SUCCESS, - request.id, - request.method - ); + result = FFW.RPCHelper.getCustomResultCode(null, 'SubscribeWayPoints'); + + if ('DO_NOT_RESPOND' == result) { + Em.Logger.log('Do not respond on this request'); + return; + } + + if(FFW.RPCHelper.isSuccessResultCode(result)){ + if (!this.model.isSubscribedOnWayPoints) { + this.model.set('isSubscribedOnWayPoints', true); + FFW.Navigation.sendNavigationResult( + result, + request.id, + request.method + ); + } else { + FFW.Navigation.sendError( + SDL.SDLModel.data.resultCode.REJECTED, + request.id, + request.method, + 'SDL Should not send this request more than once' + ); + } } else { FFW.Navigation.sendError( - SDL.SDLModel.data.resultCode.REJECTED, + result, request.id, request.method, - 'SDL Should not send this request more than once' + 'Erroneous response is assigned by settings' ); } }, @@ -407,6 +436,94 @@ SDL.NavigationController = Em.Object.create( }, 2000 ); // Allow time for the initial map display - } + }, + + /** + * @desc Verifies if image is an PNG image, + * accordingly to file extension. + * @param imagePath - path to image + * @return {Boolean} true if image is PNG and false otherwise + */ + isPng: function(imagePath) { + const img_extension = '.png'; + var search_offset = imagePath.lastIndexOf('.'); + return imagePath.includes(img_extension, search_offset); + }, + + /** + * @desc Collects images paths from request + * and calls validation function. + * @param request - request data + */ + validateIcons: function(request) { + var params = request.params; + imageList = []; + var nonPngCounter = 0; + + if(params.turnList) { + var countList=params.turnList.length; + for(var i = 0; i < countList; i++) { + if(params.turnList[i].turnIcon) { + var iconPath = params.turnList[i].turnIcon.value; + if(!this.isPng(iconPath)) { + delete params.turnList[i].turnIcon; + nonPngCounter++; + continue; + } + imageList.push(iconPath); + } + } + } + if(params.softButtons) { + var countButtons=params.softButtons.length; + for(var i=0;i 0) { + FFW.Navigation.sendNavigationResult( + SDL.SDLModel.data.resultCode.WARNINGS, + request.id, + request.method, + ); + return; + } + + var callback = function(failed) { + var WARNINGS = SDL.SDLModel.data.resultCode.WARNINGS; + var SUCCESS = SDL.SDLModel.data.resultCode.SUCCESS; + FFW.Navigation.sendNavigationResult( + failed ? WARNINGS : SUCCESS, + request.id, + request.method, + failed ? "Requested image(s) not found" : null); + } + SDL.SDLModel.validateImages(request.id, callback, imageList); + }, } ); diff --git a/app/controller/SettingsController.js b/app/controller/SettingsController.js index 7d41af2dd..c98a7e311 100644 --- a/app/controller/SettingsController.js +++ b/app/controller/SettingsController.js @@ -68,8 +68,21 @@ SDL.SettingsController = Em.Object.create( * disallowed. */ currentDeviceAllowance: null, + + /** + * @description Value of CCPU version displayed in user input + */ + editedCcpuVersionValue: "", + onState: function(event) { + if(SDL.States.currentState.name === 'rpcconfig'){ + FFW.RPCHelper.setCurrentAppID(null); + } SDL.States.goToStates('settings.' + event.goToState); + if('rpccontrol.rpcconfig' === event.goToState){ + SDL.RPCControlConfigView.set('appNameLabel.content',event.appName); + FFW.RPCHelper.updateRpc(event.appID); + } }, onChildState: function(event) { SDL.States.goToStates( @@ -170,7 +183,7 @@ SDL.SettingsController = Em.Object.create( */ GetListOfPermissions: function(element) { FFW.BasicCommunication.GetListOfPermissions(element.appID); - SDL.AppPermissionsView.update(SDL.SDLModelData.externalConsentStatus, 0); + SDL.AppPermissionsView.update(SDL.SDLModelData.externalConsentStatus, element.appID); SDL.States.goToStates('settings.policies.appPermissions'); }, /** @@ -263,6 +276,10 @@ SDL.SettingsController = Em.Object.create( ); }, simpleParseUserFriendlyMessageData: function(messages, func) { + if (!messages) { + return; + } + var tts = '', text = ''; messages.forEach( @@ -349,14 +366,8 @@ SDL.SettingsController = Em.Object.create( SDL.SDLModel.data.policyURLs[0] ); } - if(!SDL.SDLModel.data.policyUpdateRetry.isRetry) { + if(abort !== 'ABORT' && !SDL.SDLModel.data.policyUpdateRetry.isRetry) { SDL.SDLModel.data.policyUpdateRetry.isRetry = true; - SDL.SDLModel.data.policyUpdateRetry.isIterationInProgress = true; - SDL.SDLModel.data.policyUpdateRetry.timer = setTimeout( - function() { - sendOnSystemRequest(); - }, 1000 - ); return; } var length = SDL.SDLModel.data.policyUpdateRetry.retry.length; @@ -410,7 +421,7 @@ SDL.SettingsController = Em.Object.create( if (params.success == false) { Em.Logger.log('PTU: Downloading PTS was not successful'); - reject(); + return reject(); } Em.Logger.log('PTU: PTS downloaded successfully'); @@ -485,7 +496,7 @@ SDL.SettingsController = Em.Object.create( if (params.success == false) { Em.Logger.log('PTU: PTU save was not successful'); - reject(); + return reject(); } Em.Logger.log('PTU: PTU saved successfully'); @@ -537,6 +548,7 @@ SDL.SettingsController = Em.Object.create( if (urls.length > 0 && FLAGS.ExternalPolicies === true) { SDL.SettingsController.OnSystemRequestHandler(urls[0]); + SDL.SettingsController.policyUpdateRetry(); } else { SDL.SettingsController.OnSystemRequestHandler(); } @@ -593,6 +605,13 @@ SDL.SettingsController = Em.Object.create( } }, + /** + * @description Saves new CCPU version value from user input + */ + applyNewCcpuVersionValue: function() { + SDL.SDLModel.data.ccpuVersion = this.editedCcpuVersionValue; + }, + /** * @function sendGetPolicyConfigurationDataRequest * @description send GetPolicyConfigurationData request from HMI by user action diff --git a/app/controller/sdl/Abstract/Controller.js b/app/controller/sdl/Abstract/Controller.js index 5364fc12d..8eda035fc 100644 --- a/app/controller/sdl/Abstract/Controller.js +++ b/app/controller/sdl/Abstract/Controller.js @@ -58,6 +58,7 @@ SDL.SDLController = Em.Object.extend( SDL.InfoAppsView.showAppList(); SDL.AppPermissionsListView.showAppList(); SDL.RCModulesController.updateModuleSeatLocationContent(); + SDL.RPCControlView.showAppList(); }.observes('SDL.SDLModel.data.registeredApps.@each'), /** * Handeler for command button press @@ -68,7 +69,7 @@ SDL.SDLController = Em.Object.extend( onCommand: function(element) { if (element.commandID < 0) { switch (element.commandID) { - case -1: + case SDL.SDLModel.data.exitCommandsEnum.DRIVER_DISTRACTION_VIOLATION: { FFW.BasicCommunication.ExitApplication( SDL.SDLController.model.appID, @@ -76,7 +77,7 @@ SDL.SDLController = Em.Object.extend( ); break; } - case -2: + case SDL.SDLModel.data.exitCommandsEnum.USER_EXIT: { FFW.BasicCommunication.ExitApplication( SDL.SDLController.model.appID, @@ -84,7 +85,7 @@ SDL.SDLController = Em.Object.extend( ); break; } - case -3: + case SDL.SDLModel.data.exitCommandsEnum.UNAUTHORIZED_TRANSPORT_REGISTRATION: { FFW.BasicCommunication.ExitApplication( SDL.SDLController.model.appID, @@ -92,6 +93,22 @@ SDL.SDLController = Em.Object.extend( ); break; } + case SDL.SDLModel.data.exitCommandsEnum.RESOURCE_CONSTRAINT: + { + FFW.BasicCommunication.ExitApplication( + SDL.SDLController.model.appID, + 'RESOURCE_CONSTRAINT' + ); + break; + } + case SDL.SDLModel.data.exitCommandsEnum.CLOSE_CLOUD_CONNECTION: + { + FFW.BasicCommunication.ExitApplication( + SDL.SDLController.model.appID, + 'CLOSE_CLOUD_CONNECTION' + ); + break; + } default: { console.log('Unknown command with ID: ' + element.commandID); @@ -110,6 +127,7 @@ SDL.SDLController = Em.Object.extend( } } else { FFW.UI.onCommand(element.commandID, this.model.appID); + this.model.set('currentSubMenuId', 'top'); SDL.OptionsView.deactivate(); } }, @@ -135,7 +153,12 @@ SDL.SDLController = Em.Object.extend( * @param id {Number} */ onSubMenu: function(id) { - this.model.set('currentSubMenuId', id); + if (id >= 0 && id != 'top') { + this.model.set('currentMenuDepth', this.model.currentMenuDepth + 1); + } else { + this.model.set('currentMenuDepth', 0); + } + this.model.set('currentSubMenuId', id); }, /** * Comparison function for sort array of buttons in options list by @@ -162,7 +185,8 @@ SDL.SDLController = Em.Object.extend( SDL.SDLModel.data.toggleProperty('VRActive'); } if (element.commandID === -2) { //Magic number if predefined VR command USER_EXIT - this.userExitAction(element.appID); + var that = this; + setTimeout( function() { that.userExitAction(element.appID); }, 50); } else { FFW.VR.onCommand(element.commandID, element.appID, element.grammarID); } @@ -179,7 +203,8 @@ SDL.SDLController = Em.Object.extend( closeApplication: function(appID) { if (SDL.States.currentState.getPath('path') === 'media.sdlmedia' || SDL.States.currentState.getPath('path') === 'info.nonMedia' || - SDL.States.currentState.getPath('path') === 'navigationApp.baseNavigation') { + SDL.States.currentState.getPath('path') === 'navigationApp.baseNavigation' || + SDL.States.currentState.getPath('path') === 'webViewApp') { SDL.States.goToStates('info.apps'); } }, @@ -214,10 +239,10 @@ SDL.SDLController = Em.Object.extend( * StateManager */ deactivateApp: function() { + SDL.SDLController.onSubMenu('top'); if (this.model) { SDL.SDLModel.onDeactivateApp(SDL.States.nextState, this.model.appID); } - SDL.SDLController.onSubMenu('top'); SDL.SDLController.model.set('tbtActivate', false); this.set('model', null); }, @@ -258,7 +283,7 @@ SDL.SDLController = Em.Object.extend( if (SDL.SDLModel.data.VRActive) { return 'VRSESSION'; } - if (SDL.AlertPopUp.active) { + if (SDL.AlertPopUp.active || SDL.SubtleAlertPopUp.active) { return 'ALERT'; } if (SDL.SliderView.active || @@ -278,6 +303,7 @@ SDL.SDLController = Em.Object.extend( 'SDL.SDLModel.data.AudioPassThruState', 'SDL.SDLModel.data.VRActive', 'SDL.AlertPopUp.active', + 'SDL.SubtleAlertPopUp.active', 'SDL.States.info.nonMedia.active', 'SDL.States.media.sdlmedia.active', 'SDL.States.navigationApp.baseNavigation.active', @@ -324,9 +350,13 @@ SDL.SDLController = Em.Object.extend( for (var i = 0; i < SDL.SDLModel.data.registeredComponents.length; i++) { if (SDL.SDLModel.data.registeredComponents[i].type == component) { SDL.SDLModel.data.set('registeredComponents.' + i + '.state', true); - return; + break; } } + + if (this.areAllComponentsReady()) { + FFW.BasicCommunication.onReady(); + } }, /** * Registered components handler @@ -447,19 +477,19 @@ SDL.SDLController = Em.Object.extend( ); }, /** - * Notify SDLCore that HMI is ready and all components are registered + * Checks whether HMI is ready and all components are registered * - * @type {String} + * @return {Boolean} */ - componentsReadiness: function(component) { + areAllComponentsReady: function() { for (var i = 0; i < SDL.SDLModel.data.registeredComponents.length; i++) { if (FLAGS[SDL.SDLModel.data.registeredComponents[i].type] != SDL.SDLModel.data.registeredComponents[i].state) { - return; + return false; } } - FFW.BasicCommunication.onReady(); - }.observes('SDL.SDLModel.data.registeredComponents.@each.state'), + return true; + }, /** * Show VrHelpItems popup with necessary params * if VRPopUp is active - show data from Global Properties @@ -565,6 +595,16 @@ SDL.SDLController = Em.Object.extend( SDL.AlertPopUp.deactivate(); break; } + case 'AlertManeuverPopUp': + { + SDL.AlertManeuverPopUp.deactivate(); + break; + } + case 'SubtleAlertPopUp': + { + SDL.SubtleAlertPopUp.deactivate(); + break; + } case 'ScrollableMessage': { SDL.ScrollableMessage.deactivate(true); @@ -606,6 +646,18 @@ SDL.SDLController = Em.Object.extend( this.onActivateSDLApp(element); break; } + case 'AlertManeuverPopUp': + { + SDL.AlertManeuverPopUp.deactivate(); + this.onActivateSDLApp(element); + break; + } + case 'SubtleAlertPopUp': + { + SDL.SubtleAlertPopUp.deactivate(); + this.onActivateSDLApp(element); + break; + } case 'ScrollableMessage': { SDL.ScrollableMessage.deactivate(); @@ -638,6 +690,28 @@ SDL.SDLController = Em.Object.extend( this.onResetTimeout(element.appID, 'UI.Alert'); break; } + case 'AlertManeuverPopUp': + { + clearTimeout(SDL.AlertManeuverPopUp.timer); + SDL.AlertManeuverPopUp.timer = setTimeout( + function() { + SDL.AlertManeuverPopUp.deactivate(); + }, SDL.AlertManeuverPopUp.timeout + ); + FFW.TTS.OnResetTimeout(element.appID, 'Navigation.AlertManeuver'); + break; + } + case 'SubtleAlertPopUp': + { + clearTimeout(SDL.SubtleAlertPopUp.timer); + SDL.SubtleAlertPopUp.timer = setTimeout( + function() { + SDL.SubtleAlertPopUp.deactivate(); + }, SDL.SubtleAlertPopUp.timeout + ); + this.onResetTimeout(element.appID, 'UI.SubtleAlert'); + break; + } case 'ScrollableMessage': { clearTimeout(SDL.ScrollableMessage.timer); @@ -658,18 +732,16 @@ SDL.SDLController = Em.Object.extend( closePopUp: function(methodName) { if (methodName == 'UI.Alert') { SDL.AlertPopUp.deactivate(); - } - if (methodName == 'UI.PerformAudioPassThru') { + } else if (methodName === 'UI.SubtleAlert') { + SDL.SubtleAlertPopUp.deactivate(); + } else if (methodName == 'UI.PerformAudioPassThru') { SDL.AudioPassThruPopUp.deactivate(); this.performAudioPassThruResponse(SDL.SDLModel.data.resultCode.SUCCESS); - } - if (methodName == 'UI.PerformInteraction') { + } else if (methodName == 'UI.PerformInteraction') { SDL.InteractionChoicesView.deactivate('ABORTED'); - } - if (methodName == 'UI.ScrollableMessage') { + } else if (methodName == 'UI.ScrollableMessage') { SDL.ScrollableMessage.deactivate(true); - } - if (methodName == 'UI.Slider') { + } else if (methodName == 'UI.Slider') { SDL.SliderView.deactivate(true); } // if (SDL.VRHelpListView.active) { @@ -686,7 +758,7 @@ SDL.SDLController = Em.Object.extend( * Method to close AlertMeneuverPopUp view */ closeAlertMeneuverPopUp: function() { - SDL.AlertManeuverPopUp.set('activate', false); + SDL.AlertManeuverPopUp.deactivate(); }, /** * Method to open Turn List view from TBT @@ -764,14 +836,38 @@ SDL.SDLController = Em.Object.extend( /** * Method to sent notification for Alert * - * @param {String} - * result + * @param {Number} + * result code * @param {Number} * alertRequestID */ alertResponse: function(result, alertRequestID, info) { FFW.UI.alertResponse(result, alertRequestID, info); }, + /** + * Method to send response for SubtleAlert + * + * @param {Number} + * result code + * @param {Number} + * subtleAlertRequestID + * @param {String} + * info + * @param {Number} + * tryAgainTime time in ms until current SubtleAlert finished + */ + subtleAlertResponse: function(result, subtleAlertRequestID, info, tryAgainTime) { + FFW.UI.subtleAlertResponse(result, subtleAlertRequestID, info, tryAgainTime); + }, + /** + * Method to send notification when subtle alert is clicked + * + * @param {Number} + * appID + */ + onSubtleAlertPressed: function(appID) { + FFW.UI.onSubtleAlertPressed(appID); + }, /** * Method to sent notification for Scrollable Message * @@ -787,15 +883,15 @@ SDL.SDLController = Em.Object.extend( messageRequestId, 'UI.ScrollableMessage' ); - }else if(result == SDL.SDLModel.data.resultCode.WARNINGS) { + } else if(result == SDL.SDLModel.data.resultCode.WARNINGS) { FFW.UI.sendUIResult( result, messageRequestId, - 'UI.ScrollableMessage' + 'UI.ScrollableMessage', + 'Requested image(s) not found' ); - } - else { - FFW.UI.sendError( + } else { + FFW.UI.sendUIResult( result, messageRequestId, 'UI.ScrollableMessage', @@ -945,48 +1041,68 @@ SDL.SDLController = Em.Object.extend( ) ); } - var exitCommand = { - 'id': -10, - 'params': { - 'menuParams': { - 'parentID': 0, - 'menuName': 'Exit \'DRIVER_DISTRACTION_VIOLATION\'', - 'position': 0 - }, - cmdID: -1 - } - }; - SDL.SDLController.getApplicationModel(params.appID).addCommand( - exitCommand - ); - exitCommand = { - 'id': -10, - 'params': { - 'menuParams': { - 'parentID': 0, - 'menuName': 'Exit \'USER_EXIT\'', - 'position': 0 - }, - cmdID: -2 - } - }; - SDL.SDLController.getApplicationModel(params.appID).addCommand( - exitCommand - ); - exitCommand = { - 'id': -10, - 'params': { - 'menuParams': { - 'parentID': 0, - 'menuName': 'Exit \'UNAUTHORIZED_TRANSPORT_REGISTRATION\'', - 'position': 0 - }, - cmdID: -3 + var exitCommands = [ + { + 'id': -10, + 'params': { + 'menuParams': { + 'parentID': 0, + 'menuName': 'Exit \'DRIVER_DISTRACTION_VIOLATION\'', + 'position': 0 + }, + cmdID: SDL.SDLModel.data.exitCommandsEnum.DRIVER_DISTRACTION_VIOLATION + } + }, + { + 'id': -10, + 'params': { + 'menuParams': { + 'parentID': 0, + 'menuName': 'Exit \'USER_EXIT\'', + 'position': 0 + }, + cmdID: SDL.SDLModel.data.exitCommandsEnum.USER_EXIT + } + }, + { + 'id': -10, + 'params': { + 'menuParams': { + 'parentID': 0, + 'menuName': 'Exit \'UNAUTHORIZED_TRANSPORT_REGISTRATION\'', + 'position': 0 + }, + cmdID: SDL.SDLModel.data.exitCommandsEnum.UNAUTHORIZED_TRANSPORT_REGISTRATION + } + }, + { + 'id': -10, + 'params': { + 'menuParams': { + 'parentID': 0, + 'menuName': 'Exit \'RESOURCE_CONSTRAINT\'', + 'position': 0 + }, + cmdID: SDL.SDLModel.data.exitCommandsEnum.RESOURCE_CONSTRAINT + } + }, + { + 'id': -10, + 'params': { + 'menuParams': { + 'parentID': 0, + 'menuName': 'Exit \'CLOSE_CLOUD_CONNECTION\'', + 'position': 0 + }, + cmdID: SDL.SDLModel.data.exitCommandsEnum.CLOSE_CLOUD_CONNECTION + } } - }; - SDL.SDLController.getApplicationModel(params.appID).addCommand( - exitCommand - ); + ]; + + let model = SDL.SDLController.getApplicationModel(params.appID); + exitCommands.forEach(command => { + model.addCommand(command); + }); }, /** * Unregister application @@ -1021,7 +1137,10 @@ SDL.SDLController = Em.Object.extend( } if (app.webEngineApp && app.policyAppID in SDL.SDLModel.webApplicationFramesMap) { let frame = SDL.SDLModel.webApplicationFramesMap[app.policyAppID]; - document.body.removeChild(frame); + const web_engine_view = document.getElementById("webEngineView"); + if (web_engine_view) { + web_engine_view.removeChild(frame); + } delete SDL.SDLModel.webApplicationFramesMap[app.policyAppID]; } }, @@ -1067,6 +1186,10 @@ SDL.SDLController = Em.Object.extend( SDL.PopUp.create().appendTo('body').popupActivate(message); } SDL.InfoAppsView.showAppList(); + + params.applications.forEach(appRecord => { + SDL.SDLModel.appIDtoPolicyAppIDMapping[appRecord.appID] = appRecord.policyAppID; + }); }, /** * SDL Driver Distraction ON/OFF switcher @@ -1188,6 +1311,9 @@ SDL.SDLController = Em.Object.extend( } SDL.InfoController.getWebAppEntryPointPath(model.policyAppID, callback); + } else if (model.webEngineApp !== true && model.appType.indexOf('WEB_VIEW') >= 0) { + SDL.PopUp.create().appendTo('body') + .popupActivate("Only Web Engine apps with app type WEB_VIEW can be activated!"); } else { FFW.BasicCommunication.ActivateApp(element.appID); } @@ -1337,6 +1463,8 @@ SDL.SDLController = Em.Object.extend( */ onSystemContextChange: function(appID, windowID) { var sysContextValue = this.get('sysContext'); + SDL.SDLController.setWebEngineFramesActive(sysContextValue == 'MAIN'); + if (( appID && SDL.SDLController.getApplicationModel(appID) != @@ -1495,13 +1623,50 @@ SDL.SDLController = Em.Object.extend( getDefaultCapabilities: function (windowID, appID) { let windowType = (windowID === undefined || windowID === 0) ? "MAIN" : "WIDGET"; - let windowCapability = SDL.SDLModelData.defaultWindowCapability[windowType]; + let windowCapability = SDL.deepCopy(SDL.SDLModelData.defaultWindowCapability[windowType]); if(windowType === "WIDGET") { windowCapability["systemCapability"]["displayCapabilities"][0]["windowCapabilities"][0]["windowID"] = windowID; } + if(appID) { + const is_web_view_template = function(model) { + const template = model.templateConfiguration.template; + if (template == "DEFAULT" && model.appType.indexOf('WEB_VIEW') >= 0) { + return true; + } + + return template == "WEB_VIEW"; + } + + var appModel = this.getApplicationModel(appID); + if (appModel && is_web_view_template(appModel) && windowType == "MAIN") { + let text_fields = windowCapability["systemCapability"]["displayCapabilities"][0]["windowCapabilities"][0]["textFields"]; + const text_fields_to_exclude = [ + 'mainField1', 'mainField2', 'mainField3', 'mainField4', + 'mediaClock', 'mediaTrack' + ]; + for (var i = text_fields.length - 1; i >= 0; i--) { + if (text_fields_to_exclude.includes(text_fields[i].name)) { + text_fields.splice(i, 1); + } + } + + let image_fields = windowCapability["systemCapability"]["displayCapabilities"][0]["windowCapabilities"][0]["imageFields"]; + const image_fields_to_exclude = [ + 'softButtonImage', 'menuIcon', 'graphic', 'secondaryGraphic' + ]; + for (var i = image_fields.length - 1; i >= 0; i--) { + if (image_fields_to_exclude.includes(image_fields[i].name)) { + image_fields.splice(i, 1); + } + } + + delete windowCapability["systemCapability"]["displayCapabilities"][0]["windowCapabilities"][0]["softButtonCapabilities"]; + } + windowCapability["appID"] = appID; } + return windowCapability; }, /** @@ -1549,5 +1714,54 @@ SDL.SDLController = Em.Object.extend( } return title; }, + + /** + * @function setWebEngineFramesActive + * @param {Boolean} isActive + * @description set touch events activity for all currently active WEP frames + */ + setWebEngineFramesActive: function(isActive) { + var frames = document.getElementsByClassName("WebEngineFrame"); + for (var i = 0; i < frames.length; ++i) { + if (isActive) { + frames[i].style.pointerEvents = null; + } else { + frames[i].style.pointerEvents = "none"; + } + } + }, + + /** + * @function hideWebApps + * @description Makes all web application view disabled + */ + hideWebApps: function() { + for(var key in SDL.SDLModel.webApplicationFramesMap) { + SDL.SDLModel.webApplicationFramesMap[key].hidden = true; + } + }, + + /** + * @function showWebViewApp + * @param {Number} appID + * @description Activates web view for application specified by appID + */ + showWebViewApp: function(appID) { + this.hideWebApps(); + let policyAppID = SDL.SDLModel.appIDtoPolicyAppIDMapping[appID]; + SDL.SDLModel.webApplicationFramesMap[policyAppID].hidden = false; + }, + + /** + * @description Callback for display image mode change. + */ + imageModeChanged: function() { + const length = SDL.OptionsView.commands.items.length; + for (var i=0; i { var location_name = SDL.VehicleModuleCoverageController.getLocationName(seat_location); seatLocationNames.push(location_name); + + if (vehicleRepresentation[rightMostSeatIndex].col === seat_location.col || + leftMostSeatIndex === seat_location.col) { + var location_window_status = { + "location": seat_location, + "state": { + "approximatePosition": 0, + "deviation": 0 + } + }; + windowStatus.push(location_window_status); + } }); + SDL.SDLVehicleInfoModel.vehicleData.windowStatus = windowStatus; + var self = this; var coverageSettings = SDL.VehicleModuleCoverageController.getCoverageSettings(); Object.keys(coverageSettings).forEach(module_type => { @@ -354,6 +372,7 @@ SDL.RCModulesController = Em.Object.create({ break; } case 'SEAT': { + let seatUUIDs = []; module_coverage.forEach(module_service_area => { var location_name = SDL.VehicleModuleCoverageController.getLocationName(module_service_area); self.set('seatModels.' + location_name, SDL.SeatModel.create({ @@ -361,7 +380,9 @@ SDL.RCModulesController = Em.Object.create({ UUID: this.moduleUUIDMapping[module_type][location_name]} )); self.seatModels[location_name].generateSeatCapabilities(module_service_area); + seatUUIDs.push(this.moduleUUIDMapping[module_type][location_name]); }); + SDL.SeatView.id.seatModuleUUID.set('content', seatUUIDs); break; } case 'AUDIO': { @@ -644,12 +665,13 @@ SDL.RCModulesController = Em.Object.create({ updateCurrentModels: function(location_name) { this.set('currentClimateModel', this.getCoveringModuleModel('CLIMATE', location_name)); this.set('currentAudioModel', this.getCoveringModuleModel('AUDIO', location_name)); - this.set('currentSeatModel', this.getCoveringModuleModel('SEAT', location_name)); this.set('currentRadioModel', this.getCoveringModuleModel('RADIO', location_name)); this.set('currentHMISettingsModel', this.getCoveringModuleModel('HMI_SETTINGS', location_name)); this.set('currentLightModel', this.getCoveringModuleModel('LIGHT', location_name)); - this.currentSeatModel.update(); + SDL.SeatView.id.seatModuleUUID.set('value', this.moduleUUIDMapping['SEAT'][location_name]); + SDL.SeatView.id.seatModuleUUID.trigger('change'); + this.currentRadioModel.update(); this.currentAudioModel.update(); this.currentHMISettingsModel.update(); @@ -751,7 +773,7 @@ SDL.RCModulesController = Em.Object.create({ { if (data.params.moduleData.climateControlData) { var currentClimateState = - this.climateModels[location_name].getClimateControlData().climateEnable; + this.climateModels[location_name].generateClimateControlData().climateEnable; var requestedClimateState = data.params.moduleData.climateControlData.climateEnable; if(!currentClimateState) { diff --git a/app/controller/sdl/RController.js b/app/controller/sdl/RController.js index 2dcbc5672..2c073a6fb 100644 --- a/app/controller/sdl/RController.js +++ b/app/controller/sdl/RController.js @@ -249,8 +249,22 @@ SDL.RController = SDL.SDLController.extend( const isDayColorSchemeExists = "dayColorScheme" in params ; const isNightColorSchemeExists = "nightColorScheme" in params; + let get_template_from_app_type = function(model) { + if (model.appType) { + for (var i = 0; i < model.appType.length; i++) { + if (model.appType[i] == 'NAVIGATION' || model.appType[i] == 'PROJECTION') { + return 'NAV_FULLSCREEN_MAP'; + } + if (model.appType[i] == 'WEB_VIEW') { + return 'WEB_VIEW'; + } + } + } + return model.isMedia ? 'MEDIA' : 'NON-MEDIA'; + }; + let defaultTemplateConfiguration = { - "template" : "DEFAULT" + "template" : get_template_from_app_type(model) }; const defaultColorScheme = { @@ -356,50 +370,70 @@ SDL.RController = SDL.SDLController.extend( ) ); } - var exitCommand = { - 'id': -10, - 'params': { - 'menuParams': { - 'parentID': 0, - 'menuName': 'Exit \'DRIVER_DISTRACTION_VIOLATION\'', - 'position': 0 - }, - - cmdID: -1 - } - }; - SDL.SDLController.getApplicationModel(params.appID).addCommand( - exitCommand - ); - exitCommand = { - 'id': -10, - 'params': { - 'menuParams': { - 'parentID': 0, - 'menuName': 'Exit \'USER_EXIT\'', - 'position': 0 - }, - - cmdID: -2 - } - }; - SDL.SDLController.getApplicationModel(params.appID).addCommand( - exitCommand - ); - exitCommand = { - 'id': -10, - 'params': { - 'menuParams': { - 'parentID': 0, - 'menuName': 'Exit \'UNAUTHORIZED_TRANSPORT_REGISTRATION\'', - 'position': 0 - }, - - cmdID: -3 + var exitCommands = [ + { + 'id': -10, + 'params': { + 'menuParams': { + 'parentID': 0, + 'menuName': 'Exit \'DRIVER_DISTRACTION_VIOLATION\'', + 'position': 0 + }, + cmdID: SDL.SDLModel.data.exitCommandsEnum.DRIVER_DISTRACTION_VIOLATION + } + }, + { + 'id': -10, + 'params': { + 'menuParams': { + 'parentID': 0, + 'menuName': 'Exit \'USER_EXIT\'', + 'position': 0 + }, + cmdID: SDL.SDLModel.data.exitCommandsEnum.USER_EXIT + } + }, + { + 'id': -10, + 'params': { + 'menuParams': { + 'parentID': 0, + 'menuName': 'Exit \'UNAUTHORIZED_TRANSPORT_REGISTRATION\'', + 'position': 0 + }, + cmdID: SDL.SDLModel.data.exitCommandsEnum.UNAUTHORIZED_TRANSPORT_REGISTRATION + } + }, + { + 'id': -10, + 'params': { + 'menuParams': { + 'parentID': 0, + 'menuName': 'Exit \'RESOURCE_CONSTRAINT\'', + 'position': 0 + }, + + cmdID: SDL.SDLModel.data.exitCommandsEnum.RESOURCE_CONSTRAINT + } + }, + { + 'id': -10, + 'params': { + 'menuParams': { + 'parentID': 0, + 'menuName': 'Exit \'CLOSE_CLOUD_CONNECTION\'', + 'position': 0 + }, + cmdID: SDL.SDLModel.data.exitCommandsEnum.CLOSE_CLOUD_CONNECTION + } } - }; + ]; + let model = SDL.SDLController.getApplicationModel(params.appID); - model.addCommand(exitCommand); + exitCommands.forEach(command => { + model.addCommand(command) + }); + this.setInitalWindowTemplate(params, model); }, @@ -441,7 +475,7 @@ SDL.RController = SDL.SDLController.extend( onCommand: function(element) { if (element.commandID < 0) { switch (element.commandID) { - case -1: + case SDL.SDLModel.data.exitCommandsEnum.DRIVER_DISTRACTION_VIOLATION: { FFW.BasicCommunication.ExitApplication( SDL.SDLController.model.appID, @@ -449,7 +483,7 @@ SDL.RController = SDL.SDLController.extend( ); break; } - case -2: + case SDL.SDLModel.data.exitCommandsEnum.USER_EXIT: { FFW.BasicCommunication.ExitApplication( SDL.SDLController.model.appID, @@ -457,7 +491,7 @@ SDL.RController = SDL.SDLController.extend( ); break; } - case -3: + case SDL.SDLModel.data.exitCommandsEnum.UNAUTHORIZED_TRANSPORT_REGISTRATION: { FFW.BasicCommunication.ExitApplication( SDL.SDLController.model.appID, @@ -465,6 +499,22 @@ SDL.RController = SDL.SDLController.extend( ); break; } + case SDL.SDLModel.data.exitCommandsEnum.RESOURCE_CONSTRAINT: + { + FFW.BasicCommunication.ExitApplication( + SDL.SDLController.model.appID, + 'RESOURCE_CONSTRAINT' + ); + break; + } + case SDL.SDLModel.data.exitCommandsEnum.CLOSE_CLOUD_CONNECTION: + { + FFW.BasicCommunication.ExitApplication( + SDL.SDLController.model.appID, + 'CLOSE_CLOUD_CONNECTION' + ); + break; + } default: { console.log('Unknown command with ID: ' + element.commandID); @@ -476,13 +526,16 @@ SDL.RController = SDL.SDLController.extend( // if subMenu // activate driver destruction if necessary - if (SDL.SDLModel.data.driverDistractionState) { + var allowedDepth = SDL.systemCapabilities.driverDistractionCapability.subMenuDepth-1; + var activeDepth = SDL.SDLController.model.get('currentMenuDepth'); + if (SDL.SDLModel.data.driverDistractionState && activeDepth >= allowedDepth) { SDL.DriverDistraction.activate(); } else { this.onSubMenu(element.menuID); } } else { FFW.UI.onCommand(element.commandID, this.model.appID); + this.model.set('currentSubMenuId', 'top'); SDL.OptionsView.deactivate(); } }, diff --git a/app/controller/sdl/RPCController.js b/app/controller/sdl/RPCController.js index 6effd4af4..dcc0f99c2 100644 --- a/app/controller/sdl/RPCController.js +++ b/app/controller/sdl/RPCController.js @@ -73,31 +73,31 @@ SDL.RPCController = Em.Object.create( capabilitiesCheck: function(key, value) { if (key == 'imageType' && value == 'STATIC') { SDL.RPCController.capabilityCheckResult = { - code: SDL.SDLModel.data.resultCode['UNSUPPORTED_RESOURCE'], + code: SDL.SDLModel.data.resultCode['WARNINGS'], type: value }; } if (key == 'type' && value == 'PRE_RECORDED') { SDL.RPCController.capabilityCheckResult = { - code: SDL.SDLModel.data.resultCode['UNSUPPORTED_RESOURCE'], + code: SDL.SDLModel.data.resultCode['WARNINGS'], type: value }; } if (key == 'type' && value == 'SAPI_PHONEMES') { SDL.RPCController.capabilityCheckResult = { - code: SDL.SDLModel.data.resultCode['UNSUPPORTED_RESOURCE'], + code: SDL.SDLModel.data.resultCode['WARNINGS'], type: value }; } if (key == 'type' && value == 'LHPLUS_PHONEMES') { SDL.RPCController.capabilityCheckResult = { - code: SDL.SDLModel.data.resultCode['UNSUPPORTED_RESOURCE'], + code: SDL.SDLModel.data.resultCode['WARNINGS'], type: value }; } if (key == 'type' && value == 'SILENCE') { SDL.RPCController.capabilityCheckResult = { - code: SDL.SDLModel.data.resultCode['UNSUPPORTED_RESOURCE'], + code: SDL.SDLModel.data.resultCode['WARNINGS'], type: value }; } @@ -1284,6 +1284,60 @@ SDL.RPCController = Em.Object.create( }; return this.resultStruct; }, + /** + * Validate method for request UI.SubtleAlert + * + * @param {Object} + * params + */ + SubtleAlert: function(params) { + if (params == null) { + this.resultStruct = { + 'resultCode': SDL.SDLModel.data.resultCode.INVALID_DATA, + 'resultMessage': 'Parameter \'params\' does not exist!' + }; + return this.resultStruct; + } + if (params.alertStrings == null) { + this.resultStruct = { + 'resultCode': SDL.SDLModel.data.resultCode.INVALID_DATA, + 'resultMessage': 'Parameter \'alertStrings\' does not exist!' + }; + return this.resultStruct; + } + if (params.alertStrings.length < 0) { + this.resultStruct = { + 'resultCode': SDL.SDLModel.data.resultCode.INVALID_DATA, + 'resultMessage': 'Wrong type of parameter \'alertStrings\'!' + }; + return this.resultStruct; + } + if ('duration' in params && typeof params.duration != 'number') { + this.resultStruct = { + 'resultCode': SDL.SDLModel.data.resultCode.INVALID_DATA, + 'resultMessage': 'Wrong type of parameter \'duration\'!' + }; + return this.resultStruct; + } + if (params.appID == null) { + this.resultStruct = { + 'resultCode': SDL.SDLModel.data.resultCode.INVALID_DATA, + 'resultMessage': 'Parameter \'appID\' does not exist!' + }; + return this.resultStruct; + } + if (typeof params.appID != 'number') { + this.resultStruct = { + 'resultCode': SDL.SDLModel.data.resultCode.INVALID_DATA, + 'resultMessage': 'Wrong type of parameter \'appID\'!' + }; + return this.resultStruct; + } + this.resultStruct = { + 'resultCode': SDL.SDLModel.data.resultCode.SUCCESS + }; + return this.resultStruct; + }, /** * Validate method for request Show * diff --git a/app/controlls/Button.js b/app/controlls/Button.js index 340f2c51b..bad0154a6 100644 --- a/app/controlls/Button.js +++ b/app/controlls/Button.js @@ -163,6 +163,21 @@ SDL.Button = Em.View.extend(Ember.TargetActionSupport, ); }, + didInsertElement: function(){ + // $(this) wraps the ember view in a jquery object. + // `icon` is a view property defined above. + if ($(this)[0].icon) { + // this.$('img') returns a jquery instance of + // the img element inside of the SDL.Button + this.$('img').on('error', function(event) { + if(SDL.SDLController.model && SDL.SDLController.model.appID) { + var regex = /\?(.*)/g; + FFW.UI.OnUpdateFile(SDL.SDLController.model.appID, $(this)[0].icon.replace(regex, "")) + } + }.bind(this)); + } + }, + // component default template defaultTemplate: Em.Handlebars.compile( '' + @@ -172,28 +187,66 @@ SDL.Button = Em.View.extend(Ember.TargetActionSupport, templates: { text: Em.Handlebars.compile('{{view.text}}'), + textOverlay: Em.Handlebars.compile( + '' + + '' + + '{{view.text}}' + ), + icon: Em.Handlebars.compile( + '' + ), + + iconOverlay: Em.Handlebars.compile( + '' + '' ), - rightText: Em.Handlebars.compile( + subtle: Em.Handlebars.compile( + '' + + '{{view.text}}' + ), + + subtleOverlay: Em.Handlebars.compile( + '' + '' + + '{{view.text}}' + ), + + rightText: Em.Handlebars.compile( + '' + '{{view.text}}' ), rightTextOverLay: Em.Handlebars.compile( '' + - '' + + '' + '{{view.text}}' ), arrow: Em.Handlebars.compile( - '' + + '' + '{{view.text}}' + '' ), + arrowShort: Em.Handlebars.compile( + '' + + '{{view.text}}' + + '' + ), + arrowShortOverLay: Em.Handlebars.compile( + '' + + '' + + '{{view.text}}' + + '' + ), rightIcon: Em.Handlebars.compile( - '' + + '' + '{{view.text}}' + '' ) diff --git a/app/controlls/List.js b/app/controlls/List.js index 5e28a0fd4..524b49036 100644 --- a/app/controlls/List.js +++ b/app/controlls/List.js @@ -116,6 +116,16 @@ SDL.List = Em.ContainerView.extend({ this.items.splice(id, 1); this.list.refresh(); }, + + /** Method setting up display mode for correspond components */ + setMode: function(mode){ + var items = this.list.get('childViews'); + + for (var i = 0; i < items.length; ++i) { + var button = items[i]; + button.setMode(mode); + } + }, /** List components */ childViews: [ @@ -152,9 +162,27 @@ SDL.List = Em.ContainerView.extend({ classNames: 'list-item', classNameBindings: [ - 'this.voiceOver' + 'this.voiceOver', + 'dayMode', + 'nightMode', + 'highLightedMode' ], + dayMode:false, + nightMode:false, + highLightedMode:false, + + setMode:function(mode) { + mode = SDL.SDLModel.data.imageModeList.includes(mode) ? mode : SDL.SDLModel.data.imageModeList[0]; + this.set('dayMode', mode == SDL.SDLModel.data.imageModeList[0]); + this.set('nightMode', mode == SDL.SDLModel.data.imageModeList[1]); + this.set('highLightedMode', mode == SDL.SDLModel.data.imageModeList[2]); + }, + + imageModeDidChange: function() { + this.setMode(SDL.SDLModel.data.imageMode); + }.observes('SDL.SDLModel.data.imageMode'), + // Dynamic property set init: function() { @@ -176,6 +204,8 @@ SDL.List = Em.ContainerView.extend({ } ); + element.setMode(SDL.SDLModel.data.imageMode); + // Push element to list this.get('childViews').pushObject(element); } diff --git a/app/controlls/MenuList.js b/app/controlls/MenuList.js index e8adeeb32..0635f936a 100644 --- a/app/controlls/MenuList.js +++ b/app/controlls/MenuList.js @@ -83,6 +83,16 @@ SDL.MenuList = Em.ContainerView.extend({ ); }, + /** Method setting up display mode for correspond components */ + setMode: function(mode){ + var items = this.get('content.childViews'); + + for (var i = 0; i < items.length; ++i) { + var button = items[i]; + button.setMode(mode); + } + }, + classNames: [ 'ffw_list_menu' ], diff --git a/app/model/ClimateControlModel.js b/app/model/ClimateControlModel.js index fbe32a7b8..a44f4f1a6 100644 --- a/app/model/ClimateControlModel.js +++ b/app/model/ClimateControlModel.js @@ -179,8 +179,11 @@ SDL.ClimateControlModel = Em.Object.extend({ return result; }, - getClimateControlData: function() { - var result = { + /** + * @description Generates object containing full climate data properties + */ + generateClimateControlData: function() { + return { fanSpeed: this.climateControlData.fanSpeed, currentTemperature: SDL.ClimateController.getTemperatureStruct( this.climateControlData.temperatureUnit, @@ -203,12 +206,19 @@ SDL.ClimateControlModel = Em.Object.extend({ heatedMirrorsEnable: this.climateControlData.heatedMirrorsEnable, climateEnable: this.climateControlData.climateEnable }; + }, - return result; + /** + * @description Gets climate data object with filtered properties + */ + getClimateControlData: function() { + const climate_data = this.generateClimateControlData(); + const filter_properties = this.getDataForSending(); + return SDL.SDLController.filterObjectProperty(climate_data, filter_properties); }, setClimateData: function(data) { - var before_set = SDL.deepCopy(this.getClimateControlData()); + var before_set = SDL.deepCopy(this.generateClimateControlData()); if(data.climateEnable != null) { this.setClimateEnable(data.climateEnable); @@ -275,7 +285,7 @@ SDL.ClimateControlModel = Em.Object.extend({ this.setHeatedMirrorsEnable(data.heatedMirrorsEnable); } - var after_set = SDL.deepCopy(this.getClimateControlData()); + var after_set = SDL.deepCopy(this.generateClimateControlData()); var properties = SDL.SDLController.getChangedProperties(before_set, after_set); @@ -297,7 +307,7 @@ SDL.ClimateControlModel = Em.Object.extend({ }, sendClimateChangeNotification: function(properties) { - var data = this.getClimateControlData(); + var data = this.generateClimateControlData(); data = SDL.SDLController.filterObjectProperty(data, properties); if (Object.keys(data).length > 0) { FFW.RC.onInteriorVehicleDataNotification({moduleType:'CLIMATE',moduleId: this.UUID, climateControlData: data}); @@ -467,7 +477,7 @@ SDL.ClimateControlModel = Em.Object.extend({ getDataForSending: function() { var dataForSending = []; - var climateData = this.getClimateControlData(); + var climateData = this.generateClimateControlData(); var climateEnable = climateData.climateEnable; if(climateEnable) { for(var key in climateData) { diff --git a/app/model/HmiSettingsModel.js b/app/model/HmiSettingsModel.js index 200631284..84c68a226 100644 --- a/app/model/HmiSettingsModel.js +++ b/app/model/HmiSettingsModel.js @@ -84,11 +84,22 @@ SDL.HmiSettingsModel = Em.Object.extend({ return capabilities; }, + /** + * @function defineAutoTimeValue + * @description Defines which time value should be sent + * accordingly to current system time. + * @return String (DAY or NIGHT) + */ + defineAutoTimeValue: function() { + const time = new Date().getHours(); + return (time > 7 && time < 20 ? 'DAY': 'NIGHT'); + }, + setHmiSettingsData: function(data){ var result = {}; if(data.displayMode && this.displayMode != data.displayMode) { this.set('displayMode',data.displayMode); - result.displayMode = data.displayMode; + result.displayMode = (data.displayMode === 'AUTO' ? this.defineAutoTimeValue() : data.displayMode); } if(data.temperatureUnit && this.temperatureUnit != data.temperatureUnit) { this.set('temperatureUnit',data.temperatureUnit); @@ -114,9 +125,7 @@ SDL.HmiSettingsModel = Em.Object.extend({ distanceUnit: this.distanceUnit }; if(result.displayMode == 'AUTO'){ - var time = new Date().toLocaleTimeString(); - time = parseInt(time.substring(0, time.indexOf(':'))); - result.displayMode = (time > 7 && time < 20? 'DAY': 'NIGHT'); + result.displayMode = this.defineAutoTimeValue(); } return result; }, diff --git a/app/model/SeatModel.js b/app/model/SeatModel.js index eaebcfb66..714df9616 100644 --- a/app/model/SeatModel.js +++ b/app/model/SeatModel.js @@ -208,6 +208,11 @@ SDL.SeatModel = Em.Object.extend({ SDL.deepCopy(this.tempSeatControlData)); }, + updateView: function() { + this.set('tempSeatControlData', SDL.deepCopy(this.seatControlData)); + this.update(); + }, + goToStates: function() { this.update(); }, @@ -231,7 +236,7 @@ SDL.SeatModel = Em.Object.extend({ } this.tempSeatControlData.memory = this.seatMemoryAction; - this.set('seatControlData', this.tempSeatControlData); + this.set('seatControlData', SDL.deepCopy(this.tempSeatControlData)); var memorySlot = "1"; this.memory[memorySlot] = SDL.deepCopy(this.tempSeatControlData); this.createdMemory = memorySlot; @@ -285,7 +290,7 @@ SDL.SeatModel = Em.Object.extend({ break; case 'NONE': - this.set('tempSeatControlData',this.seatControlData); + this.set('tempSeatControlData',SDL.deepCopy(this.seatControlData)); break; } } diff --git a/app/model/media/AudioModel.js b/app/model/media/AudioModel.js index d2622a51b..5fdb06d9b 100644 --- a/app/model/media/AudioModel.js +++ b/app/model/media/AudioModel.js @@ -343,21 +343,6 @@ SDL.AudioModel = Em.Object.extend({ if (SDL.SDLController.model) { SDL.SDLController.model.set('active', true); } - /** - * Go to SDL state - */ - if (SDL.SDLController.model.appType) { - for (var i = 0; i < SDL.SDLController.model.appType.length; i++) { - if (SDL.SDLController.model.appType[i] == 'NAVIGATION' || - SDL.SDLController.model.appType[i] == 'PROJECTION') { - SDL.BaseNavigationView.update(); - SDL.States.goToStates('navigationApp.baseNavigation'); - return; - } - } - } - - SDL.States.goToStates('media.sdlmedia'); }, /** @@ -832,12 +817,13 @@ SDL.AudioModel = Em.Object.extend({ resultNew.volume = data.volume; } for (var i = 0; i < dataLength; i++) { + if (data.equalizerSettings[i].channelId == this.tempEqualizerSettings.channelId) { + this.set('tempEqualizerSettings.channelSetting', data.equalizerSettings[i].channelSetting); + } for (var j = 0; j < currentLength; j++) { if (data.equalizerSettings[i].channelId == this.lastRadioControlStruct.equalizerSettings[j].channelId) { this.lastRadioControlStruct.equalizerSettings[j].channelSetting = SDL.deepCopy(data.equalizerSettings[i].channelSetting); - if (j == this.tempEqualizerSettIndex - 1) { - this.set('tempEqualizerSettings.equalizerSettings', data.equalizerSettings[i].equalizerSettings); - } + break; } } } @@ -888,12 +874,13 @@ SDL.AudioModel = Em.Object.extend({ resultNew.volume = data.volume; } for (var i = 0; i < dataLength; i++) { + if (data.equalizerSettings[i].channelId == this.tempEqualizerSettings.channelId) { + this.set('tempEqualizerSettings.channelSetting', data.equalizerSettings[i].channelSetting); + } for (var j = 0; j < currentLength; j++) { if (data.equalizerSettings[i].channelId == this.lastRadioControlStruct.equalizerSettings[j].channelId) { this.lastRadioControlStruct.equalizerSettings[j].channelSetting = SDL.deepCopy(data.equalizerSettings[i].channelSetting); - if (j == this.tempEqualizerSettIndex - 1) { - this.set('tempEqualizerSettings.equalizerSettings', data.equalizerSettings[i].equalizerSettings); - } + break; } } } diff --git a/app/model/media/AudioModels/MediaCDPlayer.js b/app/model/media/AudioModels/MediaCDPlayer.js index 06fa787e6..fa1424e0b 100644 --- a/app/model/media/AudioModels/MediaCDPlayer.js +++ b/app/model/media/AudioModels/MediaCDPlayer.js @@ -204,6 +204,11 @@ SDL.MediaCDPlayer = Em.Object.extend({ this.prevTrack(); } + if(!FFW.CAN) { + Em.Logger.warn("CAN module is not available. Notification won't be sent"); + return; + } + var self = this, media = self.data.get('selectedItem'); @@ -227,6 +232,11 @@ SDL.MediaCDPlayer = Em.Object.extend({ playTrackPress: function() { this.play(); + if(!FFW.CAN) { + Em.Logger.warn("CAN module is not available. Notification won't be sent"); + return; + } + var self = this, media = self.data.get('selectedItem'); @@ -250,6 +260,11 @@ SDL.MediaCDPlayer = Em.Object.extend({ nextTrackPress: function() { this.nextTrack(); + if(!FFW.CAN) { + Em.Logger.warn("CAN module is not available. Notification won't be sent"); + return; + } + var self = this, media = self.data.get('selectedItem'); diff --git a/app/model/media/AudioModels/RadioModel.js b/app/model/media/AudioModels/RadioModel.js index 92e2391fd..fa456ea37 100755 --- a/app/model/media/AudioModels/RadioModel.js +++ b/app/model/media/AudioModels/RadioModel.js @@ -1192,19 +1192,18 @@ SDL.RadioModel = Em.Object.extend({ this.setFrequencyInteger(parseInt(data)); } if (this.radioControlStruct.band === 'XM') { - this.setFrequencyInteger(parseInt( - (function(value){ + var getBand = function(value, stations){ var kArray = [], vArray = []; - for (key in this.xmStations) { + for (key in stations) { kArray.push(key); - vArray.push(this.xmStations[key]); + vArray.push(stations[key]); } var vIndex = vArray.indexOf(value); return kArray[vIndex]; - })(data) - )); + }; + this.setFrequencyInteger(parseInt(getBand(data,this.xmStations))); } this.updateCurrentFrequencyInfo(); diff --git a/app/model/sdl/Abstract/AppModel.js b/app/model/sdl/Abstract/AppModel.js index 89bc620f2..6fbc75b2e 100644 --- a/app/model/sdl/Abstract/AppModel.js +++ b/app/model/sdl/Abstract/AppModel.js @@ -390,21 +390,33 @@ SDL.ABSAppModel = Em.Object.extend( * @type {Number} */ currentSubMenuId: 'top', + + /** + * Count of submenu depth for DD tracking + * + * @type {Number} + */ + currentMenuDepth: 0, /** * Return current submenu name * * @return {String} */ currentSubMenuLabel: function() { - - //Param "top" is Top level menu index - var submenu, commands = this.commandsList['top']; - for (var i = 0; i < commands.length; i++) { - if (commands[i].menuID == this.currentSubMenuId) { - submenu = commands[i].name; + var commandsList = this.commandsList; + var findMenuName = (commands, menuID) => { + for (id in commands) { + var subMenuCommands = commands[id]; + for (element of subMenuCommands) { + if (element.menuID === menuID) { + return element.name; + } + } } + return 'Options'; } - return this.get('currentSubMenuId') != 'top' ? submenu : 'Options'; + return this.get('currentSubMenuId') != 'top' ? + findMenuName(commandsList, this.currentSubMenuId) : 'Options'; }.property('this.currentSubMenuId'), /** * Interaction chooses data @@ -500,49 +512,84 @@ SDL.ABSAppModel = Em.Object.extend( if (!this.get('commandsList.' + parentID)) { this.commandsList[parentID] = []; } - var commands = this.get('commandsList.' + parentID); - // Magic number is limit of 1000 commands added on one menu - if (commands.length <= 999) { - commands[commands.length] = { - commandID: request.params.cmdID, - name: request.params.menuParams.menuName, - parent: parentID, - position: request.params.menuParams.position ? - request.params.menuParams.position : 0, - isTemplate:request.params.cmdIcon ? - request.params.cmdIcon.isTemplate ?request.params.cmdIcon.isTemplate : null - : null, - icon: request.params.cmdIcon ? request.params.cmdIcon.value : null - }; - if (SDL.SDLController.getApplicationModel(request.params.appID) && - SDL.OptionsView.active) { - SDL.SDLController.buttonsSort(parentID, this.appID); - SDL.OptionsView.commands.refreshItems(); - } - if(request.params.cmdIcon){ - var image = request.params.cmdIcon.value; - var search_offset = image.lastIndexOf('.'); - str='.png'; - var isPng=image.includes(str, search_offset); - if(!isPng){ - FFW.UI.sendUIResult( - SDL.SDLModel.data.resultCode.WARNINGS, request.id, - request.method - ); + + const is_sdl_request = request.id >= 0; + let commands = this.get('commandsList.' + parentID); + let result = SDL.SDLModel.data.resultCode.SUCCESS; + + if (is_sdl_request) { + result = FFW.RPCHelper.getCustomResultCode(this.appID, 'uiAddCommand'); + + if ('DO_NOT_RESPOND' == result) { + Em.Logger.log('Do not respond on this request'); return; } } - if (request.id >= 0) { - FFW.UI.sendUIResult( - SDL.SDLModel.data.resultCode.SUCCESS, request.id, - request.method - ); - } - } else { + + if (FFW.RPCHelper.isSuccessResultCode(result)) { + // Magic number is limit of 1000 commands added on one menu + if (commands.length <= 999) { + var position = request.params.menuParams.position !== undefined ? + request.params.menuParams.position : commands.length; + // Add 4 to the position so the items appear after the default + // exit options. Default exit options have a request id < 0. + if (request.id >= 0 && parentID === 'top') { + position += 5; // for exit application commands + } + var newItem = { + commandID: request.params.cmdID, + name: request.params.menuParams.menuName, + parent: parentID, + isTemplate:request.params.cmdIcon ? + request.params.cmdIcon.isTemplate ?request.params.cmdIcon.isTemplate : null + : null, + icon: request.params.cmdIcon ? request.params.cmdIcon.value : null + }; + // Insert new item at calculated position + commands.splice(position, 0, newItem); + if (SDL.SDLController.getApplicationModel(request.params.appID) && + SDL.OptionsView.active) { + SDL.SDLController.buttonsSort(parentID, this.appID); + SDL.OptionsView.commands.refreshItems(); + } + + if(request.params.cmdIcon) { + + var image = request.params.cmdIcon.value; + if(!SDL.NavigationController.isPng(image)) { + FFW.UI.sendUIResult( + SDL.SDLModel.data.resultCode.WARNINGS, request.id, + request.method); + return; + } + + var callback = function(failed) { + var WARNINGS = SDL.SDLModel.data.resultCode.WARNINGS; + var SUCCESS = SDL.SDLModel.data.resultCode.SUCCESS; + + FFW.UI.sendUIResult( + failed ? WARNINGS : SUCCESS, + request.id, + request.method, + failed ? "Requested image(s) not found" : null); + } + SDL.SDLModel.validateImages(request.id, callback, [image]); + return; + } + + if (is_sdl_request) { + FFW.UI.sendUIResult(result, request.id, request.method); + } + } else { + FFW.UI.sendError( + result, request.id, request.method, + 'Adding more than 1000 item to the top menu or to submenu is not allowed.' + ); + } + } else { FFW.UI.sendError( - SDL.SDLModel.data.resultCode.REJECTED, request.id, - request.method, - 'Adding more than 1000 item to the top menu or to submenu is not allowed.' + result, request.id, request.method, + 'Erroneous response is assigned by settings' ); } }, @@ -581,38 +628,81 @@ SDL.ABSAppModel = Em.Object.extend( * @param {Object} */ addSubMenu: function(request) { - - // parentID is equal to 'top' cause Top level menu ID - var parentID = 'top'; - var commands = this.get('commandsList.' + parentID); - // Magic number is limit of 1000 commands added on one menu - if (commands.length <= 999) { - this.commandsList[request.params.menuID] = []; - commands[commands.length] = { - menuID: request.params.menuID, - name: request.params.menuParams.menuName ? - request.params.menuParams.menuName : '', - parent: 0, - position: request.params.menuParams.position ? - request.params.menuParams.position : 0, - icon: request.params.menuIcon ? request.params.menuIcon.value : null - }; - if (SDL.SDLController.getApplicationModel(request.params.appID) && - SDL.OptionsView.active) { - SDL.SDLController.buttonsSort(parentID, this.appID); - SDL.OptionsView.commands.refreshItems(); - } - FFW.UI.sendUIResult( - SDL.SDLModel.data.resultCode.SUCCESS, request.id, - request.method - ); - } else { + // Check for duplicate submenu + if (request.params.menuID in this.commandsList) { FFW.UI.sendError( - SDL.SDLModel.data.resultCode.REJECTED, request.id, + SDL.SDLModel.data.resultCode.INVALID_ID, request.id, request.method, - 'Adding more than 1000 item to the top menu or to submenu is not allowed.' + 'Submenu ID already exists' ); + return; } + + // parentID is equal to 'top' cause Top level menu ID + var parentID = request.params.menuParams.parentID ? request.params.menuParams.parentID : 'top'; + var commands = this.get('commandsList.' + parentID); + + result = FFW.RPCHelper.getCustomResultCode(this.appID, 'AddSubmenu'); + if ('DO_NOT_RESPOND' == result) { + Em.Logger.log('Do not respond on this request'); + return; + } + + if(FFW.RPCHelper.isSuccessResultCode(result)) { + // Magic number is limit of 1000 commands added on one menu + if (commands.length <= 999) { + this.commandsList[request.params.menuID] = []; + var position = request.params.menuParams.position !== undefined ? + request.params.menuParams.position : commands.length; + // Add 4 to the position so the items appear after the default + // exit options. Default exit options have a request id < 0. + if (request.id >= 0 && parentID === 'top') { + position += 5; // for exit application commands + } + + var newItem = { + menuID: request.params.menuID, + name: request.params.menuParams.menuName ? + request.params.menuParams.menuName : '', + parent: parentID, + icon: request.params.menuIcon ? request.params.menuIcon.value : null + }; + // Insert new item at calculated position + commands.splice(position, 0, newItem); + if (SDL.SDLController.getApplicationModel(request.params.appID) && + SDL.OptionsView.active) { + SDL.SDLController.buttonsSort(parentID, this.appID); + SDL.OptionsView.commands.refreshItems(); + } + var callback = function(failed) { + var WARNINGS = SDL.SDLModel.data.resultCode.WARNINGS; + var SUCCESS = SDL.SDLModel.data.resultCode.SUCCESS; + + FFW.UI.sendUIResult( + failed ? WARNINGS : SUCCESS, + request.id, + request.method, + failed ? "Requested image(s) not found" : null); + } + var imageList = []; + if(request.params.menuIcon) { + imageList.push(request.params.menuIcon.value); + } + SDL.SDLModel.validateImages(request.id, callback, imageList); + } else { + FFW.UI.sendError( + SDL.SDLModel.data.resultCode.REJECTED, request.id, + request.method, + 'Adding more than 1000 item to the top menu or to submenu is not allowed.' + ); + } + } else { + FFW.UI.sendError( + result, request.id, + request.method, + 'Erroneous response is assigned by settings' + ); + } }, /** * Delete submenu and related commands from list @@ -620,13 +710,22 @@ SDL.ABSAppModel = Em.Object.extend( * @param {Number} */ deleteSubMenu: function(menuID) { - if (this.commandsList['top'].filterProperty('commandID', menuID)) { - this.get('commandsList.top').removeObjects( - this.get('commandsList.top').filterProperty('menuID', menuID) - ); - //delete(this.commandsList[menuID]); + var commandsList = this.commandsList; + + for (id in commandsList) { + var filteredObjects = commandsList[id].filterProperty('menuID', menuID); + + if (filteredObjects.length > 0) { + commandsList[id].removeObjects(filteredObjects); + } + } + + if (menuID in commandsList) { + delete(commandsList[menuID]) + return SDL.SDLModel.data.resultCode.SUCCESS; } - return SDL.SDLModel.data.resultCode.SUCCESS; + + return SDL.SDLModel.data.resultCode.INVALID_ID; }, /** * SDL UI CreateInteraction response handeler push set of commands to @@ -667,31 +766,34 @@ SDL.ABSAppModel = Em.Object.extend( createWindow: function(windowParam) { var content = {}; if (windowParam.duplicateUpdatesFromWindowID === 0) { - var showStringsArray = []; - SDL.SDLController.model.appInfo.field1 ? showStringsArray.push({ - "fieldName": "mainField1", - "fieldText": SDL.SDLController.model.appInfo.field1 - }) : null ; + var app_info = SDL.SDLController.model ? SDL.SDLController.model.appInfo : null; - SDL.SDLController.model.appInfo.field2 ? showStringsArray.push({ - "fieldName": "mainField2", - "fieldText": SDL.SDLController.model.appInfo.field2 - }) : null ; + var showStringsArray = []; + if (app_info) { + showStringsArray.push({ + "fieldName": "mainField1", + "fieldText": app_info.field1 + }); + showStringsArray.push({ + "fieldName": "mainField2", + "fieldText": SDL.SDLController.model.appInfo.field2 + }); - content["showStrings"] = showStringsArray; - - content["softButtons"] = this.get("softButtons").slice(0,4); - - if (SDL.SDLController.model.appInfo.mainImage) { - content["graphic"] = { - "value" : SDL.SDLController.model.appInfo.mainImage - }; - } else if (SDL.SDLController.model.appInfo.trackIcon) { - content["graphic"] = { - "value" : SDL.SDLController.model.appInfo.trackIcon - }; + if (app_info.mainImage) { + content["graphic"] = { + "value" : app_info.mainImage + }; + } else if (app_info.trackIcon) { + content["graphic"] = { + "value" : app_info.trackIcon + }; + } } + content["showStrings"] = showStringsArray; + content["softButtons"] = windowParam.type == 'WIDGET' ? + this.get("softButtons").slice(0,4) : + this.get("softButtons"); content["templateConfiguration"] = this.templateConfiguration; windowParam.content = content; diff --git a/app/model/sdl/Abstract/Model.js b/app/model/sdl/Abstract/Model.js index 6f5acfa0b..3854c6796 100644 --- a/app/model/sdl/Abstract/Model.js +++ b/app/model/sdl/Abstract/Model.js @@ -200,48 +200,28 @@ SDL.SDLModel = Em.Object.extend({ onFileRemoved: function(params) { var result = false; + var app_model = SDL.SDLController.getApplicationModel(params.appID); + var is_image_type = ['GRAPHIC_PNG', 'GRAPHIC_BMP', 'GRAPHIC_JPEG'].includes(params.fileType); - if (( - params.fileType === 'GRAPHIC_PNG' || params.fileType === 'GRAPHIC_BMP' || - params.fileType === 'GRAPHIC_JPEG') && - SDL.SDLController.getApplicationModel(params.appID)) { - result = SDL.SDLController.getApplicationModel(params.appID). - onImageRemoved(params.fileName); - - if (SDL.SDLController.getApplicationModel(params.appID).appIcon. - indexOf(params.fileName) != -1 && - params.fileName.length == - SDL.SDLController.getApplicationModel(params.appID).appIcon.length) { - SDL.SDLController.getApplicationModel(params.appID). - set('appIcon', SDL.SDLModel.data.defaultListOfIcons.app); + if (is_image_type && app_model) { + result = app_model.onImageRemoved(params.fileName); + + if (app_model.appIcon.includes(params.fileName) && + params.fileName.length == app_model.appIcon.length) { + app_model.set('appIcon', SDL.SDLModel.data.defaultListOfIcons.app); } - if (SDL.SDLController.getApplicationModel(params.appID - ).constantTBTParams) { - - if (SDL.SDLController.getApplicationModel(params.appID - ).constantTBTParams.turnIcon && - SDL.SDLController.getApplicationModel(params.appID).constantTBTParams. - turnIcon.value.indexOf(params.fileName) != -1 && - params.fileName.length == SDL.SDLController.getApplicationModel( - params.appID - ).constantTBTParams.turnIcon.value.length) { - SDL.SDLController.getApplicationModel(params.appID - ).constantTBTParams.turnIcon.value = - SDL.SDLModel.data.defaultListOfIcons.command; + if (app_model.constantTBTParams) { + if (app_model.constantTBTParams.turnIcon && + app_model.constantTBTParams.turnIcon.value === params.fileName) { + app_model.constantTBTParams.turnIcon.value = SDL.SDLModel.data.defaultListOfIcons.command; SDL.TurnByTurnView.activate(params.appID); } - if (SDL.SDLController.getApplicationModel(params.appID - ).constantTBTParams.nextTurnIcon && - SDL.SDLController.getApplicationModel(params.appID).constantTBTParams. - nextTurnIcon.value.indexOf(params.fileName) != -1 && - params.fileName.length == SDL.SDLController.getApplicationModel( - params.appID - ).constantTBTParams.nextTurnIcon.value.length) { - SDL.SDLController.getApplicationModel(params.appID - ).constantTBTParams.nextTurnIcon.value = - SDL.SDLModel.data.defaultListOfIcons.command; + if (app_model.constantTBTParams.nextTurnIcon && + app_model.constantTBTParams.nextTurnIcon.value.indexOf(params.fileName) != -1 && + params.fileName.length == app_model.constantTBTParams.nextTurnIcon.value.length) { + app_model.constantTBTParams.nextTurnIcon.value = SDL.SDLModel.data.defaultListOfIcons.command; SDL.TurnByTurnView.activate(params.appID); } } @@ -284,42 +264,28 @@ SDL.SDLModel = Em.Object.extend({ } } - var len = SDL.SDLController.getApplicationModel(params.appID - ).turnList.length; + var len = app_model.turnList.length; for (var i = 0; i < len; i++) { - if (!SDL.SDLController.getApplicationModel(params.appID - ).turnList[i].turnIcon) { + if (!app_model.turnList[i].turnIcon) { continue; } - if (SDL.SDLController.getApplicationModel(params.appID - ).turnList[i].turnIcon.value.indexOf(params.fileName) != -1 && - params.fileName.length == SDL.SDLController.getApplicationModel( - params.appID - ).turnList[i].turnIcon.value.length) { - SDL.SDLController.getApplicationModel(params.appID - ).turnList[i].turnIcon.value = - SDL.SDLModel.data.defaultListOfIcons.command; + if (app_model.turnList[i].turnIcon.value.indexOf(params.fileName) != -1 && + params.fileName.length == app_model.turnList[i].turnIcon.value.length) { + app_model.turnList[i].turnIcon.value = SDL.SDLModel.data.defaultListOfIcons.command; } } SDL.TBTTurnList.updateList(params.appID); - if (SDL.SDLController.getApplicationModel(params.appID).softButtons) { - var len = SDL.SDLController.getApplicationModel(params.appID - ).softButtons.length; + if (app_model.softButtons) { + var len = app_model.softButtons.length; for (var i = 0; i < len; i++) { - if (!SDL.SDLController.getApplicationModel(params.appID - ).softButtons[i].image) { + if (!app_model.softButtons[i].image) { continue; } - if (SDL.SDLController.getApplicationModel(params.appID - ).softButtons[i].image.value.indexOf(params.fileName) != -1 && - params.fileName.length == SDL.SDLController.getApplicationModel( - params.appID - ).softButtons[i].image.value.length) { - SDL.SDLController.getApplicationModel(params.appID - ).softButtons[i].image.value = - SDL.SDLModel.data.defaultListOfIcons.command; + if (app_model.softButtons[i].image.value.indexOf(params.fileName) != -1 && + params.fileName.length == app_model.softButtons[i].image.value.length) { + app_model.softButtons[i].image.value = SDL.SDLModel.data.defaultListOfIcons.command; } } @@ -345,15 +311,12 @@ SDL.SDLModel = Em.Object.extend({ } } - if (SDL.SDLController.getApplicationModel(params.appID - ).globalProperties.vrHelp) { - for (var i = 0; i < SDL.SDLController.getApplicationModel(params.appID - ).globalProperties.vrHelp.length; i++) { - if (SDL.SDLController.getApplicationModel(params.appID - ).globalProperties.vrHelp[i].image.value === params.fileName) { - SDL.SDLController.getApplicationModel(params.appID - ).globalProperties.vrHelp[i].image.value = - SDL.SDLModel.data.defaultListOfIcons.command; + if (app_model.globalProperties.vrHelp) { + for (var i = 0; i < app_model.globalProperties.vrHelp.length; i++) { + if (app_model.globalProperties.vrHelp[i].image && + app_model.globalProperties.vrHelp[i].image.value === params.fileName) { + app_model.globalProperties.vrHelp[i].image.value = + SDL.SDLModel.data.defaultListOfIcons.command; } } } @@ -999,7 +962,10 @@ SDL.SDLModel = Em.Object.extend({ } if (SDL.SDLController.getApplicationModel(params.appID)) { for (var i in params) { - if (i === 'keyboardProperties') { + if (i === "appID") { + continue; + } + else if (i === 'keyboardProperties') { mergeKeyboardProperties(params[i]); } else { SDL.SDLController.getApplicationModel(params.appID). @@ -1011,6 +977,92 @@ SDL.SDLModel = Em.Object.extend({ } }, + /** + * List of images(paths to images) to check. + */ + imageCheckList: {}, + + /** + * @function validateImages + * @description Checks if image exists by path provided in request data + * @param requestID - request id, to which images belong + * @param callback - user callback after check + * @param imageList - list of paths to check + */ + validateImages: function(requestID, callback, imageList) { + if(imageList == null || imageList.length == 0) { + callback(false); + return; + } + + this.imageCheckList[requestID] = []; + const filteredImageList = imageList.filter(function(item, pos) { + return imageList.indexOf(item) == pos; + }); + + filteredImageList.forEach(image => { + this.imageCheckList[requestID].push({ + 'path': image, + 'checkResult': null + }); + }); + + for(var i = 0; i < this.imageCheckList[requestID].length; i++) { + var image = new Image(); + image.onload = function() { + for(var i = 0; i < SDL.SDLModel.imageCheckList[requestID].length; i++) { + var formattedImgPath = this.src.substring(this.src.indexOf('://') + '://'.length); + var path = SDL.SDLModel.imageCheckList[requestID][i].path; + if(path === formattedImgPath) { + SDL.SDLModel.imageCheckList[requestID][i].checkResult = true; + break; + } + } + SDL.SDLModel.finalizeImageValidation(requestID, callback); + }; + image.onerror = function() { + for(var i = 0; i < SDL.SDLModel.imageCheckList[requestID].length; i++) { + var formattedImgPath = this.src.substring(this.src.indexOf('://') + '://'.length); + var path = SDL.SDLModel.imageCheckList[requestID][i].path; + if(path === formattedImgPath) { + SDL.SDLModel.imageCheckList[requestID][i].checkResult = false; + break; + } + } + SDL.SDLModel.finalizeImageValidation(requestID, callback); + }; + image.src = this.imageCheckList[requestID][i].path; + } + }, + + /** + * @function finalizeImageValidation + * @description Collects result of images validation. + * If validation is finished - calls user callback function. + * @param callback - user callback. + */ + finalizeImageValidation: function(requestID, callback) { + var failed = false; + var BreakException = {}; + try { + SDL.SDLModel.imageCheckList[requestID].forEach(image => { + if (image.checkResult === null) { + throw BreakException; + } + if (!image.checkResult) { + failed = true; + } + }); + } catch (exception) { + if (exception == BreakException) { + return; + } + } + + delete SDL.SDLModel.imageCheckList.requestID; + callback(failed); + }, + /** * Method to call function from DeviceListView to show list of connected * devices @@ -1142,6 +1194,47 @@ SDL.SDLModel = Em.Object.extend({ } }, + /** + * SDL UI SubtleAlert response handler show popup window + * + * @param {Object} + * message Object with parameters come from SDLCore + * @param {Number} + * subtleAlertRequestId Id of current handled request + */ + onUISubtleAlert: function(message, subtleAlertRequestId) { + if (SDL.AlertPopUp.active) { + SDL.SDLController.subtleAlertResponse(SDL.SDLModel.data.resultCode.REJECTED, + subtleAlertRequestId, + 'an Alert is active', + SDL.AlertPopUp.endTime - Date.now()); + } else if (SDL.ScrollableMessage.active) { + SDL.SDLController.subtleAlertResponse(SDL.SDLModel.data.resultCode.REJECTED, + subtleAlertRequestId, + 'a ScrollableMessage is active', + SDL.ScrollableMessage.endTime - Date.now()); + } else if (SDL.InteractionChoicesView.active) { + SDL.SDLController.subtleAlertResponse(SDL.SDLModel.data.resultCode.REJECTED, + subtleAlertRequestId, + 'a PerformInteraction is active', + SDL.InteractionChoicesView.endTime - Date.now()); + } else if (SDL.SubtleAlertPopUp.active) { + SDL.SDLController.subtleAlertResponse(SDL.SDLModel.data.resultCode.REJECTED, + subtleAlertRequestId, + 'another SubtleAlert is active', + SDL.SubtleAlertPopUp.endTime - Date.now()); + } else if (SDL.AlertManeuverPopUp.activate) { + SDL.SDLController.subtleAlertResponse(SDL.SDLModel.data.resultCode.REJECTED, + subtleAlertRequestId, + 'an AlertManeuver popup is active', + SDL.AlertManeuverPopUp.endTime - Date.now()); + } else { + SDL.SubtleAlertPopUp.SubtleAlertActive(message, subtleAlertRequestId); + return true; + } + return false; + }, + /** * SDL UI PerformInteraction response handler show popup window * @@ -1150,6 +1243,12 @@ SDL.SDLModel = Em.Object.extend({ */ uiPerformInteraction: function(message) { + if (!message.params) { + FFW.UI.sendError(SDL.SDLModel.data.resultCode.INVALID_DATA, message.id, + message.method, 'Empty message was received for UI.PerformInteraction' + ); + return false; + } if (!SDL.SDLController.getApplicationModel(message.params.appID ).activeRequests.uiPerformInteraction) { if (message.params && message.params.vrHelpTitle && @@ -1163,9 +1262,13 @@ SDL.SDLModel = Em.Object.extend({ SDL.InteractionChoicesView.cancelID = message.params.cancelID; - if (message.params && message.params.choiceSet == null) { - FFW.UI.sendUIResult(SDL.SDLModel.data.resultCode.SUCCESS, - message.id, 'UI.PerformInteraction'); + // Images are not validated for this request since choiceId cannot be sent back in + // the case of a WARNINGS response + + if(message.params.choiceSet == null){ + FFW.UI.sendUIResult(SDL.SDLModel.data.resultCode.SUCCESS, + message.id, 'UI.PerformInteraction' + ); return true; } @@ -1177,7 +1280,6 @@ SDL.SDLModel = Em.Object.extend({ return true; } else { - FFW.UI.sendError(SDL.SDLModel.data.resultCode.REJECTED, message.id, message.method, 'UI PerformInterection REJECTED on HMI' ); @@ -1332,6 +1434,12 @@ SDL.SDLModel = Em.Object.extend({ } } SDL.TTSPopUp.ActivateTTS(message, files, appID); + } else { + FFW.TTS.sendError( + SDL.SDLModel.data.resultCode.WARNINGS, this.requestId, 'TTS.Speak', + 'No TTS Chunks provided in Speak request' + ); + this.requestId = null; } }, @@ -1496,7 +1604,9 @@ SDL.SDLModel = Em.Object.extend({ SDL.TurnByTurnView.deactivate(); - if (!SDL.SDLModel.data.phoneCallActive && reason == 'GENERAL') { + if (!SDL.SDLModel.data.phoneCallActive && + !SDL.SDLModel.data.templateChangeInProgress && + reason == 'GENERAL') { FFW.BasicCommunication.OnAppDeactivated(appID); } } diff --git a/app/model/sdl/Abstract/data.js b/app/model/sdl/Abstract/data.js index 81d202896..65c3d8624 100644 --- a/app/model/sdl/Abstract/data.js +++ b/app/model/sdl/Abstract/data.js @@ -33,6 +33,15 @@ SDL.SDLModelData = Em.Object.create( { + + init: function(){ + this.resultCodes = Object.keys(this.resultCode); + }, + + /** + * Array of result codes + */ + resultCodes: null, /** * List of default app permissions entityes for AppPermissionsView */ @@ -129,6 +138,10 @@ SDL.SDLModelData = Em.Object.create( * Active state of phone call on HMI for Deactivate app to handle event */ phoneCallActive: false, + /** + * True, if active app is currently changing template + */ + templateChangeInProgress: false, /** * FLAG of any app in limited level exists */ @@ -455,7 +468,10 @@ SDL.SDLModelData = Em.Object.create( 'NO_DEVICES_CONNECTED': 20, 'WARNINGS': 21, 'GENERIC_ERROR': 22, - 'USER_DISALLOWED': 23 + 'USER_DISALLOWED': 23, + 'TRUNCATED_DATA': 24, + 'SAVED': 25, + 'READ_ONLY': 26 }, /** * Enum with app priority rankings @@ -468,6 +484,20 @@ SDL.SDLModelData = Em.Object.create( 'NORMAL': 4, 'NONE': 5 }, + /** + * Array of vehicle data result codes + */ + vehicleDataResultCode: [ + 'SUCCESS', + 'TRUNCATED_DATA', + 'DISALLOWED', + 'USER_DISALLOWED', + 'INVALID_ID', + 'VEHICLE_DATA_NOT_AVAILABLE', + 'DATA_ALREADY_SUBSCRIBED', + 'DATA_NOT_SUBSCRIBED', + 'IGNORED' + ], /** * Info navigationApp data for ShowConstantTBT request * @@ -617,6 +647,11 @@ SDL.SDLModelData = Em.Object.create( * @type {String} */ hmiUILanguage: 'EN-US', + /** + * CCPU version value + * @type {String} + */ + ccpuVersion: '12345_US', /** * Parameter describes if performInteraction session was started on HMI * this flag set to true when UI.PerformInteraction request came on HMI @@ -677,6 +712,12 @@ SDL.SDLModelData = Em.Object.create( 'Night mode', 'Highlighted mode' ], + /** + * @description Current display mode value + * @type {String} + */ + imageMode:'Highlighted mode', + windowType: { "MAIN": 0, "WIDGET": 1 @@ -700,163 +741,181 @@ SDL.SDLModelData = Em.Object.create( "textFields": [ { "name": "mainField1", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 500, "rows": 1 }, { "name": "mainField2", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 500, "rows": 1 }, { "name": "statusBar", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 500, "rows": 1 }, { "name": "mediaClock", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 500, "rows": 1 }, { "name": "mediaTrack", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 500, "rows": 1 }, { "name": "templateTitle", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 100, "rows": 1 }, { "name": "alertText1", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 500, "rows": 1 }, { "name": "alertText2", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 500, "rows": 1 }, { "name": "alertText3", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 500, "rows": 1 }, { "name": "scrollableMessageBody", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 500, "rows": 1 }, { "name": "initialInteractionText", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 500, "rows": 1 }, { "name": "navigationText1", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 500, "rows": 1 }, { "name": "navigationText2", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 500, "rows": 1 }, { "name": "ETA", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 500, "rows": 1 }, { "name": "totalDistance", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 500, "rows": 1 }, { "name": "audioPassThruDisplayText1", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 500, "rows": 1 }, { "name": "audioPassThruDisplayText2", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 500, "rows": 1 }, { "name": "sliderHeader", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 500, "rows": 1 }, { "name": "sliderFooter", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 500, "rows": 1 }, { "name": "menuName", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 500, "rows": 1 }, { "name": "secondaryText", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 500, "rows": 1 }, { "name": "tertiaryText", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 500, "rows": 1 }, { "name": "menuTitle", - "characterSet": "TYPE2SET", - "width": 500, + "characterSet": "UTF_8", + "width": 10, "rows": 1 }, { "name": "locationName", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 500, "rows": 1 }, { "name": "locationDescription", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 500, "rows": 1 }, { "name": "addressLines", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 500, "rows": 1 }, { "name": "phoneNumber", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", + "width": 500, + "rows": 1 + }, + { + "name": "subtleAlertText1", + "characterSet": "UTF_8", + "width": 500, + "rows": 1 + }, + { + "name": "subtleAlertText2", + "characterSet": "UTF_8", + "width": 500, + "rows": 1 + }, + { + "name": "subtleAlertSoftButtonText", + "characterSet": "UTF_8", "width": 500, "rows": 1 } @@ -1017,11 +1076,23 @@ SDL.SDLModelData = Em.Object.create( 'resolutionWidth': 105, 'resolutionHeight': 65 } + }, + { + 'name': 'subtleAlertIcon', + 'imageTypeSupported': [ + 'GRAPHIC_BMP', + 'GRAPHIC_JPEG', + 'GRAPHIC_PNG' + ], + 'imageResolution': { + 'resolutionWidth': 105, + 'resolutionHeight': 65 + } } ], "imageTypeSupported": ["STATIC", "DYNAMIC"], "numCustomPresetsAvailable": 8, - "templatesAvailable": ["TEXT_WITH_GRAPHIC", "BUTTONS_WITH_GRAPHIC", "GRAPHIC_WITH_TEXT"], + "templatesAvailable": ["MEDIA", "NON-MEDIA", "DEFAULT", "NAV_FULLSCREEN_MAP", 'WEB_VIEW'], "buttonCapabilities": [ { "longPressAvailable": true, @@ -1159,7 +1230,11 @@ SDL.SDLModelData = Em.Object.create( "upDownAvailable": true, "imageSupported": true, "textSupported": true - }] + }], + "dynamicUpdateCapabilities": { + "supportedDynamicImageFieldNames": ["subMenuIcon", "menuIcon"], + "supportsDynamicSubMenus": true + } }] }], } @@ -1181,7 +1256,7 @@ SDL.SDLModelData = Em.Object.create( "menuLayoutsAvailable": ["LIST"], "textFields": [{ "name": "mainField1", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 500, "rows": 1 }], @@ -1488,6 +1563,17 @@ SDL.SDLModelData = Em.Object.create( levelspan: 1 } ] + }, + + /** + * Enum for media Player Indicator + */ + exitCommandsEnum: { + 'DRIVER_DISTRACTION_VIOLATION': -1, + 'USER_EXIT': -2, + 'UNAUTHORIZED_TRANSPORT_REGISTRATION': -3, + 'RESOURCE_CONSTRAINT': -4, + 'CLOSE_CLOUD_CONNECTION': -5 } } ); diff --git a/app/model/sdl/MediaModel.js b/app/model/sdl/MediaModel.js index e8d8d6ead..3a23ab1e3 100644 --- a/app/model/sdl/MediaModel.js +++ b/app/model/sdl/MediaModel.js @@ -40,9 +40,7 @@ SDL.SDLMediaModel = SDL.ABSAppModel.extend({ var subscribeVIData = {}; for (var key in SDL.SDLVehicleInfoModel.vehicleData) { - if (key != 'externalTemperature') { - subscribeVIData[key] = false; - } + subscribeVIData[key] = false; } this.set('subscribedData', subscribeVIData); @@ -84,11 +82,13 @@ SDL.SDLMediaModel = SDL.ABSAppModel.extend({ this.set('VRCommands', []); this.set('tbtActivate', false); this.set('isPlaying', true); + this.set('globalProperties', Em.Object.create()); this.set('globalProperties.helpPrompt', []); this.set('globalProperties.timeoutPrompt', []); this.set('globalProperties.keyboardProperties', Em.Object.create()); this.set('globalProperties.keyboardProperties.keyboardLayout', 'QWERTY'); this.set('globalProperties.keyboardProperties.limitedCharacterList', []); + this.set('globalProperties.menuIcon', Em.Object.create()); this.set('commandsList', {'top': []}); this.set('softButtons', []); diff --git a/app/model/sdl/NonMediaModel.js b/app/model/sdl/NonMediaModel.js index 54a07a1ab..318b8ab68 100644 --- a/app/model/sdl/NonMediaModel.js +++ b/app/model/sdl/NonMediaModel.js @@ -40,9 +40,7 @@ SDL.SDLNonMediaModel = SDL.ABSAppModel.extend({ var subscribeVIData = {}; for (var key in SDL.SDLVehicleInfoModel.vehicleData) { - if (key != 'externalTemperature') { - subscribeVIData[key] = false; - } + subscribeVIData[key] = false; } this.set('subscribedData', subscribeVIData); @@ -86,11 +84,13 @@ SDL.SDLNonMediaModel = SDL.ABSAppModel.extend({ this.set('initialColorScheme.displayLayout', this.displayLayout); this.set('VRCommands', []); this.set('tbtActivate', false); + this.set('globalProperties', Em.Object.create()); this.set('globalProperties.helpPrompt', []); this.set('globalProperties.timeoutPrompt', []); this.set('globalProperties.keyboardProperties', Em.Object.create()); this.set('globalProperties.keyboardProperties.keyboardLayout', 'QWERTY'); this.set('globalProperties.keyboardProperties.limitedCharacterList', []); + this.set('globalProperties.menuIcon', Em.Object.create()); this.set('inactiveWindows', []); this.set('backgroundWindows', []); @@ -273,6 +273,29 @@ SDL.SDLNonMediaModel = SDL.ABSAppModel.extend({ sdlSetMediaClockTimer: function() { return; - } + }, + + classNameBindings: [ + 'dayMode', + 'nightMode', + 'highLightedMode' + ], + + dayMode:false, + nightMode:false, + highLightedMode:false, + + /** + * @description Method applies image mode view for model. + * @param {Number} + */ + setMode:function(mode){ + if(this.isTemplate){ + mode = SDL.SDLModel.data.imageModeList.includes(mode) ? mode : SDL.SDLModel.data.imageModeList[0]; + this.set('dayMode', mode == SDL.SDLModel.data.imageModeList[0]); + this.set('nightMode', mode == SDL.SDLModel.data.imageModeList[1]); + this.set('highLightedMode', mode == SDL.SDLModel.data.imageModeList[2]); + } + }, } ); diff --git a/app/model/sdl/RModel.js b/app/model/sdl/RModel.js index 188aa26f6..e5740290b 100644 --- a/app/model/sdl/RModel.js +++ b/app/model/sdl/RModel.js @@ -61,6 +61,11 @@ SDL.RModel = SDL.SDLModel.extend({ */ webApplicationFramesMap: {}, + /** + * Map of app id and corresponding policy app ids + */ + appIDtoPolicyAppIDMapping: {}, + /** * Current drivers device flag * @@ -193,7 +198,7 @@ SDL.RModel = SDL.SDLModel.extend({ 'cmdID': -2, 'vrCommands': ['USER_EXIT ' + params.appName], 'appID': params.appID, - 'type': 'Command' + 'type': 'Application' }; this.addCommandVR(message); diff --git a/app/model/sdl/VehicleInfoModel.js b/app/model/sdl/VehicleInfoModel.js index 3eec53096..c76f8a97f 100644 --- a/app/model/sdl/VehicleInfoModel.js +++ b/app/model/sdl/VehicleInfoModel.js @@ -51,7 +51,11 @@ SDL.SDLVehicleInfoModel = Em.Object.create( 'THIRD', 'FOURTH', 'FIFTH', - 'SIXTH' + 'SIXTH', + 'SEVENTH', + 'EIGHTH', + 'NINTH', + 'TENTH' ], /** * Data changed in Odometr Input in VehicleInfo popUp @@ -112,6 +116,7 @@ SDL.SDLVehicleInfoModel = Em.Object.create( 'externalTemperature': 'VEHICLEDATA_EXTERNTEMP', 'turnSignal': 'VEHICLEDATA_TURNSIGNAL', 'vin': 'VEHICLEDATA_VIN', + 'gearStatus': 'VEHICLEDATA_GEARSTATUS', 'prndl': 'VEHICLEDATA_PRNDL', 'tirePressure': 'VEHICLEDATA_TIREPRESSURE', 'odometer': 'VEHICLEDATA_ODOMETER', @@ -134,8 +139,10 @@ SDL.SDLVehicleInfoModel = Em.Object.create( 'abs_State': 'VEHICLEDATA_ABS_STATE', 'turnSignal': 'VEHICLEDATA_TURNSIGNAL', 'tirePressureValue': 'VEHICLEDATA_TIREPRESSURE_VALUE', - 'tpms': 'VEHICLEDATA_TPMS', - 'cloudAppVehicleID': 'VEHICLEDATA_CLOUDAPPVEHICLEID' + 'cloudAppVehicleID': 'VEHICLEDATA_CLOUDAPPVEHICLEID', + 'handsOffSteering': 'VEHICLEDATA_HANDSOFFSTEERING', + 'stabilityControlsStatus': 'VEHICLEDATA_STABILITYCONTROLSSTATUS', + 'windowStatus': 'VEHICLEDATA_WINDOWSTATUS' }, /** * Stored VehicleInfo Data @@ -169,11 +176,20 @@ SDL.SDLVehicleInfoModel = Em.Object.create( 'fuelLevel': 0.2E0, 'fuelLevel_State': 'UNKNOWN', 'instantFuelConsumption': 2.2E0, - 'externalTemperature': null, + 'externalTemperature': 20.5E0, 'vin': '52-452-52-752', 'turnSignal': 'OFF', 'prndl': 'PARK', + 'gearStatus': { + 'userSelectedGear': 'DRIVE', + 'actualGear': 'PARK', + 'transmissionType': 'AUTOMATIC' + }, 'electronicParkBrakeStatus': 'OPEN', + 'stabilityControlsStatus': { + 'escSystem': 'OFF', + 'trailerSwayControl': 'OFF' + }, 'tirePressure': { 'pressureTelltale': 'OFF', 'leftFront': { @@ -210,7 +226,11 @@ SDL.SDLVehicleInfoModel = Em.Object.create( 'fuelRange': [ { 'type':'GASOLINE', - 'range': 400 + 'range': 400, + 'level': 10, + 'levelState': 'NORMAL', + 'capacity': 100, + 'capacityUnit': 'LITERS' } ], 'odometer': 23, @@ -306,12 +326,12 @@ SDL.SDLVehicleInfoModel = Em.Object.create( 'frontRecommended': 2.2E0, 'rearRecommended': 2.2E0 }, - 'tpms': 'TIRES_NOT_TRAINED', 'cloudAppVehicleID': 'SDLVehicleNo123', 'displayResolution': { 'width': 800, 'height': 480 - } + }, + 'handsOffSteering': false // // 'avgFuelEconomy': 0.1, // 'batteryVoltage': 12.5, @@ -435,11 +455,26 @@ SDL.SDLVehicleInfoModel = Em.Object.create( */ SubscribeVehicleData: function(message) { var subscribeVIData = {}; - for (var key in message.params) { + var customResultCode = FFW.RPCHelper.getCustomResultCode(null, 'SubscribeVehicleData'); + + if ('DO_NOT_RESPOND' == customResultCode['SubscribeVehicleData']) { + Em.Logger.log('Do not respond on this request'); + return; + } + + const is_user_allowed_code = + FFW.RPCHelper.isSuccessResultCode(customResultCode['SubscribeVehicleData']); + + for (var key in message.params){ if (key === 'clusterModeStatus') { key = 'clusterModes'; } + subscribeVIData[key] = { + dataType: this.eVehicleDataType[key], + resultCode: customResultCode.vehicleDataStruct[key], + } + var vehicleDataType = this.eVehicleDataType.hasOwnProperty(key) ? this.eVehicleDataType[key] : "VEHICLEDATA_OEM_CUSTOM_DATA"; @@ -459,22 +494,22 @@ SDL.SDLVehicleInfoModel = Em.Object.create( continue; } - if (key === 'externalTemperature') { - subscribeVIData[key] = { - dataType: vehicleDataType, - resultCode: 'VEHICLE_DATA_NOT_AVAILABLE' - }; - continue; + if (is_user_allowed_code) { + SDL.SDLModel.subscribedData[key] = true; } - SDL.SDLModel.subscribedData[key] = true; subscribeVIData[key] = { dataType: vehicleDataType, - resultCode: 'SUCCESS' + resultCode: is_user_allowed_code ? 'SUCCESS' : 'USER_DISALLOWED' }; } var resultCode = this.CalculateSubscriptionsResultCode(subscribeVIData); + if (customResultCode['SubscribeVehicleData'] != SDL.SDLModel.data.resultCode.SUCCESS) { + // Custom result code specified by user has a higher priority for response + resultCode = customResultCode['SubscribeVehicleData']; + } + FFW.VehicleInfo.sendVISubscribeVehicleDataResult( resultCode, message.id, message.method, subscribeVIData ); @@ -510,14 +545,6 @@ SDL.SDLVehicleInfoModel = Em.Object.create( continue; } - if (key === 'externalTemperature') { - subscribeVIData[key] = { - dataType: vehicleDataType, - resultCode: 'VEHICLE_DATA_NOT_AVAILABLE' - }; - continue; - } - SDL.SDLModel.subscribedData[key] = false; subscribeVIData[key] = { dataType: vehicleDataType, diff --git a/app/view/climateView.js b/app/view/climateView.js index 8b1ea43cd..2d9b1a8c4 100644 --- a/app/view/climateView.js +++ b/app/view/climateView.js @@ -125,6 +125,7 @@ SDL.ClimateView = Em.ContainerView.create( elementId: 'desiredTemp_minus', classNames: 'minus', templateName: 'icon', + disabledBinding: 'parentView.disabled', icon: 'images/climate/minus_ico.png', onDown: false, model: 'currentClimateModel', @@ -156,7 +157,7 @@ SDL.ClimateView = Em.ContainerView.create( elementId: 'desiredTemp_plus', classNames: 'plus', templateName: 'icon', - model: '', + disabledBinding: 'parentView.disabled', icon: 'images/climate/plus_ico.png', onDown: false, model: 'currentClimateModel', @@ -188,6 +189,7 @@ SDL.ClimateView = Em.ContainerView.create( elementId: 'fanSpeed_minus', classNames: 'minus', templateName: 'icon', + disabledBinding: 'parentView.disabled', icon: 'images/climate/minus_ico.png', onDown: false, model: 'currentClimateModel', @@ -208,6 +210,7 @@ SDL.ClimateView = Em.ContainerView.create( elementId: 'fanSpeed_plus', classNames: 'plus', templateName: 'icon', + disabledBinding: 'parentView.disabled', icon: 'images/climate/plus_ico.png', onDown: false, model: 'currentClimateModel', @@ -239,6 +242,7 @@ SDL.ClimateView = Em.ContainerView.create( elementId: 'currentTemp_minus', classNames: 'minus', templateName: 'icon', + disabledBinding: 'parentView.disabled', icon: 'images/climate/minus_ico.png', onDown: false, model: 'currentClimateModel', @@ -269,6 +273,7 @@ SDL.ClimateView = Em.ContainerView.create( elementId: 'currentTemp_plus', classNames: 'plus', templateName: 'icon', + disabledBinding: 'parentView.disabled', icon: 'images/climate/plus_ico.png', onDown: false, model: 'currentClimateModel', diff --git a/app/view/home/controlButtons.js b/app/view/home/controlButtons.js index e021b29fc..917b0105f 100644 --- a/app/view/home/controlButtons.js +++ b/app/view/home/controlButtons.js @@ -142,6 +142,7 @@ getCurrentDisplayModeClass: function() { default: return ''; } }, + /** * HMI element Select with list of supported image mode */ @@ -149,38 +150,12 @@ getCurrentDisplayModeClass: function() { elementId: 'imageMode', classNames: 'imageModeSelect', contentBinding: 'SDL.SDLModel.data.imageModeList', - selection: 'Highlighted mode', - change:function(){ - SDL.InfoAppsView.findNewApps.setMode(this.selection); - SDL.InfoAppsView.Asist911.setMode(this.selection); - SDL.InfoAppsView.vehicleHealthReport.setMode(this.selection); - SDL.InfoAppsView.getDeviceList.setMode(this.selection); - SDL.InfoView.leftMenu.items.servicesButton.setMode(this.selection); - SDL.InfoView.leftMenu.items.appsButton.setMode(this.selection); - SDL.InfoView.leftMenu.items.calendarButton.setMode(this.selection); - SDL.InfoView.leftMenu.items.goToCD.setMode(this.selection); - SDL.InfoView.leftMenu.items.travelLinkButton.setMode(this.selection); - SDL.InfoView.leftMenu.items.sdlButton.setMode(this.selection); - SDL.TurnByTurnView.nextTurnIconImage.setMode(this.selection); - SDL.TurnByTurnView.turnIconImage.setMode(this.selection); - SDL.InteractionChoicesView.set('imageMode',this.selection); - SDL.InteractionChoicesView.updateIcons(); - if (SDL.SDLController.model) { - SDL.SDLController.model.setMode(this.selection); - length=SDL.OptionsView.commands.items.length; - var commands = SDL.SDLController.model.get('currentCommandsList'); - for(var i=0;i 0) { + parentToPush.setTemplate('BUTTONS_WITH_GRAPHIC'); + } + for(var i = 0; i < length; ++i) { var softButton = SDL.Button.create(SDL.PresetEventsCustom,{ classNames: ['button', 'softButton', 'softButton_' + (i + 1)], diff --git a/app/view/info/appsView.js b/app/view/info/appsView.js index df1a5b296..d8b28ccfe 100644 --- a/app/view/info/appsView.js +++ b/app/view/info/appsView.js @@ -172,6 +172,18 @@ SDL.InfoAppsView = Em.ContainerView.create({ /** Items */ items: new Array() } -) +), + + /** + * @description Callback for display image mode change. + */ + imageModeChanged: function() { + SDL.InfoAppsView.findNewApps.setMode(SDL.SDLModel.data.imageMode); + SDL.InfoAppsView.Asist911.setMode(SDL.SDLModel.data.imageMode); + SDL.InfoAppsView.vehicleHealthReport.setMode(SDL.SDLModel.data.imageMode); + SDL.InfoAppsView.getDeviceList.setMode(SDL.SDLModel.data.imageMode); + SDL.InfoAppsView.applicationsStore.setMode(SDL.SDLModel.data.imageMode); + SDL.InfoAppsView.listOfApplications.setMode(SDL.SDLModel.data.imageMode); + }.observes('SDL.SDLModel.data.imageMode') } ); diff --git a/app/view/info/nonMediaView.js b/app/view/info/nonMediaView.js index d5c590f39..dae0151ae 100644 --- a/app/view/info/nonMediaView.js +++ b/app/view/info/nonMediaView.js @@ -167,6 +167,18 @@ SDL.InfoNonMedia = Em.ContainerView.create( ); } }.observes('SDL.SDLController.model.softButtons.@each'), + updateOptionsButton: function() { + if (SDL.SDLController.model && SDL.SDLController.model.appID == + SDL.NonMediaController.currentAppId) { + var menuTitle = SDL.SDLController.model.globalProperties.menuTitle + this.get('content.optionsButton').set('text', menuTitle && menuTitle.length ? menuTitle : 'Options') + var menuIcon = SDL.SDLController.model.globalProperties.menuIcon + this.get('content.optionsButton').set('icon', menuIcon && menuIcon.value && menuIcon.value.length ? menuIcon.value : null) + this.get('content.optionsButton').set('templateName', menuIcon && menuIcon.isTemplate ? 'arrowShortOverLay' : 'arrowShort') + } + }.observes( + 'SDL.SDLController.model.globalProperties.menuTitle', + 'SDL.SDLController.model.globalProperties.menuIcon'), groupName: 'NonMediaView', @@ -189,7 +201,8 @@ SDL.InfoNonMedia = Em.ContainerView.create( { text: 'Options', - templateName: 'arrow', + classNames: 'softButton', + templateName: 'arrowShort', action: 'openCommandsList', target: 'SDL.SDLController' diff --git a/app/view/infoView.js b/app/view/infoView.js index 69f8073d3..87b8967ee 100644 --- a/app/view/infoView.js +++ b/app/view/infoView.js @@ -176,7 +176,19 @@ SDL.InfoView = Em.ContainerView.create( icon: 'images/media/ico_cd.png', target: 'SDL.RCModulesController.currentAudioModel' } - ) + ), + + /** + * @description Callback for display image mode change. + */ + imageModeChanged: function() { + SDL.InfoView.leftMenu.items.servicesButton.setMode(SDL.SDLModel.data.imageMode); + SDL.InfoView.leftMenu.items.appsButton.setMode(SDL.SDLModel.data.imageMode); + SDL.InfoView.leftMenu.items.calendarButton.setMode(SDL.SDLModel.data.imageMode); + SDL.InfoView.leftMenu.items.goToCD.setMode(SDL.SDLModel.data.imageMode); + SDL.InfoView.leftMenu.items.travelLinkButton.setMode(SDL.SDLModel.data.imageMode); + SDL.InfoView.leftMenu.items.sdlButton.setMode(SDL.SDLModel.data.imageMode); + }.observes('SDL.SDLModel.data.imageMode') } ) } diff --git a/app/view/media/sdlmediaView.js b/app/view/media/sdlmediaView.js index 9150b6f3e..3c5cdba57 100644 --- a/app/view/media/sdlmediaView.js +++ b/app/view/media/sdlmediaView.js @@ -76,7 +76,20 @@ SDL.sdlView = Em.ContainerView SDL.SDLController.model.appID ); } - }.observes('SDL.SDLController.model.softButtons.@each'), + }.observes( + 'SDL.SDLController.model.softButtons.@each'), + updateOptionsButton: function() { + if (SDL.SDLController.model && SDL.SDLController.model.appID == + SDL.SDLMediaController.currentAppId) { + var menuTitle = SDL.SDLController.model.globalProperties.menuTitle + this.get('content.optionsButton').set('text', menuTitle && menuTitle.length ? menuTitle : 'Options') + var menuIcon = SDL.SDLController.model.globalProperties.menuIcon + this.get('content.optionsButton').set('icon', menuIcon && menuIcon.value && menuIcon.value.length ? menuIcon.value : null) + this.get('content.optionsButton').set('templateName', menuIcon && menuIcon.isTemplate ? 'arrowShortOverLay' : 'arrowShort') + } + }.observes( + 'SDL.SDLController.model.globalProperties.menuTitle', + 'SDL.SDLController.model.globalProperties.menuIcon'), groupName: 'MediaView', elementId: 'sdl_view_container_menu', content: Em.ContainerView.extend( @@ -93,7 +106,8 @@ SDL.sdlView = Em.ContainerView optionsButton: SDL.Button.extend( { text: 'Options', - templateName: 'arrow', + classNames: 'softButton', + templateName: 'arrowShort', action: 'openCommandsList', target: 'SDL.SDLController' } diff --git a/app/view/mediaView.js b/app/view/mediaView.js index 97cec9f13..60e2ceb69 100644 --- a/app/view/mediaView.js +++ b/app/view/mediaView.js @@ -42,12 +42,40 @@ SDL.MediaView = Em.ContainerView.create( 'volumeMenu', 'optionsMenu', SDL.playerView, - SDL.sdlView + 'sdlView' ], /** Left Menu view component */ leftMenu: SDL.LeftMenuView, /** Volume Menu view component */ volumeMenu: SDL.VolumeMenuView, - optionsMenu: SDL.audioView + optionsMenu: SDL.audioView, + sdlView: SDL.sdlView, + + /** + * @description Callback for display image mode change. + */ + imageModeChanged: function() { + this.leftMenu.radio.setMode(SDL.SDLModel.data.imageMode); + this.leftMenu.cdButton.setMode(SDL.SDLModel.data.imageMode); + this.leftMenu.usbButton.setMode(SDL.SDLModel.data.imageMode); + this.leftMenu.bluetoothButton.setMode(SDL.SDLModel.data.imageMode); + this.leftMenu.lineInButton.setMode(SDL.SDLModel.data.imageMode); + this.leftMenu.ipodButton.setMode(SDL.SDLModel.data.imageMode); + this.leftMenu.sdlButton.setMode(SDL.SDLModel.data.imageMode); + + this.volumeMenu.currentVolume.currentVolume_minus.setMode(SDL.SDLModel.data.imageMode); + this.volumeMenu.currentVolume.currentVolume_plus.setMode(SDL.SDLModel.data.imageMode); + + this.optionsMenu.preferencesButton.optionsButton.setMode(SDL.SDLModel.data.imageMode); + + this.sdlView.innerMenu.setMode(SDL.SDLModel.data.imageMode); + this.sdlView.controlls.Controls.PrevTrackButton.setMode(SDL.SDLModel.data.imageMode); + this.sdlView.controlls.Controls.PlayButton.setMode(SDL.SDLModel.data.imageMode); + this.sdlView.controlls.Controls.NextTrackButton.setMode(SDL.SDLModel.data.imageMode); + + this.sdlView.controlls.tuneButtons.wrapper.get('childViews').forEach( (view) => { + view.setMode(SDL.SDLModel.data.imageMode); + }); + }.observes('SDL.SDLModel.data.imageMode') } ); diff --git a/app/view/navigationApp/baseNavigationView.js b/app/view/navigationApp/baseNavigationView.js index 02212ad91..1fd3c52a4 100644 --- a/app/view/navigationApp/baseNavigationView.js +++ b/app/view/navigationApp/baseNavigationView.js @@ -131,6 +131,12 @@ SDL.BaseNavigationView = Em.ContainerView.create( } } }, + updateOptionsButton: function() { + if (SDL.SDLController.model) { + var menuTitle = SDL.SDLController.getApplicationModel(SDL.SDLController.model.appID).globalProperties.menuTitle + this.get('optionsBtn').set('text', menuTitle && menuTitle.length ? menuTitle : 'Options') + } + }.observes('SDL.SDLController.model.globalProperties.menuTitle'), mainField1: SDL.Label.extend( { classNames: 'mainField1 mainField', diff --git a/app/view/navigationView.js b/app/view/navigationView.js index 7621a621d..335ce1d4f 100644 --- a/app/view/navigationView.js +++ b/app/view/navigationView.js @@ -54,6 +54,7 @@ SDL.NavigationView = Em.ContainerView.create( itemGenerator: function() { var items = []; for (var i = 0; i < SDL.NavigationModel.LocationDetails.length; i++) { + const img = SDL.NavigationModel.LocationDetails[i].locationImage; items.push( { type: SDL.Button, @@ -62,9 +63,8 @@ SDL.NavigationView = Em.ContainerView.create( className: 'button', text: SDL.NavigationModel.LocationDetails[i].locationName, disabled: false, - icon: SDL.NavigationModel.LocationDetails[i].locationImage.value, - templateName: SDL.NavigationModel.LocationDetails[i].locationImage - ? '' : 'text', + icon: img ? img.value : '', + templateName: img && img.isTemplate ? 'textOverlay' : '', action: 'openWayPoint', target: 'SDL.NavigationController' } @@ -112,6 +112,14 @@ SDL.NavigationView = Em.ContainerView.create( action: 'setRoutes', target: 'SDL.NavigationController' } - ) + ), + + /** + * @description Callback for display image mode change. + */ + imageModeChanged: function() { + SDL.NavigationView.POIButton.setMode(SDL.SDLModel.data.imageMode); + SDL.NavigationView.navigate.setMode(SDL.SDLModel.data.imageMode); + }.observes('SDL.SDLModel.data.imageMode') } -); \ No newline at end of file +); diff --git a/app/view/sdl/AlertManeuverPopUp.js b/app/view/sdl/AlertManeuverPopUp.js index e257bbab8..a6ea13838 100644 --- a/app/view/sdl/AlertManeuverPopUp.js +++ b/app/view/sdl/AlertManeuverPopUp.js @@ -51,7 +51,15 @@ SDL.AlertManeuverPopUp = Em.ContainerView.create( content1: 'Title', content2: 'Text', activate: false, + endTime: null, timer: null, + timeout: 5000, + alertManeuerRequestId: 0, + isCloseButtonVisible: true, + /** + * @desc Defines whether icons paths verified successfully. + */ + iconsAreValid: false, /** * Wagning image on Alert Maneuver PopUp */ @@ -94,8 +102,15 @@ SDL.AlertManeuverPopUp = Em.ContainerView.create( */ softbuttons: Em.ContainerView.extend( { - elementId: 'alertManeuverSoftButtons', - classNames: 'alertManeuverSoftButtons' + childViews: [ + 'buttons' + ], + buttons: Em.ContainerView.extend( + { + elementId: 'alertManeuverSoftButtons', + classNames: 'alertManeuverSoftButtons' + } + ) } ), /** @@ -105,83 +120,151 @@ SDL.AlertManeuverPopUp = Em.ContainerView.create( { text: 'Close', classNames: 'closeButton softButton', - action: 'closeAlertMeneuverPopUp', - target: 'SDL.SDLController', + classNameBindings: [ + 'SDL.AlertManeuverPopUp.isCloseButtonVisible::inactive_state'], + actionUp: function() { + this._super(); + SDL.SDLController.closeAlertMeneuverPopUp(); + }, templateName: 'text' } ), + + /** + * @description Callback for display image mode change. + */ + imageModeChanged: function() { + var items = this.get('softbuttons.buttons.childViews'); + for (var i = 0; i < items.length; ++i) { + var button = items[i]; + button.setMode(SDL.SDLModel.data.imageMode); + } + this.closeButton.setMode(SDL.SDLModel.data.imageMode); + }.observes('SDL.SDLModel.data.imageMode'), + /** * @desc Function creates Soft Buttons on AlertPoUp * @param {Object} params */ addSoftButtons: function(params) { - if (params) { - var softButtonsClass; - switch (params.length) { - case 1: - softButtonsClass = 'one'; - break; - case 2: - softButtonsClass = 'two'; - break; - case 3: - softButtonsClass = 'three'; - break; - case 4: - softButtonsClass = 'four'; - break; + const softButtons = params.softButtons; + if (!softButtons) { + return; + } + + var softButtonsClass; + switch (softButtons.length) { + case 1: + softButtonsClass = 'one'; + break; + case 2: + softButtonsClass = 'two'; + break; + case 3: + softButtonsClass = 'three'; + break; + case 4: + softButtonsClass = 'four'; + break; + } + + let is_template = function(image) { + return image != null && image.isTemplate; + } + + let get_template_type = function(button_type, image) { + switch (button_type) { + case "IMAGE": + return is_template(image) ? "iconOverlay" : "icon"; + + case "BOTH": + return is_template(image) ? "rightTextOverLay" : "rightText"; } - for (var i = 0; i < params.length; i++) { - let get_template_type = function(button_type) { - switch (params[i].type) { - case "IMAGE": - return "icon"; - case "BOTH": - return "rightText"; - } - return "text"; - } - this.get('softbuttons.childViews').pushObject( - SDL.Button.create( - SDL.PresetEventsCustom, { - softButtonID: params[i].softButtonID, - icon: params[i].image ? params[i].image.value : '', - text: params[i].text, - classNames: 'list-item softButton ' + softButtonsClass, - elementId: 'softButton' + i, - templateName: get_template_type(params[i].type), - systemAction: params[i].systemAction, - appID: params.appID - } - ) - ); + return "text"; + } + + var imageList = []; + for (var i = 0; i < softButtons.length; i++) { + if (softButtons[i].image) { + imageList.push(softButtons[i].image.value); } + + this.get('softbuttons.buttons.childViews').pushObject( + SDL.Button.create( + SDL.PresetEventsCustom, { + softButtonID: softButtons[i].softButtonID, + icon: softButtons[i].image ? softButtons[i].image.value : '', + text: softButtons[i].text, + groupName: 'AlertManeuverPopUp', + classNames: 'list-item softButton ' + softButtonsClass, + elementId: 'softButton' + i, + classNameBindings: ['isHighlighted:isHighlighted', + 'getCurrentDisplayModeClass'], + + getCurrentDisplayModeClass: function() { + return SDL.ControlButtons.getCurrentDisplayModeClass(); + }.property('SDL.ControlButtons.imageMode.selection'), + + isHighlighted: softButtons[i].isHighlighted, + templateName: get_template_type(softButtons[i].type, softButtons[i].image), + systemAction: softButtons[i].systemAction, + appID: params.appID + } + ) + ); + } + + var callback = function(failed) { + SDL.AlertManeuverPopUp.iconsAreValid = !failed; + } + + SDL.SDLModel.validateImages(params.appID, callback, imageList); + + if (softButtons.length > 0) { + this.set('isCloseButtonVisible', false); } }, - AlertManeuverActive: function(message) { - this.get('softbuttons.childViews').removeObjects( - this.get('softbuttons.childViews').filterProperty('softButtonID') + /** + * Deactivate PopUp + */ + deactivate: function(message) { + if (SDL.TTSPopUp.active) { + SDL.TTSPopUp.DeactivateTTS(); + } + + clearTimeout(this.timer); + + const resultCode = this.iconsAreValid ? + SDL.SDLModel.data.resultCode.SUCCESS : SDL.SDLModel.data.resultCode.WARNINGS; + const info = this.iconsAreValid ? + null : "Requested image(s) not found"; + + FFW.Navigation.sendNavigationResult( + resultCode, + this.alertManeuerRequestId, + 'Navigation.AlertManeuver', + info ); + this.set('activate', false ); + this.set('alertManeuerRequestId', 0); + }, - var params = message.params; - if (params.softButtons) { - this.addSoftButtons( params.softButtons ); - } + AlertManeuverActive: function(message) { + this.softbuttons.buttons.removeAllChildren(); + this.softbuttons.buttons.rerender(); - this.set( 'activate', true ); + this.set('iconsAreValid', true); + this.set('isCloseButtonVisible', true); + this.addSoftButtons(message.params); - clearTimeout( this.timer ); + this.set('activate', true ); + this.set('alertManeuerRequestId', message.id); - var self = this; - this.timer = setTimeout( function() { - self.set( 'activate', false ); - FFW.Navigation.sendNavigationResult( - SDL.SDLModel.data.resultCode.SUCCESS, - message.id, - message.method - ); - }, 5000 ); + clearTimeout( this.timer ); + this.timer = setTimeout( () => { + this.deactivate(message); + }, this.timeout); } } ); diff --git a/app/view/sdl/AlertPopUp.js b/app/view/sdl/AlertPopUp.js index bca7928ef..9d346ced4 100644 --- a/app/view/sdl/AlertPopUp.js +++ b/app/view/sdl/AlertPopUp.js @@ -60,6 +60,7 @@ SDL.AlertPopUp = Em.ContainerView.create( active: false, timer: null, timeout: null, + endTime: null, progressIndicator: false, reason: '', message: undefined, @@ -141,6 +142,7 @@ SDL.AlertPopUp = Em.ContainerView.create( deactivate: function(reason, info) { this.set('active', false); clearTimeout(this.timer); + this.set('endTime', null); this.set('content1', ''); this.set('content2', ''); this.set('content3', ''); @@ -272,6 +274,7 @@ SDL.AlertPopUp = Em.ContainerView.create( // for // Alert // popUp + this.set('endTime', Date.now() + this.timeout); this.set('priority', priority); clearTimeout(this.timer); this.timer = setTimeout( diff --git a/app/view/sdl/SubtleAlertPopUp.js b/app/view/sdl/SubtleAlertPopUp.js new file mode 100644 index 000000000..3fdfa048d --- /dev/null +++ b/app/view/sdl/SubtleAlertPopUp.js @@ -0,0 +1,267 @@ +/* + * Copyright (c) 2020, Ford Motor Company All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * · Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * · Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * · Neither the name of the Ford Motor Company nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +/** + * @name SDL.SubtleAlertPopUp + * @desc SubtleAlertPopUp module visual representation + * @category View + * @filesource app/view/sdl/SubtleAlertPopUp.js + * @version 1.0 + */ + +SDL.SubtleAlertPopUp = Em.ContainerView.create( + { + elementId: 'SubtleAlertPopUp', + classNames: 'SubtleAlertPopUp', + classNameBindings: [ + 'active:SubtleAlertActive' + ], + childViews: [ + 'image', + 'messages', + 'softbuttons' + ], + /** + * Id of current request + * + * @type {Number} + */ + alertRequestId: null, + appID: null, + content1: '', + content2: '', + active: false, + timer: null, + timeout: null, + endTime: null, + reason: '', + message: undefined, + /** + * When SubtleAlert is clicked, open the app that sent the alert + */ + onClick: function(event) { + if (document.getElementById('SubtleAlertPopUp').contains(event.target)){ + var buttonsDiv = document.getElementById('subtleAlertSoftButtons'); + for (var button of buttonsDiv.childNodes) { + if (button.contains(event.target)) { + return; + } + } + + SDL.SubtleAlertPopUp.deactivate(); + SDL.SDLController.onActivateSDLApp({ appID: SDL.SubtleAlertPopUp.appID }); + SDL.SDLController.onSubtleAlertPressed(SDL.SubtleAlertPopUp.appID); + } else{ + SDL.SubtleAlertPopUp.deactivate(); + } + }, + /** + * Warning image on Subtle Alert PopUp + */ + image: Em.View.extend( + { + elementId: 'subtleAlertPopUpImage', + classNames: 'subtleAlertPopUpImageContainer', + template: Ember.Handlebars.compile( + '' + ) + } + ), + /** + * @function imageUndefined + * @param {Object} event + * @description action if an image is undefined. + */ + imageUndefined: function (event) { + event.target.style.display = 'none'; + this.message = "Requested image(s) not found"; + this.reason = "WARNINGS" + }, + /** + * @function imageLoaded + * @param {Object} event + * @description action if an image is loaded. + */ + imageLoaded: function (event) { + event.target.style.display = 'block'; + }, + messages: Em.ContainerView.extend( + { + childViews: [ + 'message1', + 'message2' + ], + classNames: 'messages', + message1: SDL.Label.extend( + { + elementId: 'message1', + classNames: 'message1', + contentBinding: 'parentView.parentView.content1' + } + ), + message2: SDL.Label.extend( + { + elementId: 'message2', + classNames: 'message2', + contentBinding: 'parentView.parentView.content2' + } + ) + } + ), + /** + * Deactivate PopUp + */ + deactivate: function (reason, info) { + this.set('active', false); + clearTimeout(this.timer); + this.set('endTime', null); + this.set('content1', ''); + this.set('content2', ''); + if ((reason == 'timeout' && + this.softbuttons.buttons._childViews.length > 0) || + reason === 'ABORTED') { + SDL.SDLController.subtleAlertResponse( + SDL.SDLModel.data.resultCode.ABORTED, this.alertRequestId, info + ); + } else if (reason === 'WARNINGS' || + this.reason === 'WARNINGS') { + info = info ? info : this.message; + SDL.SDLController.subtleAlertResponse( + SDL.SDLModel.data.resultCode.WARNINGS, this.alertRequestId, info + ); + } else { + SDL.SDLController.subtleAlertResponse( + SDL.SDLModel.data.resultCode.SUCCESS, this.alertRequestId, info + ); + } + window.removeEventListener('click', this.onClick); + SDL.SDLController.onSystemContextChange(); + SDL.SDLModel.data.registeredApps.forEach(app => { + app.activeWindows.forEach(widget => { + SDL.SDLController.onSystemContextChange(app.appID, widget.windowID); + }); + }); + }, + /** + * Container for softbuttons + */ + softbuttons: Em.ContainerView.extend( + { + childViews: [ + 'buttons' + ], + classNames: 'buttons', + buttons: Em.ContainerView.extend( + { + elementId: 'subtleAlertSoftButtons', + classNames: 'subtleAlertSoftButtons' + } + ) + } + ), + /** + * @desc Function creates Soft Buttons on SubtleAlertPopUp + * @param {Object} params + */ + addSoftButtons: function (params, appID) { + this.softbuttons.buttons.removeAllChildren(); + this.softbuttons.buttons.rerender(); + if (params) { + var softButtonsClass; + switch (params.length) { + case 1: + softButtonsClass = 'oneSubtle'; + break; + case 2: + softButtonsClass = 'twoSubtle'; + break; + } + for (var i = 0; i < params.length; i++) { + this.get('softbuttons.buttons.childViews') + .pushObject( + SDL.Button.create( + SDL.PresetEventsCustom, { + systemAction: params[i].systemAction, + groupName: 'SubtleAlertPopUp', + classNameBindings: ['isHighlighted:isHighlighted', + 'getCurrentDisplayModeClass'], + getCurrentDisplayModeClass: function () { + return SDL.ControlButtons.getCurrentDisplayModeClass( + SDL.ControlButtons.imageMode.selection); + }.property('SDL.ControlButtons.imageMode.selection'), + isHighlighted: params[i].isHighlighted ? true : false, + softButtonID: params[i].softButtonID, + icon: params[i].image ? params[i].image.value : '', + text: params[i].text, + classNames: 'softButton ' + softButtonsClass, + elementId: 'softButton' + i, + templateName: params[i].image ? params[i].image.isTemplate ? 'subtleOverlay' : 'subtle' : 'text', + appID: appID + } + ) + ); + } + } + }, + SubtleAlertActive: function (message, alertRequestId) { + var self = this; + this.set('alertRequestId', alertRequestId); + this.set('cancelID', message.cancelID); + this.set('reason', 'timeout'); + this.set('message', undefined); + this.addSoftButtons(message.softButtons, message.appID); + this.set('appID', message.appID); + this.set('icon', message.alertIcon ? message.alertIcon.value : "images/sdl/Warning.png"); + for (var i = 0; i < message.alertStrings.length; i++) { + switch (message.alertStrings[i].fieldName) { + case 'subtleAlertText1': + { + this.set('content1', message.alertStrings[i].fieldText); + break; + } + case 'subtleAlertText2': + { + this.set('content2', message.alertStrings[i].fieldText); + break; + } + } + } + this.set('active', true); + this.set('timeout', message.duration ? message.duration : 10000); + this.set('endTime', Date.now() + this.timeout); + clearTimeout(this.timer); + this.timer = setTimeout( + function () { + self.deactivate(self.reason, self.message); + }, this.timeout + ); + window.addEventListener('click', this.onClick); + } + } +); diff --git a/app/view/sdl/VRPopUp.js b/app/view/sdl/VRPopUp.js index 79132161b..62dd9f537 100644 --- a/app/view/sdl/VRPopUp.js +++ b/app/view/sdl/VRPopUp.js @@ -69,12 +69,14 @@ SDL.VRPopUp = Em.ContainerView.create( AddCommand: function(cmdID, vrCommands, appID, type, grammarID) { if (type == 'Application') { for (var i = 0; i < vrCommands.length; i++) { + var isExit = cmdID === -2 && vrCommands[i].startsWith('USER_EXIT '); this.get('listOfCommands.list.childViews').pushObject( SDL.Button.create( { - action: 'onActivateSDLApp', + action: isExit ? 'onVRCommand' : 'onActivateSDLApp', target: 'SDL.SDLController', appID: appID, + commandID: cmdID, text: vrCommands[i], classNames: 'list-item', templateName: 'text' diff --git a/app/view/sdl/addWidgetPopUp.js b/app/view/sdl/addWidgetPopUp.js index a728a04a4..c5e242ead 100644 --- a/app/view/sdl/addWidgetPopUp.js +++ b/app/view/sdl/addWidgetPopUp.js @@ -104,6 +104,7 @@ SDL.AddWidgetPopUp = Em.ContainerView.create( toggleActivity: function() { this.toggleProperty('active'); this.updateWidgetList(); + SDL.SDLController.setWebEngineFramesActive(!this.active); } } ); diff --git a/app/view/sdl/shared/interactionChoicesView.js b/app/view/sdl/shared/interactionChoicesView.js index fc94b0546..d54f6bc2b 100644 --- a/app/view/sdl/shared/interactionChoicesView.js +++ b/app/view/sdl/shared/interactionChoicesView.js @@ -139,6 +139,7 @@ SDL.InteractionChoicesView = SDL.SDLAbstractView.create( ), timer: null, timeout: null, + endTime: null, search: false, list: false, icon: false, @@ -260,6 +261,7 @@ SDL.InteractionChoicesView = SDL.SDLAbstractView.create( this.timerUpdate(); } else { clearTimeout(this.timer); + this.set('endTime', null); this.timer = null; this.set('active', false); SDL.SDLController.VRMove(); @@ -355,6 +357,7 @@ SDL.InteractionChoicesView = SDL.SDLAbstractView.create( this.listOfChoices.list.refresh(); } var self = this; + this.set('endTime', Date.now() + timeout); clearTimeout(this.timer); this.timer = setTimeout( function() { @@ -412,6 +415,14 @@ SDL.InteractionChoicesView = SDL.SDLAbstractView.create( self.deactivate('TIMED_OUT'); }, timeout ); - } + }, + + /** + * @description Callback for display image mode change. + */ + imageModeChanged: function() { + SDL.InteractionChoicesView.set('imageMode',SDL.SDLModel.data.imageMode); + SDL.InteractionChoicesView.updateIcons(); + }.observes('SDL.SDLModel.data.imageMode') } ); diff --git a/app/view/sdl/shared/keyboard.js b/app/view/sdl/shared/keyboard.js index b10620b1e..a3dceb81f 100644 --- a/app/view/sdl/shared/keyboard.js +++ b/app/view/sdl/shared/keyboard.js @@ -79,7 +79,7 @@ SDL.Keyboard = SDL.SDLAbstractView.create( */ deactivate: function() { this._super(); - this.searchBar.input.set('value', null); + this.searchBar.input.set('value', ''); this.set('target', null); }, inputChanges: function(element) { diff --git a/app/view/sdl/shared/optionsView.js b/app/view/sdl/shared/optionsView.js index 885e49bef..71f11a77d 100644 --- a/app/view/sdl/shared/optionsView.js +++ b/app/view/sdl/shared/optionsView.js @@ -56,9 +56,23 @@ SDL.OptionsView = SDL.SDLAbstractView.create( // Extend deactivate window deactivate: function() { if (SDL.SDLController.model) { - if (SDL.SDLController.model.get('currentSubMenuId') >= 0 && - !SDL.SDLController.model.get('subMenuInitFromApp')) { - SDL.SDLController.onSubMenu('top'); + var currentSubMenuID = SDL.SDLController.model.get('currentSubMenuId'); + if (currentSubMenuID != 'top' && + currentSubMenuID >= 0 && + !SDL.SDLController.model.get('subMenuInitFromApp')) { + var commandsList = SDL.SDLController.model.get('commandsList'); + var findParentID = (commands, menuID) => { + for (id in commands) { + var subMenuCommands = commands[id]; + for (element of subMenuCommands) { + if (element.menuID === menuID) { + return element.parent; + } + } + } + return 'top'; + } + SDL.SDLController.onSubMenu(findParentID(commandsList, currentSubMenuID)); } else { SDL.SDLController.onSubMenu('top'); this._super(); @@ -90,19 +104,30 @@ SDL.OptionsView = SDL.SDLAbstractView.create( refreshItems: function() { if (SDL.SDLController.model) { var commands = SDL.SDLController.model.get('currentCommandsList'), + allMenuItems = SDL.SDLController.model.get('commandsList'), i, len, template; this.items = []; - len = commands.length; + if (SDL.SDLModel.data.driverDistractionState) { + var ddMaxLength = SDL.systemCapabilities.driverDistractionCapability.menuLength; + len = (ddMaxLength > commands.length) ? commands.length : ddMaxLength; + } else { + len = commands.length; + } for (i = 0; i < len; i++) { - if (commands[i].menuID >= 0) { + var menuID = commands[i].menuID; + if (menuID && menuID >= 0) { + if (allMenuItems[menuID].length === 0) { + // Notify mobile to update submenu + FFW.UI.OnUpdateSubMenu(SDL.SDLController.model.appID, menuID); + } template = 'arrow'; - }else if(commands[i].isTemplate){ + } else if (commands[i].isTemplate){ template = commands[i].isTemplate ? 'rightTextOverLay' : 'rightText'; - }else { + } else { template = commands[i].icon ? 'rightText' : 'text'; } this.items.push( @@ -112,7 +137,7 @@ SDL.OptionsView = SDL.SDLAbstractView.create( templateName: template, text: commands[i].name, commandID: commands[i].commandID, - menuID: commands[i].menuID, + menuID: menuID, icon: commands[i].icon, target: 'SDL.SDLController', action: 'onCommand', @@ -121,11 +146,23 @@ SDL.OptionsView = SDL.SDLAbstractView.create( } ); } + if (commands.length !== len) { + this.items.push( + { + type: SDL.Button, + params: { + templateName: "text", + text: "Some Menu Items Are Hidden", + onDown: false, + disabled: true + } + } + ); + } this.list.refresh(); } }.observes( - 'SDL.SDLController.model.currentSubMenuId', - 'SDL.SDLController.model.currentCommandsList.@each' + 'SDL.SDLController.model.currentSubMenuId' ) } ) diff --git a/app/view/sdl/shared/scrollableMessage.js b/app/view/sdl/shared/scrollableMessage.js index 8dab10199..557e4587c 100644 --- a/app/view/sdl/shared/scrollableMessage.js +++ b/app/view/sdl/shared/scrollableMessage.js @@ -49,6 +49,8 @@ SDL.ScrollableMessage = SDL.SDLAbstractView.create( appID: null, timer: null, timeout: null, + endTime: null, + areAllImagesValid: true, childViews: [ 'backButton', 'captionText', 'softButtons', 'listOfCommands' ], @@ -60,12 +62,25 @@ SDL.ScrollableMessage = SDL.SDLAbstractView.create( */ deactivate: function(ABORTED) { clearTimeout(this.timer); + this.set('endTime', null); this.set('active', false); this.softButtons.set('page', 0); this.timeout = null; + + let calculate_result_code = function(areAllImagesValid) { + if (ABORTED) { + return SDL.SDLModel.data.resultCode.ABORTED; + } + + if (!areAllImagesValid) { + return SDL.SDLModel.data.resultCode.WARNINGS; + } + + return SDL.SDLModel.data.resultCode.SUCCESS; + }; + SDL.SDLController.scrollableMessageResponse( - ABORTED ? SDL.SDLModel.data.resultCode['ABORTED'] : - SDL.SDLModel.data.resultCode.SUCCESS, this.messageRequestId + calculate_result_code(this.areAllImagesValid), this.messageRequestId ); SDL.SDLController.onSystemContextChange(); SDL.SDLModel.data.registeredApps.forEach(app => { @@ -74,24 +89,43 @@ SDL.ScrollableMessage = SDL.SDLAbstractView.create( }) }) }, + activate: function(appName, params, messageRequestId) { if (appName) { var self = this; if (params.messageText.fieldName == 'scrollableMessageBody') { this.set('listOfCommands.items', params.messageText.fieldText); } + this.set('messageRequestId', messageRequestId); + this.set('areAllImagesValid', true); this.set('captionText.content', appName); this.softButtons.addItems(params.softButtons, params.appID); this.set('active', true); this.set('cancelID', params.cancelID); clearTimeout(this.timer); this.timeout = params.timeout; + this.set('endTime', Date.now() + this.timeout); this.timer = setTimeout( function() { self.deactivate(); }, params.timeout ); + + if(params.softButtons) { + var imageList = []; + for(var i = 0; i < params.softButtons.length; i++) { + if(params.softButtons[i].image) { + imageList.push(params.softButtons[i].image.value); + } + } + var that = this; + var callback = function(failed) { + that.set('areAllImagesValid', !failed); + }; + + SDL.SDLModel.validateImages(messageRequestId, callback, imageList); + } } }, softButtons: SDL.MenuList.extend( diff --git a/app/view/sdl/shared/turnByTurnView.js b/app/view/sdl/shared/turnByTurnView.js index 26fea3415..dfd30567d 100644 --- a/app/view/sdl/shared/turnByTurnView.js +++ b/app/view/sdl/shared/turnByTurnView.js @@ -196,7 +196,7 @@ SDL.TurnByTurnView = SDL.SDLAbstractView.create( if (this._parentView != null && this._parentView.turnIcon) { return this._parentView.turnIcon; } else { - return ''; + return null; } }.property('this.parentView.turnIcon') } @@ -213,7 +213,7 @@ SDL.TurnByTurnView = SDL.SDLAbstractView.create( if (null!=this._parentView && this._parentView.nextTurnIcon) { return this._parentView.nextTurnIcon; } else { - return ''; + return null; } }.property('this.parentView.nextTurnIcon') } @@ -247,6 +247,14 @@ SDL.TurnByTurnView = SDL.SDLAbstractView.create( } ) } - ) + ), + + /** + * @description Callback for display image mode change. + */ + imageModeChanged: function() { + SDL.TurnByTurnView.nextTurnIconImage.setMode(SDL.SDLModel.data.imageMode); + SDL.TurnByTurnView.turnIconImage.setMode(SDL.SDLModel.data.imageMode); + }.observes('SDL.SDLModel.data.imageMode') } ); diff --git a/app/view/settings/RPCControlView.js b/app/view/settings/RPCControlView.js new file mode 100644 index 000000000..921e98904 --- /dev/null +++ b/app/view/settings/RPCControlView.js @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2020, Ford Motor Company All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: · + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. · Redistributions in binary + * form must reproduce the above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or other materials provided + * with the distribution. · Neither the name of the Ford Motor Company nor the + * names of its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +SDL.RPCControlView = Em.ContainerView.create( + { + elementId: 'rpc_settings', + classNames: 'in_settings_view', + classNameBindings: [ + 'SDL.States.settings.rpccontrol.active:active_state:inactive_state' + ], + childViews: [ + 'AppsList' + ], + showAppList: function() { + this.get('AppsList.list').removeAllChildren(); + this.AppsList.list.refresh(); + var i, apps = SDL.SDLModel.data.registeredApps, appIndex; + if (0 == apps.length && SDL.States.currentState.name == 'rpccontrol') { + SDL.States.goToStates('settings.policies'); + } + + this.get('AppsList.list.childViews').pushObject(SDL.Button.create( + { + action: 'onState', + target: 'SDL.SettingsController', + goToState:'rpccontrol.rpcwaypointconfig', + text: 'Subscribe Way Points', + classNames: 'list-item button' + })); + this.get('AppsList.list.childViews').pushObject(SDL.Button.create( + { + action: 'onState', + target: 'SDL.SettingsController', + goToState:'rpccontrol.rpcvehicledataconfig', + text: 'Vehicle Data', + classNames: 'list-item button' + })); + this.get('AppsList.list.childViews').pushObject(SDL.Button.create( + { + action: 'onState', + target: 'SDL.SettingsController', + goToState:'rpccontrol.rpcgetivdconfig', + text: 'Get Interior Vehicle Data', + classNames: 'list-item button' + })); + + for (i = 0; i < apps.length; i++) { + appIndex = SDL.SDLModel.data.registeredApps.indexOf(apps[i]); + this.get('AppsList.list.childViews').pushObject(SDL.Button.create( + { + action: 'onState', + target: 'SDL.SettingsController', + goToState:'rpccontrol.rpcconfig', + text: apps[i].appName, + appName: apps[i].appName, + appID: apps[i].appID, + classNames: 'list-item button', + iconBinding: 'SDL.SDLModel.data.registeredApps.' + appIndex + + '.appIcon', + disabled: apps[i].disabledToActivate, + templateName: 'rightText' + })); + } + }, + + AppsList: SDL.List.extend({ + elementId: 'rpc_settings_list', + classNames: 'rpc_settings_list', + itemsOnPage: 5, + items: new Array() + }) + } +); diff --git a/app/view/settings/RPCControls/RPCControlConfigView.js b/app/view/settings/RPCControls/RPCControlConfigView.js new file mode 100644 index 000000000..a8a2c254e --- /dev/null +++ b/app/view/settings/RPCControls/RPCControlConfigView.js @@ -0,0 +1,221 @@ +/* + * Copyright (c) 2020, Ford Motor Company All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: · + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. · Redistributions in binary + * form must reproduce the above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or other materials provided + * with the distribution. · Neither the name of the Ford Motor Company nor the + * names of its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +SDL.RPCControlConfigView = Em.ContainerView.create( + { + elementId: 'rpc_settings_deviceConfig', + classNames: 'rpc_settings_separate_view', + classNameBindings: [ + 'SDL.States.settings.rpccontrol.rpcconfig.active:active_state:inactive_state' + ], + childViews: [ + 'backButton', + 'rpcList', + 'resultCodeTracker', + 'saveButton', + 'resetButton', + 'appNameLabel' + ], + appNameLabel: SDL.Label.extend( + { + elementId: 'appNameLabel', + classNames: 'appNameLabel' + } + ), + resetButton: SDL.Button.extend( + { + classNames: [ + 'resetButton' + ], + action: 'resetButton', + target: 'FFW.RPCHelper', + goToState: 'rpccontrol', + text:'Reset to default', + onDown: false + } + ), + saveButton: SDL.Button.extend( + { + classNames: [ + 'saveButton' + ], + action: 'saveButton', + target: 'FFW.RPCHelper', + goToState: 'rpccontrol', + text:'Save', + onDown: false + } + ), + backButton: SDL.Button.extend( + { + classNames: [ + 'backControl' + ], + action: 'onState', + target: 'SDL.SettingsController', + goToState: 'rpccontrol', + icon: 'images/media/ico_back.png', + style: 'top: 100px', + onDown: false + } + ), + rpcList: Em.ContainerView.extend( + { + elementId: 'rpcList', + classNames: 'rpcList', + childViews: [ + 'vrAddComandlabel', + 'uiAddComandlabel', + 'addSubMenulabel', + 'createInteractionChoiceSetlabel', + 'uisetGlobalPropertieslabel', + 'ttssetGlobalPropertieslabel', + 'uiCreateWindowLabel' + ], + vrAddComandlabel: SDL.Label.extend( + { + elementId: 'addComandlabel', + classNames: 'vrAddComandlabel', + content: 'VR.AddCommand' + } + ), + uiAddComandlabel: SDL.Label.extend( + { + elementId: 'addComandlabel', + classNames: 'uiAddComandlabel', + content: 'UI.AddCommand' + } + ), + addSubMenulabel: SDL.Label.extend( + { + elementId: 'addSubMenulabel', + classNames: 'addSubMenulabel', + content: 'AddSubMenu' + } + ), + createInteractionChoiceSetlabel: SDL.Label.extend( + { + elementId: 'createInteractionChoiceSetlabel', + classNames: 'createInteractionChoiceSetlabel', + content: 'CreateInteractionChoiceSet' + } + ), + uisetGlobalPropertieslabel: SDL.Label.extend( + { + elementId: 'uisetGlobalProperties', + classNames: 'uisetGlobalProperties', + content: 'UI.SetGlobalProperties' + } + ), + ttssetGlobalPropertieslabel: SDL.Label.extend( + { + elementId: 'ttssetGlobalPropertieslabel', + classNames: 'ttssetGlobalPropertieslabel', + content: 'TTS.SetGlobalProperties' + } + ), + uiCreateWindowLabel: SDL.Label.extend( + { + elementId: 'uiCreateWindowLabel', + classNames: 'uiCreateWindowLabel', + content: 'UI.CreateWindow' + } + ) + } + ), + resultCodeTracker: Em.ContainerView.extend( + { + elementId: 'resultCodeTracker', + classNames: 'resultCodeTracker', + childViews: [ + 'vrAddComandSelect', + 'uiAddComandSelect', + 'addSubMenuSelect', + 'createInteractionChoiceSetSelect', + 'uisetGlobalPropertiesSelect', + 'ttssetGlobalPropertiesSelect', + 'uiCreateWindowSelect' + ], + vrAddComandSelect: Em.Select.extend( + { + elementId: 'vrAddComandSelect', + classNames: 'vrAddComandSelect', + contentBinding: 'FFW.RPCHelper.customResultCodesList', + valueBinding: 'FFW.RPCHelper.rpcStruct.vrAddCommand' + } + ), + uiAddComandSelect: Em.Select.extend( + { + elementId: 'uiAddComandSelect', + classNames: 'uiAddComandSelect', + contentBinding: 'FFW.RPCHelper.customResultCodesList', + valueBinding: 'FFW.RPCHelper.rpcStruct.uiAddCommand' + } + ), + addSubMenuSelect: Em.Select.extend( + { + elementId: 'addSubMenuSelect', + classNames: 'addSubMenuSelect', + contentBinding: 'FFW.RPCHelper.customResultCodesList', + valueBinding: 'FFW.RPCHelper.rpcStruct.AddSubmenu' + } + ), + createInteractionChoiceSetSelect: Em.Select.extend( + { + elementId: 'createInteractionChoiceSetSelect', + classNames: 'createInteractionChoiceSetSelect', + contentBinding: 'FFW.RPCHelper.customResultCodesList', + valueBinding: 'FFW.RPCHelper.rpcStruct.createInteractionChoiceSet' + } + ), + uisetGlobalPropertiesSelect: Em.Select.extend( + { + elementId: 'uisetGlobalPropertiesSelect', + classNames: 'uisetGlobalPropertiesSelect', + contentBinding: 'FFW.RPCHelper.customResultCodesList', + valueBinding: 'FFW.RPCHelper.rpcStruct.uiSetGlobalProperties' + } + ), + ttssetGlobalPropertiesSelect: Em.Select.extend( + { + elementId: 'ttssetGlobalPropertiesSelect', + classNames: 'ttssetGlobalPropertiesSelect', + contentBinding: 'FFW.RPCHelper.customResultCodesList', + valueBinding: 'FFW.RPCHelper.rpcStruct.ttsSetGlobalProperties' + } + ), + uiCreateWindowSelect: Em.Select.extend( + { + elementId: 'uiCreateWindowSelect', + classNames: 'uiCreateWindowSelect', + contentBinding: 'FFW.RPCHelper.customResultCodesList', + valueBinding: 'FFW.RPCHelper.rpcStruct.uiCreateWindow' + } + ), + } + ) + } +); diff --git a/app/view/settings/RPCControls/RPCGetIVDControlConfigView.js b/app/view/settings/RPCControls/RPCGetIVDControlConfigView.js new file mode 100644 index 000000000..7b4e054f4 --- /dev/null +++ b/app/view/settings/RPCControls/RPCGetIVDControlConfigView.js @@ -0,0 +1,169 @@ +/* + * Copyright (c) 2020, Ford Motor Company All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: · + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. · Redistributions in binary + * form must reproduce the above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or other materials provided + * with the distribution. · Neither the name of the Ford Motor Company nor the + * names of its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +SDL.RPCGetIVDControlConfigView = Em.ContainerView.create({ + elementId: 'rpc_get_ivd_config', + classNames: 'rpc_settings_separate_view', + classNameBindings: [ + 'SDL.States.settings.rpccontrol.rpcgetivdconfig.active:active_state:inactive_state' + ], + + childViews: [ + 'backButton', + 'newButton', + 'removeButton', + 'previousButton', + 'nextButton', + 'counterLabel', + 'customResultCodeLabel', + 'getIVDSelect', + 'subscribedLabel', + 'getIVDSubscribed' + ], + + backButton: SDL.Button.extend( + { + classNames: [ + 'backControl' + ], + action: 'onState', + target: 'SDL.SettingsController', + goToState: 'rpccontrol', + icon: 'images/media/ico_back.png', + style: 'top: 100px', + onDown: false + } + ), + + newButton: SDL.Button.extend( + { + classNames: [ + 'newButton' + ], + action: 'newGetIVDResponse', + target: 'FFW.RPCHelper', + text: 'New', + onDown: false + } + ), + + removeButton: SDL.Button.extend( + { + classNames: [ + 'removeButton' + ], + isDisabled: function() { + return FFW.RPCHelper.getIVDResultStruct.length == 1; + }.property( + 'FFW.RPCHelper.getIVDRequestNumber' + ), + disabledBinding: 'isDisabled', + action: 'removeGetIVDResponse', + target: 'FFW.RPCHelper', + text: 'Remove', + onDown: false + } + ), + + previousButton: SDL.Button.extend( + { + classNames: [ + 'previousButton' + ], + isDisabled: function() { + return FFW.RPCHelper.getIVDRequestNumber == 1; + }.property( + 'FFW.RPCHelper.getIVDRequestNumber' + ), + disabledBinding: 'isDisabled', + action: 'previousGetIVDResultCode', + target: 'FFW.RPCHelper', + text: 'Previous', + onDown: false + } + ), + + nextButton: SDL.Button.extend( + { + classNames: [ + 'nextButton' + ], + isDisabled: function() { + return FFW.RPCHelper.getIVDRequestNumber == + FFW.RPCHelper.getIVDResultStruct.length; + }.property( + 'FFW.RPCHelper.getIVDRequestNumber' + ), + disabledBinding: 'isDisabled', + action: 'nextGetIVDResultCode', + target: 'FFW.RPCHelper', + text: 'Next', + onDown: false + } + ), + + counterLabel: SDL.Label.extend( + { + elementId: 'counterLabel', + classNames: 'counterLabel', + contentBinding: 'FFW.RPCHelper.getIVDResponseStatus' + } + ), + + customResultCodeLabel: SDL.Label.extend( + { + elementId: 'customResultCodeLabel', + classNames: 'customResultCodeLabel', + content: 'Custom result code:' + } + ), + + getIVDSelect: Em.Select.extend( + { + elementId: 'getIVDSelect', + classNames: 'getIVDSelect', + contentBinding: 'FFW.RPCHelper.customResultCodesList', + valueBinding: 'FFW.RPCHelper.getIVDResult' + } + ), + + subscribedLabel: SDL.Label.extend( + { + elementId: 'subscribedLabel', + classNames: 'subscribedLabel', + content: 'isSubscribed emulation:' + } + ), + + getIVDSubscribed: Em.Select.extend( + { + elementId: 'getIVDSubscribed', + classNames: 'getIVDSubscribed', + contentBinding: 'FFW.RPCHelper.subscribeDataValues', + valueBinding: 'FFW.RPCHelper.getIVDSubscribed' + } + ) +}); diff --git a/app/view/settings/RPCControls/RPCVehicleDataControlConfigView.js b/app/view/settings/RPCControls/RPCVehicleDataControlConfigView.js new file mode 100644 index 000000000..0e4f7f91b --- /dev/null +++ b/app/view/settings/RPCControls/RPCVehicleDataControlConfigView.js @@ -0,0 +1,184 @@ +/* + * Copyright (c) 2020, Ford Motor Company All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: · + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. · Redistributions in binary + * form must reproduce the above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or other materials provided + * with the distribution. · Neither the name of the Ford Motor Company nor the + * names of its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +SDL.RPCVehicleDataControlConfigView = Em.ContainerView.create({ + elementId: 'rpc_vehicle_data_Config', + classNames: 'rpc_settings_separate_view', + classNameBindings: [ + 'SDL.States.settings.rpccontrol.rpcvehicledataconfig.active:active_state:inactive_state' + ], + + childViews: [ + 'backButton', + 'newButton', + 'removeButton', + 'previousButton', + 'nextButton', + 'counterLabel', + 'subscribevehicleData', + 'subscribevehicleDataParams' + ], + backButton: SDL.Button.extend( + { + classNames: [ + 'backControl' + ], + action: 'onState', + target: 'SDL.SettingsController', + goToState: 'rpccontrol', + icon: 'images/media/ico_back.png', + style: 'top: 100px', + onDown: false + }), + newButton: SDL.Button.extend( + { + classNames: [ + 'newButton' + ], + action: 'newVehicleDataResponse', + target: 'FFW.RPCHelper', + text: 'New', + onDown: false + }), + removeButton: SDL.Button.extend( + { + classNames: [ + 'removeButton' + ], + isDisabled: function() { + return FFW.RPCHelper.VehicleDataResultCodes.length == 1; + }.property( + 'FFW.RPCHelper.VehicleDataRequestNumber' + + ), + disabledBinding: 'isDisabled', + action: 'removeVehicleDataResponse', + target: 'FFW.RPCHelper', + text: 'Remove', + onDown: false + }), + previousButton: SDL.Button.extend( + { + classNames: [ + 'previousButton' + ], + isDisabled: function() { + return FFW.RPCHelper.VehicleDataRequestNumber == 1; + }.property( + 'FFW.RPCHelper.VehicleDataRequestNumber' + ), + disabledBinding: 'isDisabled', + action: 'previousVehicleDataResultCode', + target: 'FFW.RPCHelper', + text: 'Previous', + onDown: false + }), + nextButton: SDL.Button.extend( + { + classNames: [ + 'nextButton' + ], + isDisabled: function() { + return FFW.RPCHelper.VehicleDataRequestNumber == + FFW.RPCHelper.VehicleDataResultCodes.length; + }.property( + 'FFW.RPCHelper.VehicleDataRequestNumber' + ), + disabledBinding: 'isDisabled', + action: 'nextVehicleDataResultCode', + target: 'FFW.RPCHelper', + text: 'Next', + onDown: false + }), + counterLabel: SDL.Label.extend( + { + elementId: 'counterLabel', + classNames: 'counterLabel', + contentBinding: 'FFW.RPCHelper.getVehicleDataStatus' + }), + subscribevehicleData: Em.ContainerView.create( + { + elementId: 'subscribevehicleData', + classNames: 'subscribevehicleData', + childViews: [ + 'label', + 'select' + ], + label: SDL.Label.extend( + { + elementId: 'label', + classNames: 'label', + content: 'SubscribeVehicleData' + }), + select: Em.Select.extend( + { + elementId: 'SubscribevehicleDataSelect', + classNames: 'select', + contentBinding: 'FFW.RPCHelper.customResultCodesList', + valueBinding: 'FFW.RPCHelper.SubscribeVehicleData' + }), + }), + subscribevehicleDataParams: Em.ContainerView.create( + { + elementId: 'subscribevehicleDataParams', + classNames: 'subscribevehicleDataParams', + childViews: [] + }), + isFirstInitialization: true, + initSubscribevehicleDataParams: function(){ + if(!this.isFirstInitialization){ + return; + } + this.isFirstInitialization = false; + + for(var viewsName in FFW.RPCHelper.vehicleDataStruct){ + selectValueBinding = 'FFW.RPCHelper.vehicleDataStruct.' + viewsName; + this.get('subscribevehicleDataParams.childViews').pushObject(Em.ContainerView.create({ + elementId: viewsName, + classNames: 'params', + childViews: [ + 'label', + 'select' + ], + + label: SDL.Label.extend( + { + elementId: 'label', + classNames: 'label', + content: viewsName + }), + select: Em.Select.extend( + { + elementId: viewsName + 'Select', + classNames: 'select', + contentBinding: 'FFW.RPCHelper.customResultCodesList', + valueBinding: selectValueBinding + }), + })); + + } + } +}); diff --git a/app/view/settings/RPCControls/RPCWayPointControlConfigView.js b/app/view/settings/RPCControls/RPCWayPointControlConfigView.js new file mode 100644 index 000000000..ae09e0498 --- /dev/null +++ b/app/view/settings/RPCControls/RPCWayPointControlConfigView.js @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2020, Ford Motor Company All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: · + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. · Redistributions in binary + * form must reproduce the above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or other materials provided + * with the distribution. · Neither the name of the Ford Motor Company nor the + * names of its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +SDL.RPCWayPointControlConfigView = Em.ContainerView.create({ + elementId: 'rpc_way_points_Config', + classNames: 'rpc_settings_separate_view', + classNameBindings: [ + 'SDL.States.settings.rpccontrol.rpcwaypointconfig.active:active_state:inactive_state' + ], + + childViews: [ + 'backButton', + 'newButton', + 'removeButton', + 'previousButton', + 'nextButton', + 'counterLabel', + 'subscribeWayPointsSelect' + ], + backButton: SDL.Button.extend( + { + classNames: [ + 'backControl' + ], + action: 'onState', + target: 'SDL.SettingsController', + goToState: 'rpccontrol', + icon: 'images/media/ico_back.png', + style: 'top: 100px', + onDown: false + } + ), + newButton: SDL.Button.extend( + { + classNames: [ + 'newButton' + ], + action: 'newWayPointResponse', + target: 'FFW.RPCHelper', + text: 'New', + onDown: false + } + ), + removeButton: SDL.Button.extend( + { + classNames: [ + 'removeButton' + ], + isDisabled: function() { + return FFW.RPCHelper.wayPointResultCodes.length == 1; + }.property( + 'FFW.RPCHelper.SubscribeWayPointsRequestNumber' + + ), + disabledBinding: 'isDisabled', + action: 'removeWayPointResponse', + target: 'FFW.RPCHelper', + text: 'Remove', + onDown: false + } + ), + previousButton: SDL.Button.extend( + { + classNames: [ + 'previousButton' + ], + isDisabled: function() { + return FFW.RPCHelper.SubscribeWayPointsRequestNumber == 1; + }.property( + 'FFW.RPCHelper.SubscribeWayPointsRequestNumber' + ), + disabledBinding: 'isDisabled', + action: 'previousWayPointResultCode', + target: 'FFW.RPCHelper', + text: 'Previous', + onDown: false + } + ), + nextButton: SDL.Button.extend( + { + classNames: [ + 'nextButton' + ], + isDisabled: function() { + return FFW.RPCHelper.SubscribeWayPointsRequestNumber == + FFW.RPCHelper.wayPointResultCodes.length; + }.property( + 'FFW.RPCHelper.SubscribeWayPointsRequestNumber' + ), + disabledBinding: 'isDisabled', + action: 'nextWayPointResultCode', + target: 'FFW.RPCHelper', + text: 'Next', + onDown: false + } + ), + counterLabel: SDL.Label.extend( + { + elementId: 'counterLabel', + classNames: 'counterLabel', + contentBinding: 'FFW.RPCHelper.getWayPointResponseStatus' + } + ), + subscribeWayPointsSelect: Em.Select.extend( + { + elementId: 'subscribeWayPointsSelect', + classNames: 'subscribeWayPointsSelect', + contentBinding: 'FFW.RPCHelper.customResultCodesList', + valueBinding: 'FFW.RPCHelper.SubscribeWayPoints' + } + ), +}); diff --git a/app/view/settings/SeatView.js b/app/view/settings/SeatView.js index ed1cd87ae..5329a8868 100644 --- a/app/view/settings/SeatView.js +++ b/app/view/settings/SeatView.js @@ -963,10 +963,23 @@ SDL.SeatView = Em.ContainerView.create({ content: 'ID' }), - seatModuleUUID: SDL.Label.create({ + seatModuleUUID: Em.Select.create({ elementId: 'seatModelCurrent', classNames: 'seatModelCurrent', - contentBinding: 'SDL.RCModulesController.currentSeatModuleID' + change: function() { + var desiredUUID = this.selection; + var location_name = ''; + for(var key in SDL.RCModulesController.seatModels) { + if(desiredUUID === SDL.RCModulesController.seatModels[key].UUID) { + location_name = SDL.RCModulesController.seatModels[key].ID; + break; + } + } + if(location_name != '') { + SDL.RCModulesController.set('currentSeatModel', SDL.RCModulesController.getCoveringModuleModel('SEAT', location_name)); + SDL.RCModulesController.currentSeatModel.updateView(); + } + } }) }), diff --git a/app/view/settings/policies/appPermissionsView.js b/app/view/settings/policies/appPermissionsView.js index c45daa3c7..828625831 100644 --- a/app/view/settings/policies/appPermissionsView.js +++ b/app/view/settings/policies/appPermissionsView.js @@ -73,12 +73,14 @@ SDL.AppPermissionsView = Em.ContainerView.create( } ); } - FFW.BasicCommunication.OnAppPermissionConsent( - permissions, null, 'GUI', SDL.AppPermissionsView.currentAppId - ); + if (permissions.length > 0) { + FFW.BasicCommunication.OnAppPermissionConsent( + permissions, null, 'GUI', SDL.AppPermissionsView.currentAppId + ); + } SDL.AppPermissionsView.currentAppId = null; }, - goToState: 'policies', + goToState: 'policies.appPermissionsList', icon: 'images/media/ico_back.png', onDown: false } @@ -90,6 +92,9 @@ SDL.AppPermissionsView = Em.ContainerView.create( SDL.AppPermissionsView.currentAppId = appID; this.appList.items = []; for (var i = 0; i < message.length; i++) { + if (!message[i].name) { + continue; + } var text = ' - Undefined'; text = (message[i].allowed === true) ? ' - Allowed' : ' - Not allowed'; this.appList.items.push({ diff --git a/app/view/settings/policies/ccpuEditorView.js b/app/view/settings/policies/ccpuEditorView.js new file mode 100644 index 000000000..bd5c8f5c7 --- /dev/null +++ b/app/view/settings/policies/ccpuEditorView.js @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2020, Ford Motor Company All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: · + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. · Redistributions in binary + * form must reproduce the above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or other materials provided + * with the distribution. · Neither the name of the Ford Motor Company nor the + * names of its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +SDL.CcpuEditorView = Em.ContainerView.create( + { + elementId: 'policies_settings_ccpu_editor_view', + classNames: 'in_settings_separate_view', + classNameBindings: [ + 'SDL.States.settings.policies.ccpuEditor.active:active_state:inactive_state' + ], + childViews: [ + 'ccpuTitle', + 'backButton', + 'ccpuVersionLabel', + 'ccpuVersionInput', + 'applyButton' + ], + ccpuTitle: SDL.Label.extend( + { + classNames: 'label', + content: 'Configure CCPU version' + } + ), + backButton: SDL.Button.extend( + { + classNames: [ + 'backButton' + ], + action: 'onState', + target: 'SDL.SettingsController', + goToState: 'policies', + icon: 'images/media/ico_back.png', + onDown: false + } + ), + ccpuVersionLabel: SDL.Label.extend( + { + classNames: 'ccpuVersionLabel', + content: 'CCPU version: ' + } + ), + ccpuVersionInput: Ember.TextField.extend( + { + elementId: 'ccpuVersionInput', + classNames: 'ccpuVersionInput dataInput', + placeholder: '', + valueBinding: 'SDL.SettingsController.editedCcpuVersionValue' + } + ), + applyButton: SDL.Button.extend( + { + elementId: 'applyButton', + classNames: 'applyButton button', + text: 'Apply', + action: 'applyNewCcpuVersionValue', + target: 'SDL.SettingsController', + onDown: false + } + ) + } + ); diff --git a/app/view/settings/policiesView.js b/app/view/settings/policiesView.js index 4448e1541..9da817f11 100644 --- a/app/view/settings/policiesView.js +++ b/app/view/settings/policiesView.js @@ -83,6 +83,17 @@ SDL.PoliciesView = Em.ContainerView.create( onDown: false } }, + { + type: SDL.Button, + params: { + action: 'onState', + goToState: 'policies.ccpuEditor', + text: 'Configure CCPU version', + target: 'SDL.SettingsController', + templateName: 'arrow', + onDown: false, + } + }, { type: SDL.Button, params: { diff --git a/app/view/settingsView.js b/app/view/settingsView.js index 698f8c748..4fdc518de 100644 --- a/app/view/settingsView.js +++ b/app/view/settingsView.js @@ -43,9 +43,14 @@ SDL.SettingsView = Em.ContainerView.create( 'leftMenu', SDL.DeviceStateChangeView, SDL.PoliciesView, + SDL.RPCControlView, SDL.AppPermissionsListView, SDL.AppPermissionsView, SDL.DeviceConfigView, + SDL.RPCControlConfigView, + SDL.RPCWayPointControlConfigView, + SDL.RPCVehicleDataControlConfigView, + SDL.RPCGetIVDControlConfigView, SDL.StatisticsInfoView, SDL.SystemErrorView, SDL.ConnectionSettingsView, @@ -57,7 +62,8 @@ SDL.SettingsView = Em.ContainerView.create( SDL.InteriorLightView, SDL.ExteriorLightView, SDL.SeatView, - SDL.PolicyConfigListView + SDL.PolicyConfigListView, + SDL.CcpuEditorView ], /** Left menu */ leftMenu: Em.ContainerView.extend( @@ -83,7 +89,8 @@ SDL.SettingsView = Em.ContainerView.create( 'policies', 'HMISettings', 'light', - 'seat' + 'seat', + 'rpcControl' ], policies: SDL.Button.extend( { @@ -98,6 +105,26 @@ SDL.SettingsView = Em.ContainerView.create( action: 'turnOnPoliciesSettings', target: 'SDL.SettingsController' } + ), + rpcControl: SDL.Button.extend( + { + isDisabled: function() { + return !SDL.SDLModel.data.registeredApps.length; + }.property( + 'SDL.SDLModel.data.registeredApps.length' + ), + disabledBinding: 'isDisabled', + elementId: 'rpcControl_leftMenu', + goToState: 'rpccontrol', + classNames: 'menu-item lsp1_p', + classNameBindings: [ + 'SDL.States.settings.rpccontrol.active:info_active' + ], + text: 'RPC Control', + icon: 'images/settings/ico_settings.png', + action: 'onState', + target: 'SDL.SettingsController' + } ), HMISettings: SDL.Button.extend({ elementId: 'HMISettings_leftMenu', diff --git a/app/view/webEngine/webEngineView.js b/app/view/webEngine/webEngineView.js new file mode 100644 index 000000000..68b9015a9 --- /dev/null +++ b/app/view/webEngine/webEngineView.js @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2020, Ford Motor Company All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: · + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. · Redistributions in binary + * form must reproduce the above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or other materials provided + * with the distribution. · Neither the name of the Ford Motor Company nor the + * names of its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +/** + * @name SDL.WebEngineView + * @desc WebEngine view + * @category View + * @filesource app/view/webEngine/webEngineView.js + * @version 1.0 + */ +SDL.WebEngineView = Em.ContainerView.create({ + elementId: 'webEngineView', + + classNameBindings: [ + 'SDL.States.webViewApp.active:active_state:inactive_state' + ], + + childViews: [ + 'TemplateAppTitleLabel' + ], + + isExitButtonVisible : true, + + TemplateAppTitleLabel : SDL.Label.extend({ + elementId: 'template_title_label', + contentBinding: 'getText', + getText: function() { + if (SDL.SDLController.model) { + return SDL.SDLController.model.appName + ' / ' + + SDL.SDLController.model.templateConfiguration.template; + } + }.property( + 'SDL.SDLController.model.templateConfiguration.template', + 'SDL.SDLController.model.appName' + ) + }) +}); diff --git a/capabilities/display_capabilities.js b/capabilities/display_capabilities.js index 902f6c6dd..4f69a16f5 100644 --- a/capabilities/display_capabilities.js +++ b/capabilities/display_capabilities.js @@ -38,163 +38,163 @@ SDL.templateCapabilities = { "displayName": "SDL_HMI", "textFields": [{ "name": "mainField1", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 500, "rows": 1 }, { "name": "mainField2", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 500, "rows": 1 }, { "name": "statusBar", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 500, "rows": 1 }, { "name": "mediaClock", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 500, "rows": 1 }, { "name": "mediaTrack", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 500, "rows": 1 }, { "name": "templateTitle", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 100, "rows": 1 }, { "name": "alertText1", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 500, "rows": 1 }, { "name": "alertText2", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 500, "rows": 1 }, { "name": "alertText3", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 500, "rows": 1 }, { "name": "scrollableMessageBody", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 500, "rows": 1 }, { "name": "initialInteractionText", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 500, "rows": 1 }, { "name": "navigationText1", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 500, "rows": 1 }, { "name": "navigationText2", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 500, "rows": 1 }, { "name": "ETA", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 500, "rows": 1 }, { "name": "totalDistance", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 500, "rows": 1 }, { "name": "audioPassThruDisplayText1", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 500, "rows": 1 }, { "name": "audioPassThruDisplayText2", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 500, "rows": 1 }, { "name": "sliderHeader", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 500, "rows": 1 }, { "name": "sliderFooter", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 500, "rows": 1 }, { "name": "menuName", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 500, "rows": 1 }, { "name": "secondaryText", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 500, "rows": 1 }, { "name": "tertiaryText", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 500, "rows": 1 }, { "name": "menuTitle", - "characterSet": "TYPE2SET", - "width": 500, + "characterSet": "UTF_8", + "width": 10, "rows": 1 }, { "name": "locationName", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 500, "rows": 1 }, { "name": "locationDescription", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 500, "rows": 1 }, { "name": "addressLines", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 500, "rows": 1 }, { "name": "phoneNumber", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 500, "rows": 1 } @@ -362,7 +362,7 @@ SDL.templateCapabilities = { ], "graphicSupported": true, "imageCapabilities": ["DYNAMIC", "STATIC"], - "templatesAvailable": ["MEDIA", "NON-MEDIA", "ONSCREEN_PRESETS", "NAV_FULLSCREEN_MAP"], + "templatesAvailable": ["MEDIA", "NON-MEDIA", "NAV_FULLSCREEN_MAP", "WEB_VIEW"], "screenParams": { "resolution": { "resolutionWidth": 800, @@ -467,169 +467,181 @@ SDL.templateCapabilities = { "onScreenPresetsAvailable": true } }, - "ONSCREEN_PRESETS": { + "NON-MEDIA": { "displayCapabilities": { "displayType": "GEN2_8_DMA", "displayName": "SDL_HMI", "textFields": [{ "name": "mainField1", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 500, "rows": 1 }, { "name": "mainField2", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", + "width": 500, + "rows": 1 + }, + { + "name": "mainField3", + "characterSet": "UTF_8", + "width": 500, + "rows": 1 + }, + { + "name": "mainField4", + "characterSet": "UTF_8", "width": 500, "rows": 1 }, { "name": "statusBar", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 500, "rows": 1 }, { "name": "mediaClock", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 500, "rows": 1 }, { "name": "mediaTrack", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 500, "rows": 1 }, { "name": "templateTitle", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 100, "rows": 1 }, { "name": "alertText1", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 500, "rows": 1 }, { "name": "alertText2", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 500, "rows": 1 }, { "name": "alertText3", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 500, "rows": 1 }, { "name": "scrollableMessageBody", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 500, "rows": 1 }, { "name": "initialInteractionText", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 500, "rows": 1 }, { "name": "navigationText1", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 500, "rows": 1 }, { "name": "navigationText2", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 500, "rows": 1 }, { "name": "ETA", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 500, "rows": 1 }, { "name": "totalDistance", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 500, "rows": 1 }, { "name": "audioPassThruDisplayText1", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 500, "rows": 1 }, { "name": "audioPassThruDisplayText2", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 500, "rows": 1 }, { "name": "sliderHeader", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 500, "rows": 1 }, { "name": "sliderFooter", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 500, "rows": 1 }, { "name": "menuName", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 500, "rows": 1 }, { "name": "secondaryText", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 500, "rows": 1 }, { "name": "tertiaryText", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 500, "rows": 1 }, { "name": "menuTitle", - "characterSet": "TYPE2SET", - "width": 500, + "characterSet": "UTF_8", + "width": 12, "rows": 1 }, { "name": "locationName", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 500, "rows": 1 }, { "name": "locationDescription", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 500, "rows": 1 }, { "name": "addressLines", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 500, "rows": 1 }, { "name": "phoneNumber", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 500, "rows": 1 } @@ -797,7 +809,7 @@ SDL.templateCapabilities = { ], "graphicSupported": true, "imageCapabilities": ["DYNAMIC", "STATIC"], - "templatesAvailable": ["MEDIA", "NON-MEDIA", "ONSCREEN_PRESETS", "NAV_FULLSCREEN_MAP"], + "templatesAvailable": ["MEDIA", "NON-MEDIA", "NAV_FULLSCREEN_MAP", "WEB_VIEW"], "screenParams": { "resolution": { "resolutionWidth": 800, @@ -809,7 +821,7 @@ SDL.templateCapabilities = { "doublePressAvailable": false } }, - "numCustomPresetsAvailable": 10 + "numCustomPresetsAvailable": 8 }, "buttonCapabilities": [{ "name": "PRESET_0", @@ -897,198 +909,186 @@ SDL.templateCapabilities = { "onScreenPresetsAvailable": true } }, - "NON-MEDIA": { + "NAV_FULLSCREEN_MAP": { "displayCapabilities": { "displayType": "GEN2_8_DMA", "displayName": "SDL_HMI", "textFields": [{ "name": "mainField1", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 500, "rows": 1 }, { "name": "mainField2", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 500, "rows": 1 }, { "name": "mainField3", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 500, "rows": 1 }, { "name": "mainField4", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 500, "rows": 1 }, { "name": "statusBar", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 500, "rows": 1 }, { "name": "mediaClock", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 500, "rows": 1 }, { "name": "mediaTrack", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 500, "rows": 1 }, { "name": "templateTitle", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 100, "rows": 1 }, { "name": "alertText1", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 500, "rows": 1 }, { "name": "alertText2", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 500, "rows": 1 }, { "name": "alertText3", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 500, "rows": 1 }, { "name": "scrollableMessageBody", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 500, "rows": 1 }, { "name": "initialInteractionText", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 500, "rows": 1 }, { "name": "navigationText1", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 500, "rows": 1 }, { "name": "navigationText2", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 500, "rows": 1 }, { "name": "ETA", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 500, "rows": 1 }, { "name": "totalDistance", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 500, "rows": 1 }, { "name": "audioPassThruDisplayText1", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 500, "rows": 1 }, { "name": "audioPassThruDisplayText2", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 500, "rows": 1 }, { "name": "sliderHeader", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 500, "rows": 1 }, { "name": "sliderFooter", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 500, "rows": 1 }, { "name": "menuName", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 500, "rows": 1 }, { "name": "secondaryText", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 500, "rows": 1 }, { "name": "tertiaryText", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 500, "rows": 1 }, { "name": "menuTitle", - "characterSet": "TYPE2SET", - "width": 500, + "characterSet": "UTF_8", + "width": 15, "rows": 1 }, { "name": "locationName", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 500, "rows": 1 }, { "name": "locationDescription", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 500, "rows": 1 }, { "name": "addressLines", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 500, "rows": 1 }, { "name": "phoneNumber", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 500, "rows": 1 } ], "imageFields": [{ - "name": "softButtonImage", - "imageTypeSupported": [ - "GRAPHIC_BMP", - "GRAPHIC_JPEG", - "GRAPHIC_PNG" - ], - "imageResolution": { - "resolutionWidth": 64, - "resolutionHeight": 64 - } - }, - { "name": "choiceImage", "imageTypeSupported": [ "GRAPHIC_BMP", @@ -1160,30 +1160,6 @@ SDL.templateCapabilities = { "resolutionHeight": 64 } }, - { - "name": "graphic", - "imageTypeSupported": [ - "GRAPHIC_BMP", - "GRAPHIC_JPEG", - "GRAPHIC_PNG" - ], - "imageResolution": { - "resolutionWidth": 64, - "resolutionHeight": 64 - } - }, - { - "name": "secondaryGraphic", - "imageTypeSupported": [ - "GRAPHIC_BMP", - "GRAPHIC_JPEG", - "GRAPHIC_PNG" - ], - "imageResolution": { - "resolutionWidth": 64, - "resolutionHeight": 64 - } - }, { "name": "showConstantTBTIcon", "imageTypeSupported": [ @@ -1239,7 +1215,7 @@ SDL.templateCapabilities = { ], "graphicSupported": true, "imageCapabilities": ["DYNAMIC", "STATIC"], - "templatesAvailable": ["MEDIA", "NON-MEDIA", "ONSCREEN_PRESETS", "NAV_FULLSCREEN_MAP"], + "templatesAvailable": ["MEDIA", "NON-MEDIA", "NAV_FULLSCREEN_MAP", "WEB_VIEW"], "screenParams": { "resolution": { "resolutionWidth": 800, @@ -1250,81 +1226,10 @@ SDL.templateCapabilities = { "multiTouchAvailable": true, "doublePressAvailable": false } - }, - "numCustomPresetsAvailable": 8 + } }, "buttonCapabilities": [{ - "name": "PRESET_0", - "shortPressAvailable": true, - "longPressAvailable": true, - "upDownAvailable": true - }, { - "name": "PRESET_1", - "shortPressAvailable": true, - "longPressAvailable": true, - "upDownAvailable": true - }, { - "name": "PRESET_2", - "shortPressAvailable": true, - "longPressAvailable": true, - "upDownAvailable": true - }, { - "name": "PRESET_3", - "shortPressAvailable": true, - "longPressAvailable": true, - "upDownAvailable": true - }, { - "name": "PRESET_4", - "shortPressAvailable": true, - "longPressAvailable": true, - "upDownAvailable": true - }, { - "name": "PRESET_5", - "shortPressAvailable": true, - "longPressAvailable": true, - "upDownAvailable": true - }, { - "name": "PRESET_6", - "shortPressAvailable": true, - "longPressAvailable": true, - "upDownAvailable": true - }, { - "name": "PRESET_7", - "shortPressAvailable": true, - "longPressAvailable": true, - "upDownAvailable": true - }, { - "name": "PRESET_8", - "shortPressAvailable": true, - "longPressAvailable": true, - "upDownAvailable": true - }, { - "name": "PRESET_9", - "shortPressAvailable": true, - "longPressAvailable": true, - "upDownAvailable": true - }, { - "name": "OK", - "shortPressAvailable": true, - "longPressAvailable": true, - "upDownAvailable": true - }, { - "name": "SEEKLEFT", - "shortPressAvailable": true, - "longPressAvailable": true, - "upDownAvailable": true - }, { - "name": "SEEKRIGHT", - "shortPressAvailable": true, - "longPressAvailable": true, - "upDownAvailable": true - }, { - "name": "TUNEUP", - "shortPressAvailable": true, - "longPressAvailable": true, - "upDownAvailable": true - }, { - "name": "TUNEDOWN", + "name": "CUSTOM_BUTTON", "shortPressAvailable": true, "longPressAvailable": true, "upDownAvailable": true @@ -1336,316 +1241,16 @@ SDL.templateCapabilities = { "imageSupported": true }], "presetBankCapabilities": { - "onScreenPresetsAvailable": true + "onScreenPresetsAvailable": false } }, - "NAV_FULLSCREEN_MAP": { + "WEB_VIEW": { "displayCapabilities": { "displayType": "GEN2_8_DMA", "displayName": "SDL_HMI", - "textFields": [{ - "name": "mainField1", - "characterSet": "TYPE2SET", - "width": 500, - "rows": 1 - }, - { - "name": "mainField2", - "characterSet": "TYPE2SET", - "width": 500, - "rows": 1 - }, - { - "name": "mainField3", - "characterSet": "TYPE2SET", - "width": 500, - "rows": 1 - }, - { - "name": "mainField4", - "characterSet": "TYPE2SET", - "width": 500, - "rows": 1 - }, - { - "name": "statusBar", - "characterSet": "TYPE2SET", - "width": 500, - "rows": 1 - }, - { - "name": "mediaClock", - "characterSet": "TYPE2SET", - "width": 500, - "rows": 1 - }, - { - "name": "mediaTrack", - "characterSet": "TYPE2SET", - "width": 500, - "rows": 1 - }, - { - "name": "templateTitle", - "characterSet": "TYPE2SET", - "width": 100, - "rows": 1 - }, - { - "name": "alertText1", - "characterSet": "TYPE2SET", - "width": 500, - "rows": 1 - }, - { - "name": "alertText2", - "characterSet": "TYPE2SET", - "width": 500, - "rows": 1 - }, - { - "name": "alertText3", - "characterSet": "TYPE2SET", - "width": 500, - "rows": 1 - }, - { - "name": "scrollableMessageBody", - "characterSet": "TYPE2SET", - "width": 500, - "rows": 1 - }, - { - "name": "initialInteractionText", - "characterSet": "TYPE2SET", - "width": 500, - "rows": 1 - }, - { - "name": "navigationText1", - "characterSet": "TYPE2SET", - "width": 500, - "rows": 1 - }, - { - "name": "navigationText2", - "characterSet": "TYPE2SET", - "width": 500, - "rows": 1 - }, - { - "name": "ETA", - "characterSet": "TYPE2SET", - "width": 500, - "rows": 1 - }, - { - "name": "totalDistance", - "characterSet": "TYPE2SET", - "width": 500, - "rows": 1 - }, - { - "name": "audioPassThruDisplayText1", - "characterSet": "TYPE2SET", - "width": 500, - "rows": 1 - }, - { - "name": "audioPassThruDisplayText2", - "characterSet": "TYPE2SET", - "width": 500, - "rows": 1 - }, - { - "name": "sliderHeader", - "characterSet": "TYPE2SET", - "width": 500, - "rows": 1 - }, - { - "name": "sliderFooter", - "characterSet": "TYPE2SET", - "width": 500, - "rows": 1 - }, - { - "name": "menuName", - "characterSet": "TYPE2SET", - "width": 500, - "rows": 1 - }, - { - "name": "secondaryText", - "characterSet": "TYPE2SET", - "width": 500, - "rows": 1 - }, - { - "name": "tertiaryText", - "characterSet": "TYPE2SET", - "width": 500, - "rows": 1 - }, - { - "name": "menuTitle", - "characterSet": "TYPE2SET", - "width": 500, - "rows": 1 - }, - { - "name": "locationName", - "characterSet": "TYPE2SET", - "width": 500, - "rows": 1 - }, - { - "name": "locationDescription", - "characterSet": "TYPE2SET", - "width": 500, - "rows": 1 - }, - { - "name": "addressLines", - "characterSet": "TYPE2SET", - "width": 500, - "rows": 1 - }, - { - "name": "phoneNumber", - "characterSet": "TYPE2SET", - "width": 500, - "rows": 1 - } - ], - "imageFields": [{ - "name": "choiceImage", - "imageTypeSupported": [ - "GRAPHIC_BMP", - "GRAPHIC_JPEG", - "GRAPHIC_PNG" - ], - "imageResolution": { - "resolutionWidth": 64, - "resolutionHeight": 64 - } - }, - { - "name": "choiceSecondaryImage", - "imageTypeSupported": [ - "GRAPHIC_BMP", - "GRAPHIC_JPEG", - "GRAPHIC_PNG" - ], - "imageResolution": { - "resolutionWidth": 64, - "resolutionHeight": 64 - } - }, - { - "name": "vrHelpItem", - "imageTypeSupported": [ - "GRAPHIC_BMP", - "GRAPHIC_JPEG", - "GRAPHIC_PNG" - ], - "imageResolution": { - "resolutionWidth": 64, - "resolutionHeight": 64 - } - }, - { - "name": "turnIcon", - "imageTypeSupported": [ - "GRAPHIC_BMP", - "GRAPHIC_JPEG", - "GRAPHIC_PNG" - ], - "imageResolution": { - "resolutionWidth": 64, - "resolutionHeight": 64 - } - }, - { - "name": "menuIcon", - "imageTypeSupported": [ - "GRAPHIC_BMP", - "GRAPHIC_JPEG", - "GRAPHIC_PNG" - ], - "imageResolution": { - "resolutionWidth": 64, - "resolutionHeight": 64 - } - }, - { - "name": "cmdIcon", - "imageTypeSupported": [ - "GRAPHIC_BMP", - "GRAPHIC_JPEG", - "GRAPHIC_PNG" - ], - "imageResolution": { - "resolutionWidth": 64, - "resolutionHeight": 64 - } - }, - { - "name": "showConstantTBTIcon", - "imageTypeSupported": [ - "GRAPHIC_BMP", - "GRAPHIC_JPEG", - "GRAPHIC_PNG" - ], - "imageResolution": { - "resolutionWidth": 64, - "resolutionHeight": 64 - } - }, - { - "name": "showConstantTBTNextTurnIcon", - "imageTypeSupported": [ - "GRAPHIC_BMP", - "GRAPHIC_JPEG", - "GRAPHIC_PNG" - ], - "imageResolution": { - "resolutionWidth": 64, - "resolutionHeight": 64 - } - }, - { - "name": "showConstantTBTNextTurnIcon", - "imageTypeSupported": [ - "GRAPHIC_BMP", - "GRAPHIC_JPEG", - "GRAPHIC_PNG" - ], - "imageResolution": { - "resolutionWidth": 64, - "resolutionHeight": 64 - } - }, - { - "name": "alertIcon", - "imageTypeSupported": [ - "GRAPHIC_BMP", - "GRAPHIC_JPEG", - "GRAPHIC_PNG" - ], - "imageResolution": { - "resolutionWidth": 105, - "resolutionHeight": 65 - } - } - ], - "mediaClockFormats": [ - "CLOCK1", "CLOCK2", "CLOCK3", "CLOCKTEXT1", "CLOCKTEXT2", - "CLOCKTEXT3", "CLOCKTEXT4" - ], "graphicSupported": true, "imageCapabilities": ["DYNAMIC", "STATIC"], - "templatesAvailable": ["MEDIA", "NON-MEDIA", "ONSCREEN_PRESETS", "NAV_FULLSCREEN_MAP"], + "templatesAvailable": ["MEDIA", "NON-MEDIA", "NAV_FULLSCREEN_MAP", "WEB_VIEW"], "screenParams": { "resolution": { "resolutionWidth": 800, @@ -1657,21 +1262,6 @@ SDL.templateCapabilities = { "doublePressAvailable": false } } - }, - "buttonCapabilities": [{ - "name": "CUSTOM_BUTTON", - "shortPressAvailable": true, - "longPressAvailable": true, - "upDownAvailable": true - }], - "softButtonCapabilities": [{ - "shortPressAvailable": true, - "longPressAvailable": true, - "upDownAvailable": true, - "imageSupported": true - }], - "presetBankCapabilities": { - "onScreenPresetsAvailable": false } } -} \ No newline at end of file +} diff --git a/capabilities/systemCapabilities.js b/capabilities/systemCapabilities.js index b2f59da8c..fb0040fd1 100644 --- a/capabilities/systemCapabilities.js +++ b/capabilities/systemCapabilities.js @@ -65,5 +65,9 @@ SDL.systemCapabilities = diagonalScreenSize: 8, pixelPerInch: 96, scale: 1 + }, + driverDistractionCapability: { + menuLength: 10, + subMenuDepth: 2 } } diff --git a/css/buttonControls.css b/css/buttonControls.css index 1f0d49cd0..5c3c0e1bf 100644 --- a/css/buttonControls.css +++ b/css/buttonControls.css @@ -453,13 +453,19 @@ -webkit-transition: 0.2s; } -#OK.pressed { +#buttonControls .OkBtn.media_button { + background: url(../images/home/controlButtons/PlayPauseButton.png) no-repeat; + background-position: -55px -55px; +} + +#buttonControls .OkBtn.media_button.pressed { + background: url(../images/home/controlButtons/PlayPauseButton_pressed.png) no-repeat; + background-position: -55px -55px; +} + +#buttonControls .OkBtn.pressed { background: url(../images/home/controlButtons/OkButton_pressed.png) no-repeat; - background-position: -55px -55px !important; - width: 89px !important; - height: 90px !important; - left: 55px !important; - top: 55px !important; + background-position: -55px -55px; } #app_controlButtons { diff --git a/css/general.css b/css/general.css index c2ad20a8b..dba963c0d 100644 --- a/css/general.css +++ b/css/general.css @@ -716,6 +716,11 @@ button.next-home { right: 10px; } +.arrow-ico-short { + position: absolute; + right: 0px; +} + .right_text { float: right; margin-right: 5px; @@ -1120,7 +1125,7 @@ margin-top: 90px; .list-item span { position: relative; - margin-left: 5px; + margin-left: 55px; float: left; } @@ -2001,7 +2006,7 @@ to { display: none; } -/* Lable plus Button*/ +/* label plus Button*/ .lablePlusButton .button { float: right; right: 0px; @@ -2010,7 +2015,7 @@ to { border-left: 1px solid #393939; } -.lablePlusButton .lable span, .lablePlusButton .button span { +.lablePlusButton .label span, .lablePlusButton .button span { margin-left: 13px; } @@ -2041,7 +2046,7 @@ to { -webkit-border-radius: 4px; } -/* header lable*/ +/* header label*/ #select_system_heading_lable { position: relative; font-size: 30px; @@ -2101,7 +2106,7 @@ to { margin-top: 2px; } -/* select climate style lable*/ +/* select climate style label*/ #select_system_label { font-size: 20px; width: 135px; @@ -2152,7 +2157,7 @@ to { float: left; } -/* navigationApp select lable*/ +/* navigationApp select label*/ #sdnav_label { position: relative; float: left; @@ -2175,7 +2180,7 @@ to { margin: 50px auto; } -/* Info Lable*/ +/* Info label*/ #select_system_info { position: relative; text-align: center; @@ -2417,4 +2422,4 @@ to { #addWidgetPopUp .list-item span { margin-left: 50px; -} \ No newline at end of file +} diff --git a/css/media.css b/css/media.css index 831c3370c..cff2d308b 100644 --- a/css/media.css +++ b/css/media.css @@ -105,7 +105,6 @@ position: relative; height: 50px; cursor: pointer; - background: url(../images/media/ls-item_bg.png) no-repeat; } .media-ls-item.active_state { @@ -986,7 +985,6 @@ height: 98px; border-right: 1px solid #393939; cursor: pointer; - background: url(../images/media/cd-prev-btn.png) no-repeat; } .bc-item-big.prevcd.pressed, .bc-item-big.prevusb.pressed, @@ -1003,7 +1001,6 @@ height: 98px; border-right: 1px solid #393939; cursor: pointer; - background: url(../images/media/cd_play_btn.png) no-repeat; top: 0px; position: absolute; left: 156px; @@ -1058,7 +1055,6 @@ width: 154px; height: 98px; cursor: pointer; - background: url(../images/media/cd-next-btn.png) no-repeat; top: 0px; position: absolute; left: 314px; diff --git a/css/sdl.css b/css/sdl.css index bf78b6aeb..34956a1e9 100644 --- a/css/sdl.css +++ b/css/sdl.css @@ -1375,6 +1375,27 @@ display: none; } +#SubtleAlertPopUp.SubtleAlertPopUp { + opacity: 0; + left: 80px; + width: 640px; + height: 115px; + z-index: 5; + top: 60px; + -webkit-transition: opacity 1s ease-in-out; + background-color: black; + border: #A6A6A6 solid 2px; + border-radius: 6px; + display: none; + flex-direction: row; + align-items: center; + justify-content: center; +} + +#SubtleAlertPopUp.SubtleAlertPopUp div { + position: static; +} + #AlertManeuverPopUp .applicationName, #AudioPassThruPopUp .applicationName, #AlertPopUp .applicationName { width: 380px; left: 10px; @@ -1394,6 +1415,22 @@ width: auto; } +#SubtleAlertPopUp .subtleAlertPopUpImage { + max-width: 100px; + max-height: 100px; + margin: auto; + height: auto; + width: auto; +} + +#SubtleAlertPopUp .subtleAlertPopUpImageContainer { + width: 20%; + height: 100%; + + display: flex; + justify-content: center; +} + #AlertPopUp .progressIndicator { width: 50px; height: 50px; @@ -1411,6 +1448,31 @@ left: 25px; } +#SubtleAlertPopUp .messages { + flex: 7; + width: 50%; + height: 100%; + + display: flex; + flex-direction: column; + justify-content: center; +} + +#SubtleAlertPopUp .message1 { + font-size: 36px; + line-height: 40px; + overflow: hidden; + text-overflow: ellipsis; +} + +#SubtleAlertPopUp .message2 { + font-size: 23px; + line-height: 30px; + max-height: 60px; + overflow: hidden; + word-wrap: normal; +} + #AudioPassThruPopUp .message1, #AlertPopUp .message1 { top: 37px; left: 105px; @@ -1452,6 +1514,11 @@ display: block; } +#SubtleAlertPopUp.SubtleAlertActive { + opacity: 1; + display: flex; +} + #baseNavigation .softButton, #AlertManeuverPopUp .softButton, #AudioPassThruPopUp .softButton, #AlertPopUp .softButton { border: 1px solid #393939; border-radius: 3px; @@ -1465,6 +1532,18 @@ overflow: hidden; } +#SubtleAlertPopUp .softButton { + border: 1px solid #393939; + border-radius: 3px; + height: 50px; + line-height: 45px; + text-align: center; + float: left; + position: relative; + text-overflow: ellipsis; + overflow: hidden; +} + #baseNavigation .naviOptionsBtn { border: 1px solid #393939; border-radius: 3px; @@ -1501,9 +1580,32 @@ } #AlertPopUp .alertSoftButtons { - margin-left: 8px; top: 120px; - width: 386px; + width: 400px; +} + +#SubtleAlertPopUp .subtleAlertSoftButtons { + width: 100%; + height: 100%; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; +} + +#SubtleAlertPopUp .buttons { + width: 30%; + height: 100%; +} + +#softButton0.oneSubtle { + width: 80%; +} + +#softButton0.twoSubtle, #softButton1.twoSubtle { + width: 80%; + height: 52px; + margin: auto; } #AlertManeuverPopUp .one, #softButton0.one { @@ -1511,9 +1613,15 @@ width: 362px; } +#AlertManeuverPopUp #alertManeuverSoftButtons{ + width: 400px; + height: 245px; +} + #softButton0.two { margin-top: 42px; - width: 170px; + width: 160px; + margin-left: 30px; } #softButton1.two { @@ -1808,13 +1916,6 @@ color: green } -.InvisibleFrame { - position: absolute; - width: 0px; - height: 0px; - visibility: hidden; -} - #sdl_view_container { z-index: 501; } diff --git a/css/settings.css b/css/settings.css index 170e9793d..8e2021d77 100644 --- a/css/settings.css +++ b/css/settings.css @@ -8,6 +8,278 @@ height: 382px; background: black; z-index: 5000; + border: 1px solid white; + border-radius: 10PX; +} + +#settingsView .rpc_settings_separate_view { + top: 68px; + left:190px; + width: 495px; + height: 337px; + background: black; + z-index: 5000; + border: 1px solid white; + border-radius: 10PX; + overflow-y: scroll; +} + + .appNameLabel{ + top: 13px; + left: 213px; + font-size: 200%; + text-align: center; +} + + .backControl { + top: 20px; + width: 35px; + height: 27px; + border: 1px solid #333; + border-radius: 2px; + left: 10px; +} + + .saveButton, + .newButton { + left: 55px; + border: 1px solid #333; + border-radius: 2px; + top: 20px; + width: 60px; + height: 27px; + text-align: center; +} + +.removeButton{ + border: 1px solid #333; + border-radius: 2px; + width: 71px; + height: 27px; + text-align: center; + top: 20px; + left: 125px; +} + +.previousButton{ + border: 1px solid #333; + border-radius: 2px; + width: 71px; + height: 27px; + text-align: center; + top: 20px; + left: 280px; +} + +.nextButton{ + border: 1px solid #333; + border-radius: 2px; + width: 60px; + height: 27px; + text-align: center; + left: 360px; + top: 20px; +} + +.counterLabel{ + top: 55px; + width: 60px; + height: 27px; + text-align: center; +} + +.rpc_settings_separate_view .counterLabel{ + top: 25px; + left: 415px; + width: 60px; + height: 27px; + text-align: center; +} + + .resetButton{ + left: 125px; + border: 1px solid #333; + border-radius: 2px; + top: 20px; + width: 60px; + height: 27px; + text-align: center; + font-size: 75%; +} + +#settingsView .rpc_settings_separate_view + .rpcList{ + left: 170px; + direction: rtl; +} + + .vrAddComandlabel{ + top: 60px; +} + + .uiAddComandlabel{ + top: 85px; +} + + .addSubMenulabel{ + top: 110px; +} + +.createInteractionChoiceSetlabel { + top: 135px; + font-size: 84%; +} + +.uisetGlobalProperties { + top: 160px; +} + +.ttssetGlobalPropertieslabel { + position: absolute; + top: 185px; + font-size: 85%; +} + +.uiCreateWindowLabel { + top: 210px; +} + + .subscribeWayPoints{ + top: 185px; + left: -140px; +} + + .vehicleDataGlobal{ + top: 212px; + left: -150px; +} + + .subscribeVehicleData{ + top: 260px; + left: -140px; +} + +.subscribevehicleData{ + top: 50px; + direction: initial; + position: absolute; + height: 30px; + width: 479px; +} +.subscribevehicleData .label{ + position: absolute; + left: 10px; + top: 5px; +} +.subscribevehicleData .select{ + position: absolute; + left: 185px; + top: 5px; +} + +.subscribevehicleDataParams{ + position: relative; + height: 850px; + width: 479px; + top: 80px; +} +.subscribevehicleDataParams .params{ + top: 5px; + position: relative; + height: 30px; + width: 450px; + left: 26px; +} +.subscribevehicleDataParams .params .label{ + left: 10px; +} +.subscribevehicleDataParams .params .select{ + left: 205px; + position: absolute; +} + +#settingsView .rpc_settings_separate_view + .resultCodeTracker{ + left: 200px; + direction: ltl; +} + + .vrAddComandSelect{ + top:60px; + position: absolute; +} + +.uiAddComandSelect{ + top:85px; + position: absolute; +} + + .addSubMenuSelect{ + top: 110px; + position: absolute; +} + +.createInteractionChoiceSetSelect { + top: 135px; + position: absolute; +} + +.uisetGlobalPropertiesSelect { + top: 160px; + position: absolute; +} + +.ttssetGlobalPropertiesSelect { + top: 185px; + position: absolute; +} + +.uiCreateWindowSelect { + top: 210px; + position: absolute; +} + + .subscribeWayPointsSelect{ + top: 55px; + left: 55px; + width: 407px; + height: 18px; + position: absolute; +} + + .vehicleDataGlobalSelect{ + top: 210px; + position: absolute; +} + +.customResultCodeLabel{ + top: 60px; + left: 55px; + width: 407px; + height: 18px; + position: absolute; +} + +.getIVDSelect{ + top: 80px; + left: 55px; + width: 407px; + height: 18px; + position: absolute; +} + +.subscribedLabel { + position: absolute; + top: 110px; + left: 55px; + width: 190px; +} + +.getIVDSubscribed{ + position: absolute; + top: 135px; + left: 55px; + width: 170px; } #settingsView .in_settings_separate_view .backButton, @@ -28,7 +300,7 @@ .in_light_single_view .list, .in_light_location_view .list, .in_light_interior_view .list { - height: 201px; + height: 251px; width: 700px; top: 106px; left: 50px; @@ -68,6 +340,29 @@ padding-left: 10px; } +#settingsView .in_settings_separate_view .ccpuVersionInput { + position: absolute; + left: 145px; + top: 115px; + width: 400px; +} + +#settingsView .in_settings_separate_view .applyButton { + position: absolute; + left: 585px; + top: 115px; + width: 75px; + text-align: center; +} + +#settingsView .in_settings_separate_view .label.ccpuVersionLabel { + position: absolute; + top: 110px; + left: 10px; + background: black; + width: 120px; +} + #settingsView .in_settings_separate_view .sendRequestButton { top: 210px; left: 130px; @@ -97,6 +392,10 @@ width: 80px; } +#settingsView .right_text { + padding-left: 50px; +} + #settingsView .in_settings_separate_view .label, .in_light_exterior_view .label, .in_light_single_view .label, @@ -190,13 +489,13 @@ z-index: 1001; margin-top: 70px; } - +#settingsView .rpc_settings_list, #settingsView .policies_settings_list { height: 251px; width: 598px; left: 10px; } - +#rpc_settings_list .list-content .ffw-button, #policies_settings_list .list-content .ffw-button { width: 537px; padding-left: 10px; diff --git a/css/webEngine.css b/css/webEngine.css new file mode 100644 index 000000000..1331231ee --- /dev/null +++ b/css/webEngine.css @@ -0,0 +1,23 @@ +/* Web Engine related control styles */ + +#webEngineView { + position: absolute; + top: 48px; + width: 800px; + height: 384px; +} + +#webEngineView .WebEngineFrame { + position: absolute; + width: 800px; + height: 384px; +} + +#webEngineView #template_title_label { + position: absolute; + top: 357px; + left: 175px; + width: 460px; + text-align: center; + z-index: 1; +} diff --git a/ffw/BasicCommunicationRPC.js b/ffw/BasicCommunicationRPC.js index 3ea9ce58d..668151f74 100644 --- a/ffw/BasicCommunicationRPC.js +++ b/ffw/BasicCommunicationRPC.js @@ -282,12 +282,12 @@ FFW.BasicCommunication = FFW.RPCObserver } else { SDL.SettingsController.OnSystemRequestHandler(); } + if (FLAGS.ExternalPolicies === true) { + SDL.SettingsController.policyUpdateRetry(); + } } else { SDL.SettingsController.requestPTUFromEndpoint(SDL.SettingsController.policyUpdateFile, data[key].default); } - if (FLAGS.ExternalPolicies === true) { - SDL.SettingsController.policyUpdateRetry(); - } } } } @@ -365,7 +365,9 @@ FFW.BasicCommunication = FFW.RPCObserver } if (response.result.method == 'SDL.GetStatusUpdate') { Em.Logger.log('SDL.GetStatusUpdate: Response from SDL!'); - SDL.PopUp.create().appendTo('body').popupActivate(response.result); + SDL.PopUp.create().appendTo('body').popupActivate( + "Update Status: " + response.result.status, null, false + ); } if (response.result.method == 'BasicCommunication.GetAppProperties') { Em.Logger.log('BasicCommunication.GetAppProperties: Response from SDL!'); @@ -500,16 +502,21 @@ FFW.BasicCommunication = FFW.RPCObserver if (notification.method == this.onAppRegisteredNotification) { let appModel = Object.assign(notification.params.application, { "priority": notification.params.priority ? notification.params.priority : 'NONE' - }); + }); SDL.SDLModel.onAppRegistered( appModel, notification.params.vrSynonyms ); + FFW.RPCHelper.addApplication(notification.params.application.appID); this.OnFindApplications(); const mainWindowID = 0; let capability = SDL.SDLController.getDefaultCapabilities(mainWindowID, notification.params.application.appID); FFW.BasicCommunication.OnSystemCapabilityUpdated(capability); } if (notification.method == this.onAppUnregisteredNotification) { + if(notification.params.appID === FFW.RPCHelper.get('currentAppID')){ + SDL.States.goToStates('settings.rpccontrol'); + SDL.RPCControlView.showAppList(); + } // remove app from list SDL.SDLModel.onAppUnregistered(notification.params); } @@ -692,7 +699,7 @@ FFW.BasicCommunication = FFW.RPCObserver // from SDL // protocol 'method': request.method, - 'ccpu_version': 'ccpu_version', + 'ccpu_version': SDL.SDLModel.data.ccpuVersion, 'language': SDL.SDLModel.data.hmiUILanguage, 'wersCountryCode': 'wersCountryCode' } @@ -937,22 +944,19 @@ FFW.BasicCommunication = FFW.RPCObserver */ sendError: function(resultCode, id, method, message) { Em.Logger.log('FFW.' + method + 'Response'); - if (resultCode != SDL.SDLModel.data.resultCode.SUCCESS) { - - // send repsonse - var JSONMessage = { - 'jsonrpc': '2.0', - 'id': id, - 'error': { - 'code': resultCode, // type (enum) from SDL protocol - 'message': message, - 'data': { - 'method': method - } + // send response + var JSONMessage = { + 'jsonrpc': '2.0', + 'id': id, + 'error': { + 'code': resultCode, // type (enum) from SDL protocol + 'message': message, + 'data': { + 'method': method } - }; - this.sendMessage(JSONMessage); - } + } + }; + this.sendMessage(JSONMessage); }, /** * send response from onRPCRequest @@ -963,12 +967,46 @@ FFW.BasicCommunication = FFW.RPCObserver * id * @param {String} * method + * @param {String} + * info */ - sendBCResult: function(resultCode, id, method) { - Em.Logger.log('FFW.' + method + 'Response'); - if (resultCode === SDL.SDLModel.data.resultCode.SUCCESS) { + sendBCResult: function(resultCode, id, method, info, params) { + const is_successful_code = FFW.RPCHelper.isSuccessResultCode(resultCode); + if (is_successful_code && this.errorResponsePull[id] != null) { + // If request was successful but some error was observed upon validation + // Then result code assigned by RPCController should be considered instead + const errorStruct = this.errorResponsePull[id]; + this.errorResponsePull[id] = null; + + this.sendBCResult( + errorStruct.code, + id, + method, + `Unsupported ${errorStruct.type} type. Available data in request was processed.` + ); + return; + } - // send repsonse + let is_successful_response_format = function(is_success) { + // Successful response without params, but with not-empty message + // should be sent in errorneous format to properly forward info and result code + if (is_success && info != null && params == null) { + return false; + } + + // Error response with not empty params should be sent in regular format + // to properly forward result code and params (but sacrifice info) + if (!is_success && params != null) { + return true; + } + + // Otherwise use result code calculated according to regular HMI logic + return is_success; + }; + + Em.Logger.log('FFW.BC.' + method + 'Response'); + if (is_successful_response_format(is_successful_code)) { + // send response var JSONMessage = { 'jsonrpc': '2.0', 'id': id, @@ -977,7 +1015,14 @@ FFW.BasicCommunication = FFW.RPCObserver 'method': method } }; + + if (params != null) { + Object.assign(JSONMessage.result, params); + } + this.sendMessage(JSONMessage); + } else { + this.sendError(resultCode, id, method, info); } }, /** diff --git a/ffw/ExternalPolicies.js b/ffw/ExternalPolicies.js index 79897a48b..753b4fffa 100644 --- a/ffw/ExternalPolicies.js +++ b/ffw/ExternalPolicies.js @@ -91,7 +91,7 @@ FFW.ExternalPolicies = Em.Object.create({ Em.Logger.log('ExternalPolicies onWSMessage ' + evt.data); this.packResponseReady = true; FFW.BasicCommunication.OnSystemRequest( - this.sysReqParams.type, + this.sysReqParams.requestType, this.sysReqParams.fileName, this.sysReqParams.url, this.sysReqParams.appID diff --git a/ffw/NavigationRPC.js b/ffw/NavigationRPC.js index e5fd97d13..684f04923 100644 --- a/ffw/NavigationRPC.js +++ b/ffw/NavigationRPC.js @@ -175,58 +175,6 @@ FFW.Navigation = FFW.RPCObserver.create( } } }, - isPng:function(params){ - var returnValue=true; - if(params.nextTurnIcon){ - var image = params.nextTurnIcon.value; - var search_offset = image.lastIndexOf('.'); - str='.png'; - var isPng=image.includes(str, search_offset); - if(!isPng){ - delete params.nextTurnIcon; - returnValue=false; - } - } - if(params.turnIcon){ - var image = params.turnIcon.value; - var search_offset = image.lastIndexOf('.'); - str='.png'; - var isPng=image.includes(str, search_offset); - if(!isPng){ - delete params.turnIcon; - returnValue=false; - } - } - if(params.turnList){ - var countList=params.turnList.length; - for(var i=0;i 1){ + this.wayPointResultCodes.shift(); //remove the first element of the array + + currentNumber = this.SubscribeWayPointsRequestNumber; + this.set('SubscribeWayPointsRequestNumber', + Math.min(currentNumber, + this.wayPointResultCodes.length)); + this.updateSubscribeWayPoints(); + } else if(length == 1){ + this.set('SubscribeWayPoints', 'SUCCESS'); + } + + if ('DO_NOT_RESPOND' == code) { + return code; + } + + return SDL.SDLModel.data.resultCode[code] + }, + + /* + * Claims next result code for SubscribeVehicleData RPC + */ + getNextVehicleDataResultCode: function(){ + this.updateVehicleDataResultCodes(); + + nextVehicleDataResultCode = this.VehicleDataResultCodes[0].SubscribeVehicleData; + const next_code = 'DO_NOT_RESPOND' == nextVehicleDataResultCode ? + nextVehicleDataResultCode : SDL.SDLModel.data.resultCode[nextVehicleDataResultCode]; + + code = { + SubscribeVehicleData: next_code, + vehicleDataStruct:{} + }; + + for(var paramName in this.vehicleDataStruct){ + nextParamResultCode = this.VehicleDataResultCodes[0].vehicleDataStruct[paramName] + code.vehicleDataStruct[paramName] = nextParamResultCode; + } + + length = this.VehicleDataResultCodes.length; + if(length > 1){ + this.VehicleDataResultCodes.shift(); //remove the first element of the array + currentNumber = this.VehicleDataRequestNumber; + this.set('VehicleDataRequestNumber',0); + this.set('VehicleDataRequestNumber', Math.min(currentNumber, + this.VehicleDataResultCodes.length)); + + this.updateSubscribeVehicleData(); + } else if(length == 1){ + this.set('SubscribeVehicleData', 'SUCCESS'); + this.set('vehicleDataStruct', this.getSuccessVehicleDataStruct()); + } + + return code; + }, + + /* + * Claims next result code for GetIVD RPC + */ + getNextGetIVDResultCode: function(){ + this.updategetIVDResultCodes(); + + length = this.getIVDResultStruct.length; + + result = this.getIVDResultStruct[0]; + if(length > 1){ + this.getIVDResultStruct.shift(); //remove the first element of the array + + currentNumber = this.getIVDRequestNumber; + length = this.getIVDResultStruct.length; + this.set('getIVDRequestNumber', Math.min(currentNumber, length)); + this.updateGetIVDData(); + + // Manually update counterLabel and nextButton if currentNumber == length + if(currentNumber == length) { + SDL.RPCGetIVDControlConfigView.nextButton.set('disabled', true); + SDL.RPCGetIVDControlConfigView.counterLabel.set('content', currentNumber + '/' + length); + } + } else if (length == 1){ + this.set('getIVDResult', 'SUCCESS'); + this.set('getIVDSubscribed', FFW.RPCHelper.subscribeDataValues[0]); + } + + if ('DO_NOT_RESPOND' == result.code) { + return result; + } + + result.code = SDL.SDLModel.data.resultCode[result.code]; + return result; + }, + + wayPointResultCodes: ['SUCCESS'], + SubscribeWayPoints: '', + SubscribeWayPointsRequestNumber: 1, + + getIVDResultStruct: [ + { + code: 'SUCCESS', + subscribed: 'USE_EXISTING' + } + ], + getIVDResult: '', + getIVDSubscribed: '', + getIVDRequestNumber: 1, + + defaultRpcStruct: {}, + currentAppID: null, + + rpcStruct: { + vrAddCommand:'', + uiAddCommand: '', + createInteractionChoiceSet: '', + AddSubmenu:'', + uiSetGlobalProperties: '', + ttsSetGlobalProperties: '', + uiCreateWindow: '' + }, + + VehicleDataResultCodes: [], + VehicleDataRequestNumber: 1, + SubscribeVehicleData: '', + vehicleDataStruct: { + speed:'', + rpm: '', + fuelLevel: '', + fuelLevel_State: '', + instantFuelConsumption: '', + externalTemperature: '', + turnSignal: '', + prndl: '', + tirePressure: '', + odometer: '', + beltStatus: '', + bodyInformation: '', + deviceStatus: '', + driverBraking: '', + wiperStatus: '', + headLampStatus: '', + engineTorque: '', + accPedalPosition: '', + steeringWheelAngle: '', + engineOilLife: '', + electronicParkBrakeStatus: '', + eCallInfo: '', + airbagStatus: '', + emergencyEvent: '', + clusterModes: '', + myKey: '', + fuelRange: '', + gps: '' + } + } +); diff --git a/ffw/RPCObserver.js b/ffw/RPCObserver.js index 01f7b2b1b..ae4b0b549 100644 --- a/ffw/RPCObserver.js +++ b/ffw/RPCObserver.js @@ -152,6 +152,7 @@ FFW.RPCObserver = Em.Object.extend( params.cmdIcon.value = params.cmdIcon.value + '?m=' + new Date().getTime(); } } + if ('menuIcon' in params) { if (params.menuIcon.imageType === 'STATIC') { delete params.menuIcon; diff --git a/ffw/TTSRPC.js b/ffw/TTSRPC.js index dc4631f38..453156f1d 100644 --- a/ffw/TTSRPC.js +++ b/ffw/TTSRPC.js @@ -201,11 +201,24 @@ FFW.TTS = FFW.RPCObserver.create( // this.errorResponsePull[request.id].type + " type. Request was not // processed."); this.errorResponsePull[request.id] = null; return; // } } - SDL.SDLModel.setProperties(request.params); + resultCode = FFW.RPCHelper.getCustomResultCode(request.params.appID, 'ttsSetGlobalProperties'); + if ('DO_NOT_RESPOND' == resultCode) { + Em.Logger.log('Do not respond on this request'); + return; + } + + let info = null; + + if(FFW.RPCHelper.isSuccessResultCode(resultCode)){ + SDL.SDLModel.setProperties(request.params); + } else { + info = 'Erroneous response is assigned by settings'; + } this.sendTTSResult( - SDL.SDLModel.data.resultCode.SUCCESS, + resultCode, request.id, - request.method + request.method, + info ); break; } @@ -343,22 +356,19 @@ FFW.TTS = FFW.RPCObserver.create( */ sendError: function(resultCode, id, method, message) { Em.Logger.log('FFW.' + method + 'Response'); - if (resultCode != SDL.SDLModel.data.resultCode.SUCCESS) { - - // send repsonse - var JSONMessage = { - 'jsonrpc': '2.0', - 'id': id, - 'error': { - 'code': resultCode, // type (enum) from SDL protocol - 'message': message, - 'data': { - 'method': method - } + // send response + var JSONMessage = { + 'jsonrpc': '2.0', + 'id': id, + 'error': { + 'code': resultCode, // type (enum) from SDL protocol + 'message': message, + 'data': { + 'method': method } - }; - this.sendMessage(JSONMessage); - } + } + }; + this.sendMessage(JSONMessage); }, /** * send response from onRPCRequest @@ -369,21 +379,46 @@ FFW.TTS = FFW.RPCObserver.create( * id * @param {String} * method + * @param {String} + * info */ - sendTTSResult: function(resultCode, id, method) { - if (this.errorResponsePull[id]) { - this.sendError( - this.errorResponsePull[id].code, id, method, - 'Unsupported ' + this.errorResponsePull[id].type + - ' type. Available data in request was processed.' - ); + sendTTSResult: function(resultCode, id, method, info, params) { + const is_successful_code = FFW.RPCHelper.isSuccessResultCode(resultCode); + if (is_successful_code && this.errorResponsePull[id] != null) { + // If request was successful but some error was observed upon validation + // Then result code assigned by RPCController should be considered instead + const errorStruct = this.errorResponsePull[id]; this.errorResponsePull[id] = null; + + this.sendTTSResult( + errorStruct.code, + id, + method, + `Unsupported ${errorStruct.type} type. Available data in request was processed.` + ); return; } - Em.Logger.log('FFW.' + method + 'Response'); - if (resultCode === SDL.SDLModel.data.resultCode.SUCCESS) { - // send repsonse + let is_successful_response_format = function(is_success) { + // Successful response without params, but with not-empty message + // should be sent in errorneous format to properly forward info and result code + if (is_success && info != null && params == null) { + return false; + } + + // Error response with not empty params should be sent in regular format + // to properly forward result code and params (but sacrifice info) + if (!is_success && params != null) { + return true; + } + + // Otherwise use result code calculated according to regular HMI logic + return is_success; + }; + + Em.Logger.log('FFW.TTS.' + method + 'Response'); + if (is_successful_response_format(is_successful_code)) { + // send response var JSONMessage = { 'jsonrpc': '2.0', 'id': id, @@ -392,7 +427,14 @@ FFW.TTS = FFW.RPCObserver.create( 'method': method } }; + + if (params != null) { + Object.assign(JSONMessage.result, params); + } + this.sendMessage(JSONMessage); + } else { + this.sendError(resultCode, id, method, info); } }, /* diff --git a/ffw/UIRPC.js b/ffw/UIRPC.js old mode 100644 new mode 100755 index e90367887..09a279a1a --- a/ffw/UIRPC.js +++ b/ffw/UIRPC.js @@ -190,6 +190,18 @@ FFW.UI = FFW.RPCObserver.create( }) break; } + case 'UI.SubtleAlert': + { + if (SDL.SDLModel.onUISubtleAlert(request.params, request.id)) { + SDL.SDLController.onSystemContextChange(request.params.appID); + } + SDL.SDLModel.data.registeredApps.forEach(app => { + app.activeWindows.forEach(widget => { + SDL.SDLController.onSystemContextChange(app.appID, widget.windowID); + }) + }) + break; + } case 'UI.Show': { @@ -202,16 +214,15 @@ FFW.UI = FFW.RPCObserver.create( 'secondaryGraphic' in request.params || 'softButtons' in request.params || 'customPresets' in request.params) { - this.errorResponsePull[request.id].code = - SDL.SDLModel.data.resultCode['WARNINGS']; - //} else { - // //If no available data sent error response and stop - // process current request - // this.sendError(this.errorResponsePull[request.id].code, - // request.id, request.method, "Unsupported " + - // this.errorResponsePull[request.id].type + " type. Request - // was not processed."); this.errorResponsePull[request.id] = - // null; return; + + if (this.errorResponsePull[request.id].type === 'STATIC') { + this.errorResponsePull[request.id].code = + SDL.SDLModel.data.resultCode['UNSUPPORTED_RESOURCE']; + } + else { + this.errorResponsePull[request.id].code = + SDL.SDLModel.data.resultCode['WARNINGS']; + } } } SDL.TurnByTurnView.deactivate(); @@ -223,6 +234,15 @@ FFW.UI = FFW.RPCObserver.create( let sendCapabilityUpdated = false; if("templateConfiguration" in request.params) { if (model.templateConfiguration.template !== request.params.templateConfiguration.template) { + model.templateConfiguration.template = request.params.templateConfiguration.template; + + if (model.active) { + SDL.SDLModel.data.templateChangeInProgress = true; + SDL.States.goToStates('info.apps'); + model.turnOnSDL(); + SDL.SDLModel.data.templateChangeInProgress = false; + } + sendCapabilityUpdated = true; } if ("dayColorScheme" in request.params.templateConfiguration @@ -244,9 +264,35 @@ FFW.UI = FFW.RPCObserver.create( return; } SDL.InfoAppsView.showAppList(); - this.sendUIResult( - SDL.SDLModel.data.resultCode.SUCCESS, request.id, request.method - ); + + imageList = []; + if(request.params.graphic) { + imageList.push(request.params.graphic.value); + } + if(request.params.secondaryGraphic) { + imageList.push(request.params.secondaryGraphic.value); + } + if(request.params.softButtons) { + for(var i = 0; i < request.params.softButtons.length; i++) { + var image = request.params.softButtons[i].image; + if(image) { + imageList.push(image.value); + } + } + } + + var callback = function(failed) { + var WARNINGS = SDL.SDLModel.data.resultCode.WARNINGS; + var SUCCESS = SDL.SDLModel.data.resultCode.SUCCESS; + + FFW.UI.sendUIResult( + failed ? WARNINGS : SUCCESS, + request.id, + request.method, + failed ? "Requested image(s) not found" : null); + } + SDL.SDLModel.validateImages(request.id, callback, imageList); + if (sendCapabilityUpdated) { let capability = SDL.SDLController.getDefaultCapabilities(request.params.windowID, request.params.appID); FFW.BasicCommunication.OnSystemCapabilityUpdated(capability); @@ -273,9 +319,49 @@ FFW.UI = FFW.RPCObserver.create( // this.errorResponsePull[request.id].type + " type. Request was // not processed."); this.errorResponsePull[request.id] = null; // return; } } + resultCode = FFW.RPCHelper.getCustomResultCode(request.params.appID, 'uiSetGlobalProperties'); + if ('DO_NOT_RESPOND' == resultCode) { + Em.Logger.log('Do not respond on this request'); + return; + } + + let info = null; + + if(FFW.RPCHelper.isSuccessResultCode(resultCode)){ SDL.SDLModel.setProperties(request.params); + + var imageList = []; + if(request.params.menuIcon) { + imageList.push(request.params.menuIcon.value); + } + + if(request.params.vrHelp) { + for(var i = 0; i < request.params.vrHelp.length; i++) { + if(request.params.vrHelp[i].image) { + imageList.push(request.params.vrHelp[i].image.value); + } + } + } + + var that = this; + var callback = function(failed) { + var WARNINGS = SDL.SDLModel.data.resultCode.WARNINGS; + var SUCCESS = resultCode; + + that.sendUIResult( + failed ? WARNINGS : SUCCESS, + request.id, + request.method, + failed ? "Requested image(s) not found" : null); + } + SDL.SDLModel.validateImages(request.id, callback, imageList); + break; + } else { + info = 'Erroneous response is assigned by settings'; + } + this.sendUIResult( - SDL.SDLModel.data.resultCode.SUCCESS, request.id, request.method + resultCode, request.id, request.method, info ); break; } @@ -325,21 +411,18 @@ FFW.UI = FFW.RPCObserver.create( { // Verify if there is an unsupported data in request - //if (this.errorResponsePull[request.id] != null) { - // - ////Check if there is any available data to process the request - //if ("choiceSet" in request.params - // && request.params - // && request.params.interactionLayout != "KEYBOARD") { - // - // this.errorResponsePull[request.id].code = - // SDL.SDLModel.data.resultCode["WARNINGS"]; } else { If no - // available data sent error response and stop process current - // request this.sendError(this.errorResponsePull[request.id].code, - // request.id, request.method, "Unsupported " + - // this.errorResponsePull[request.id].type + " type. Request was - // not processed."); this.errorResponsePull[request.id] = null; - // return; } } + if (this.errorResponsePull[request.id] != null) { + if (request.params && 'choiceSet' in request.params && request.params.interactionLayout != "KEYBOARD") { + if (this.errorResponsePull[request.id].type === 'STATIC') { + this.sendError(SDL.SDLModel.data.resultCode['UNSUPPORTED_RESOURCE'], + request.id, + request.method, + 'Image of STATIC type is not supported on HMI. Request was not processed'); + return; + } + } + } + if (SDL.SDLModel.uiPerformInteraction(request)) { SDL.SDLController.onSystemContextChange(); SDL.SDLModel.data.registeredApps.forEach(app => { @@ -374,6 +457,9 @@ FFW.UI = FFW.RPCObserver.create( } else if (typeID === 26 && SDL.SliderView.active && (targetID === undefined || targetID === SDL.SliderView.cancelID)) { SDL.SliderView.deactivate(); + } else if (typeID === 64 && SDL.SubtleAlertPopUp.active + && (targetID === undefined || targetID === SDL.SubtleAlertPopUp.cancelID)) { + SDL.SubtleAlertPopUp.deactivate(); } else { this.sendError(SDL.SDLModel.data.resultCode.IGNORED, request.id, request.method, @@ -465,14 +551,14 @@ FFW.UI = FFW.RPCObserver.create( case 'MEDIA': case 'NON-MEDIA': case 'DEFAULT': - case 'ONSCREEN_PRESETS': case 'NAV_FULLSCREEN_MAP': + case 'WEB_VIEW': { sendResponseFlag = true; break; } } - var model = SDL.SDLController.getApplicationModel(request.params.appID); + if (sendResponseFlag) { Em.Logger.log('FFW.' + request.method + 'Response'); var displayLayout = request.params.displayLayout; @@ -514,6 +600,14 @@ FFW.UI = FFW.RPCObserver.create( let sendCapabilityUpdated = false; if ("displayLayout" in request.params && model.templateConfiguration.template !== request.params.displayLayout) { model.templateConfiguration.template = request.params.displayLayout + + if (model.active) { + SDL.SDLModel.data.templateChangeInProgress = true; + SDL.States.goToStates('info.apps'); + model.turnOnSDL(); + SDL.SDLModel.data.templateChangeInProgress = false; + } + sendCapabilityUpdated = true; } if ("dayColorScheme" in request.params @@ -637,175 +731,193 @@ FFW.UI = FFW.RPCObserver.create( 'textFields': [ { 'name': 'mainField1', - 'characterSet': 'TYPE2SET', + 'characterSet': 'UTF_8', 'width': 500, 'rows': 1 }, { 'name': 'mainField2', - 'characterSet': 'TYPE2SET', + 'characterSet': 'UTF_8', 'width': 500, 'rows': 1 }, { 'name': 'mainField3', - 'characterSet': 'TYPE2SET', + 'characterSet': 'UTF_8', 'width': 500, 'rows': 1 }, { 'name': 'mainField4', - 'characterSet': 'TYPE2SET', + 'characterSet': 'UTF_8', 'width': 500, 'rows': 1 }, { 'name': 'statusBar', - 'characterSet': 'TYPE2SET', + 'characterSet': 'UTF_8', 'width': 500, 'rows': 1 }, { 'name': 'mediaClock', - 'characterSet': 'TYPE2SET', + 'characterSet': 'UTF_8', 'width': 500, 'rows': 1 }, { 'name': 'mediaTrack', - 'characterSet': 'TYPE2SET', + 'characterSet': 'UTF_8', 'width': 500, 'rows': 1 }, { "name": "templateTitle", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 100, "rows": 1 }, { 'name': 'alertText1', - 'characterSet': 'TYPE2SET', + 'characterSet': 'UTF_8', 'width': 500, 'rows': 1 }, { 'name': 'alertText2', - 'characterSet': 'TYPE2SET', + 'characterSet': 'UTF_8', 'width': 500, 'rows': 1 }, { 'name': 'alertText3', - 'characterSet': 'TYPE2SET', + 'characterSet': 'UTF_8', 'width': 500, 'rows': 1 }, { 'name': 'scrollableMessageBody', - 'characterSet': 'TYPE2SET', + 'characterSet': 'UTF_8', 'width': 500, 'rows': 1 }, { 'name': 'initialInteractionText', - 'characterSet': 'TYPE2SET', + 'characterSet': 'UTF_8', 'width': 500, 'rows': 1 }, { 'name': 'navigationText1', - 'characterSet': 'TYPE2SET', + 'characterSet': 'UTF_8', 'width': 500, 'rows': 1 }, { 'name': 'navigationText2', - 'characterSet': 'TYPE2SET', + 'characterSet': 'UTF_8', 'width': 500, 'rows': 1 }, { 'name': 'ETA', - 'characterSet': 'TYPE2SET', + 'characterSet': 'UTF_8', 'width': 500, 'rows': 1 }, { 'name': 'totalDistance', - 'characterSet': 'TYPE2SET', + 'characterSet': 'UTF_8', 'width': 500, 'rows': 1 }, { 'name': 'audioPassThruDisplayText1', - 'characterSet': 'TYPE2SET', + 'characterSet': 'UTF_8', 'width': 500, 'rows': 1 }, { 'name': 'audioPassThruDisplayText2', - 'characterSet': 'TYPE2SET', + 'characterSet': 'UTF_8', 'width': 500, 'rows': 1 }, { 'name': 'sliderHeader', - 'characterSet': 'TYPE2SET', + 'characterSet': 'UTF_8', 'width': 500, 'rows': 1 }, { 'name': 'sliderFooter', - 'characterSet': 'TYPE2SET', + 'characterSet': 'UTF_8', 'width': 500, 'rows': 1 }, { 'name': 'menuName', - 'characterSet': 'TYPE2SET', + 'characterSet': 'UTF_8', 'width': 500, 'rows': 1 }, { 'name': 'secondaryText', - 'characterSet': 'TYPE2SET', + 'characterSet': 'UTF_8', 'width': 500, 'rows': 1 }, { 'name': 'tertiaryText', - 'characterSet': 'TYPE2SET', + 'characterSet': 'UTF_8', 'width': 500, 'rows': 1 }, { 'name': 'menuTitle', - 'characterSet': 'TYPE2SET', + 'characterSet': 'UTF_8', 'width': 500, 'rows': 1 }, { 'name': 'locationName', - 'characterSet': 'TYPE2SET', + 'characterSet': 'UTF_8', 'width': 500, 'rows': 1 }, { 'name': 'locationDescription', - 'characterSet': 'TYPE2SET', + 'characterSet': 'UTF_8', 'width': 500, 'rows': 1 }, { 'name': 'addressLines', - 'characterSet': 'TYPE2SET', + 'characterSet': 'UTF_8', 'width': 500, 'rows': 1 }, { 'name': 'phoneNumber', - 'characterSet': 'TYPE2SET', + 'characterSet': 'UTF_8', + 'width': 500, + 'rows': 1 + }, + { + 'name': 'subtleAlertText1', + 'characterSet': 'UTF_8', + 'width': 500, + 'rows': 1 + }, + { + 'name': 'subtleAlertText2', + 'characterSet': 'UTF_8', + 'width': 500, + 'rows': 1 + }, + { + 'name': 'subtleAlertSoftButtonText', + 'characterSet': 'UTF_8', 'width': 500, 'rows': 1 } @@ -966,6 +1078,18 @@ FFW.UI = FFW.RPCObserver.create( 'resolutionWidth': 105, 'resolutionHeight': 65 } + }, + { + 'name': 'subtleAlertIcon', + 'imageTypeSupported': [ + 'GRAPHIC_BMP', + 'GRAPHIC_JPEG', + 'GRAPHIC_PNG' + ], + 'imageResolution': { + 'resolutionWidth': 105, + 'resolutionHeight': 65 + } } ], 'mediaClockFormats': [ @@ -974,7 +1098,7 @@ FFW.UI = FFW.RPCObserver.create( ], 'graphicSupported': true, 'imageCapabilities': ['DYNAMIC', 'STATIC'], - 'templatesAvailable': ['TEMPLATE'], + 'templatesAvailable': ["MEDIA", "NON-MEDIA", "DEFAULT", "NAV_FULLSCREEN_MAP", 'WEB_VIEW'], 'screenParams': { 'resolution': { 'resolutionWidth': 800, @@ -1001,175 +1125,175 @@ FFW.UI = FFW.RPCObserver.create( "textFields": [ { 'name': 'mainField1', - 'characterSet': 'TYPE2SET', + 'characterSet': 'UTF_8', 'width': 500, 'rows': 1 }, { 'name': 'mainField2', - 'characterSet': 'TYPE2SET', + 'characterSet': 'UTF_8', 'width': 500, 'rows': 1 }, { 'name': 'mainField3', - 'characterSet': 'TYPE2SET', + 'characterSet': 'UTF_8', 'width': 500, 'rows': 1 }, { 'name': 'mainField4', - 'characterSet': 'TYPE2SET', + 'characterSet': 'UTF_8', 'width': 500, 'rows': 1 }, { 'name': 'statusBar', - 'characterSet': 'TYPE2SET', + 'characterSet': 'UTF_8', 'width': 500, 'rows': 1 }, { 'name': 'mediaClock', - 'characterSet': 'TYPE2SET', + 'characterSet': 'UTF_8', 'width': 500, 'rows': 1 }, { 'name': 'mediaTrack', - 'characterSet': 'TYPE2SET', + 'characterSet': 'UTF_8', 'width': 500, 'rows': 1 }, { "name": "templateTitle", - "characterSet": "TYPE2SET", + "characterSet": "UTF_8", "width": 100, "rows": 1 }, { 'name': 'alertText1', - 'characterSet': 'TYPE2SET', + 'characterSet': 'UTF_8', 'width': 500, 'rows': 1 }, { 'name': 'alertText2', - 'characterSet': 'TYPE2SET', + 'characterSet': 'UTF_8', 'width': 500, 'rows': 1 }, { 'name': 'alertText3', - 'characterSet': 'TYPE2SET', + 'characterSet': 'UTF_8', 'width': 500, 'rows': 1 }, { 'name': 'scrollableMessageBody', - 'characterSet': 'TYPE2SET', + 'characterSet': 'UTF_8', 'width': 500, 'rows': 1 }, { 'name': 'initialInteractionText', - 'characterSet': 'TYPE2SET', + 'characterSet': 'UTF_8', 'width': 500, 'rows': 1 }, { 'name': 'navigationText1', - 'characterSet': 'TYPE2SET', + 'characterSet': 'UTF_8', 'width': 500, 'rows': 1 }, { 'name': 'navigationText2', - 'characterSet': 'TYPE2SET', + 'characterSet': 'UTF_8', 'width': 500, 'rows': 1 }, { 'name': 'ETA', - 'characterSet': 'TYPE2SET', + 'characterSet': 'UTF_8', 'width': 500, 'rows': 1 }, { 'name': 'totalDistance', - 'characterSet': 'TYPE2SET', + 'characterSet': 'UTF_8', 'width': 500, 'rows': 1 }, { 'name': 'audioPassThruDisplayText1', - 'characterSet': 'TYPE2SET', + 'characterSet': 'UTF_8', 'width': 500, 'rows': 1 }, { 'name': 'audioPassThruDisplayText2', - 'characterSet': 'TYPE2SET', + 'characterSet': 'UTF_8', 'width': 500, 'rows': 1 }, { 'name': 'sliderHeader', - 'characterSet': 'TYPE2SET', + 'characterSet': 'UTF_8', 'width': 500, 'rows': 1 }, { 'name': 'sliderFooter', - 'characterSet': 'TYPE2SET', + 'characterSet': 'UTF_8', 'width': 500, 'rows': 1 }, { 'name': 'menuName', - 'characterSet': 'TYPE2SET', + 'characterSet': 'UTF_8', 'width': 500, 'rows': 1 }, { 'name': 'secondaryText', - 'characterSet': 'TYPE2SET', + 'characterSet': 'UTF_8', 'width': 500, 'rows': 1 }, { 'name': 'tertiaryText', - 'characterSet': 'TYPE2SET', + 'characterSet': 'UTF_8', 'width': 500, 'rows': 1 }, { 'name': 'menuTitle', - 'characterSet': 'TYPE2SET', + 'characterSet': 'UTF_8', 'width': 500, 'rows': 1 }, { 'name': 'locationName', - 'characterSet': 'TYPE2SET', + 'characterSet': 'UTF_8', 'width': 500, 'rows': 1 }, { 'name': 'locationDescription', - 'characterSet': 'TYPE2SET', + 'characterSet': 'UTF_8', 'width': 500, 'rows': 1 }, { 'name': 'addressLines', - 'characterSet': 'TYPE2SET', + 'characterSet': 'UTF_8', 'width': 500, 'rows': 1 }, { 'name': 'phoneNumber', - 'characterSet': 'TYPE2SET', + 'characterSet': 'UTF_8', 'width': 500, 'rows': 1 } @@ -1463,6 +1587,11 @@ FFW.UI = FFW.RPCObserver.create( 'bitsPerSample': '8_BIT', 'audioType': 'PCM' }], + "pcmStreamCapabilities": { + "samplingRate" : "16KHZ", + "bitsPerSample" : "16_BIT", + "audioType" : "PCM" + }, 'hmiZoneCapabilities': 'FRONT', 'softButtonCapabilities': [ { @@ -1481,8 +1610,6 @@ FFW.UI = FFW.RPCObserver.create( 'method': 'UI.GetCapabilities' } }; - JSONMessage.result.hmiCapabilities.steeringWheelLocation - = FLAGS.steeringWheelLocation; this.sendMessage(JSONMessage); break; } @@ -1545,13 +1672,26 @@ FFW.UI = FFW.RPCObserver.create( } case 'UI.CreateWindow': { - var app = SDL.SDLController.getApplicationModel(request.params.appID); - app.createWindow(request.params); - this.sendUIResult( - SDL.SDLModel.data.resultCode.SUCCESS, request.id, request.method - ); - let capabilites = SDL.SDLController.getDefaultCapabilities(request.params.windowID, request.params.appID); - FFW.BasicCommunication.OnSystemCapabilityUpdated(capabilites); + const resultCode = FFW.RPCHelper.getCustomResultCode(request.params.appID, 'uiCreateWindow'); + if ('DO_NOT_RESPOND' == resultCode) { + Em.Logger.log('Do not respond on this request'); + return; + } + + if (FFW.RPCHelper.isSuccessResultCode(resultCode)) { + var app = SDL.SDLController.getApplicationModel(request.params.appID); + if (app) { + app.createWindow(request.params); + + this.sendUIResult(resultCode, request.id, request.method); + + let capabilites = SDL.SDLController.getDefaultCapabilities(request.params.windowID, request.params.appID); + FFW.BasicCommunication.OnSystemCapabilityUpdated(capabilites); + } + } else { + this.sendUIResult(resultCode, request.id, request.method, 'Erroneous response is assigned by settings'); + } + break; } case 'UI.DeleteWindow': @@ -1580,25 +1720,25 @@ FFW.UI = FFW.RPCObserver.create( * id * @param {String} * method + * @param {String} + * message */ sendError: function(resultCode, id, method, message) { Em.Logger.log('FFW.' + method + 'Response'); - if (resultCode !== 0) { - - // send repsonse - var JSONMessage = { - 'jsonrpc': '2.0', - 'id': id, - 'error': { - 'code': resultCode, // type (enum) from SDL protocol - 'message': message, - 'data': { - 'method': method - } + // send response + var JSONMessage = { + 'jsonrpc': '2.0', + 'id': id, + 'error': { + 'code': resultCode, // type (enum) from SDL protocol + 'message': message, + 'data': { + 'method': method } - }; - this.sendMessage(JSONMessage); - } + } + }; + + this.sendMessage(JSONMessage); }, /** * send response from onRPCRequest @@ -1609,32 +1749,64 @@ FFW.UI = FFW.RPCObserver.create( * id * @param {String} * method + * @param {String} + * info + * @param {Object} + * params */ - sendUIResult: function(resultCode, id, method, info) { - if (this.errorResponsePull[id]) { - this.sendError( - this.errorResponsePull[id].code, id, method, - 'Unsupported ' + this.errorResponsePull[id].type + - ' type. Available data in request was processed.' - ); + sendUIResult: function(resultCode, id, method, info, params) { + const is_successful_code = FFW.RPCHelper.isSuccessResultCode(resultCode); + if (is_successful_code && this.errorResponsePull[id] != null) { + // If request was successful but some error was observed upon validation + // Then result code assigned by RPCController should be considered instead + const errorStruct = this.errorResponsePull[id]; this.errorResponsePull[id] = null; + + this.sendUIResult( + errorStruct.code, + id, + method, + `Unsupported ${errorStruct.type} type. Available data in request was processed.` + ); return; } - Em.Logger.log('FFW.' + method + 'Response'); - if (resultCode == SDL.SDLModel.data.resultCode.SUCCESS || - resultCode == SDL.SDLModel.data.resultCode.WARNINGS) { - // send repsonse + let is_successful_response_format = function(is_success) { + // Successful response without params, but with not-empty message + // should be sent in errorneous format to properly forward info and result code + if (is_success && info != null && params == null) { + return false; + } + + // Error response with not empty params should be sent in regular format + // to properly forward result code and params (but sacrifice info) + if (!is_success && params != null) { + return true; + } + + // Otherwise use result code calculated according to regular HMI logic + return is_success; + }; + + Em.Logger.log('FFW.UI.' + method + 'Response'); + if (is_successful_response_format(is_successful_code)) { + // send response var JSONMessage = { 'jsonrpc': '2.0', 'id': id, 'result': { 'code': resultCode, // type (enum) from SDL protocol 'method': method, - 'info': info } }; + + if (params != null) { + Object.assign(JSONMessage.result, params); + } + this.sendMessage(JSONMessage); + } else { + this.sendError(resultCode, id, method, info); } }, /** @@ -1671,6 +1843,58 @@ FFW.UI = FFW.RPCObserver.create( } } }, + /** + * send response from onRPCRequest + * + * @param {Number} + * resultCode + * @param {Number} + * rpc id + * @param {String} + * info to send w response + * @param {Number} + * tryAgainTime + */ + subtleAlertResponse: function(resultCode, id, info, tryAgainTime) { + switch (resultCode) { + case SDL.SDLModel.data.resultCode.WARNINGS: + case SDL.SDLModel.data.resultCode.SUCCESS: + { + if (SDL.TTSPopUp.active) { + SDL.TTSPopUp.DeactivateTTS(); + } + this.sendUIResult(resultCode, id, 'UI.SubtleAlert', info); + break; + } + case SDL.SDLModel.data.resultCode.REJECTED: + { + this.sendUIResult(resultCode, id, 'UI.SubtleAlert', info, { tryAgainTime: tryAgainTime }); + break; + } + case SDL.SDLModel.data.resultCode.ABORTED: + { + this.sendUIResult(resultCode, id, 'UI.SubtleAlert', 'SubtleAlert request aborted.'); + break; + } + } + }, + /** + * send notification for OnSubtleAlertPressed + * + * @param {Number} + * appID + */ + onSubtleAlertPressed: function(appID) { + Em.Logger.log('FFW.UI.OnSubtleAlertPressed'); + var JSONMessage = { + 'jsonrpc': '2.0', + 'method': 'UI.OnSubtleAlertPressed', + 'params': { + 'appID': appID + } + }; + this.sendMessage(JSONMessage); + }, /** * send response from onRPCRequest * @@ -1959,6 +2183,45 @@ FFW.UI = FFW.RPCObserver.create( } }; this.sendMessage(JSONMessage); + }, + /** + * Callback for requesting images from mobile application + * + * @param {integer} + * appID + * @param {string} + * fileName + */ + OnUpdateFile: function(appID, fileName) { + var JSONMessage = { + 'jsonrpc': '2.0', + 'method': 'UI.OnUpdateFile', + 'params': { + 'appID': appID, + 'fileName': fileName + } + }; + this.sendMessage(JSONMessage); + }, + /** + * Callback for requesting submenu contents from mobile application + * + * @param {integer} + * appID + * @param {integer} + * menuID + */ + OnUpdateSubMenu: function(appID, menuID) { + var JSONMessage = { + 'jsonrpc': '2.0', + 'method': 'UI.OnUpdateSubMenu', + 'params': { + 'appID': appID, + 'menuID': menuID, + 'updateSubCells': true + } + }; + this.sendMessage(JSONMessage); } } ); diff --git a/ffw/VRRPC.js b/ffw/VRRPC.js index 1e822cab6..d72b6417a 100644 --- a/ffw/VRRPC.js +++ b/ffw/VRRPC.js @@ -127,17 +127,43 @@ FFW.VR = FFW.RPCObserver.create( /* * handle RPC requests here */ + checkRequestType: function(type){ + switch(type){ + case 'Command': + return 'vrAddCommand'; + case 'Choice': + return 'createInteractionChoiceSet'; + default: return ''; + } + }, + onRPCRequest: function(request) { Em.Logger.log('FFW.VR.onRPCRequest'); if (this.validationCheck(request)) { switch (request.method) { case 'VR.AddCommand': { - SDL.SDLModel.addCommandVR(request.params); + var key = this.checkRequestType(request.params.type); + result = FFW.RPCHelper.getCustomResultCode(request.params.appID, key); + + if ('DO_NOT_RESPOND' == result) { + Em.Logger.log('Do not respond on this request'); + return; + } + + let info = null; + + if(FFW.RPCHelper.isSuccessResultCode(result)){ + SDL.SDLModel.addCommandVR(request.params); + } else { + info = 'Erroneous response is assigned by settings'; + } + this.sendVRResult( - SDL.SDLModel.data.resultCode.SUCCESS, + result, request.id, - request.method + request.method, + info ); break; } @@ -273,22 +299,19 @@ FFW.VR = FFW.RPCObserver.create( */ sendError: function(resultCode, id, method, message) { Em.Logger.log('FFW.' + method + 'Response'); - if (resultCode != SDL.SDLModel.data.resultCode.SUCCESS) { - - // send repsonse - var JSONMessage = { - 'jsonrpc': '2.0', - 'id': id, - 'error': { - 'code': resultCode, // type (enum) from SDL protocol - 'message': message, - 'data': { - 'method': method - } + // send response + var JSONMessage = { + 'jsonrpc': '2.0', + 'id': id, + 'error': { + 'code': resultCode, // type (enum) from SDL protocol + 'message': message, + 'data': { + 'method': method } - }; - this.sendMessage(JSONMessage); - } + } + }; + this.sendMessage(JSONMessage); }, /** * send notification when command was triggered @@ -361,21 +384,46 @@ FFW.VR = FFW.RPCObserver.create( * id * @param {String} * method + * @param {String} + * info */ - sendVRResult: function(resultCode, id, method) { - if (this.errorResponsePull[id]) { - this.sendError( - this.errorResponsePull[id].code, id, method, - 'Unsupported ' + this.errorResponsePull[id].type + - ' type. Available data in request was processed.' - ); + sendVRResult: function(resultCode, id, method, info, params) { + const is_successful_code = FFW.RPCHelper.isSuccessResultCode(resultCode); + if (is_successful_code && this.errorResponsePull[id] != null) { + // If request was successful but some error was observed upon validation + // Then result code assigned by RPCController should be considered instead + const errorStruct = this.errorResponsePull[id]; this.errorResponsePull[id] = null; + + this.sendVRResult( + errorStruct.code, + id, + method, + `Unsupported ${errorStruct.type} type. Available data in request was processed.` + ); return; } - Em.Logger.log('FFW.' + method + 'Response'); - if (resultCode === SDL.SDLModel.data.resultCode.SUCCESS) { - // send repsonse + let is_successful_response_format = function(is_success) { + // Successful response without params, but with not-empty message + // should be sent in errorneous format to properly forward info and result code + if (is_success && info != null && params == null) { + return false; + } + + // Error response with not empty params should be sent in regular format + // to properly forward result code and params (but sacrifice info) + if (!is_success && params != null) { + return true; + } + + // Otherwise use result code calculated according to regular HMI logic + return is_success; + }; + + Em.Logger.log('FFW.VR.' + method + 'Response'); + if (is_successful_response_format(is_successful_code)) { + // send response var JSONMessage = { 'jsonrpc': '2.0', 'id': id, @@ -384,7 +432,14 @@ FFW.VR = FFW.RPCObserver.create( 'method': method } }; + + if (params != null) { + Object.assign(JSONMessage.result, params); + } + this.sendMessage(JSONMessage); + } else { + this.sendError(resultCode, id, method, info); } }, /* diff --git a/ffw/VehicleInfoRPC.js b/ffw/VehicleInfoRPC.js index 0b8484423..f80d1f1dd 100644 --- a/ffw/VehicleInfoRPC.js +++ b/ffw/VehicleInfoRPC.js @@ -224,22 +224,19 @@ FFW.VehicleInfo = FFW.RPCObserver.create( */ sendError: function(resultCode, id, method, message) { Em.Logger.log('FFW.' + method + 'Response'); - if (resultCode != SDL.SDLModel.data.resultCode.SUCCESS) { - - // send repsonse - var JSONMessage = { - 'jsonrpc': '2.0', - 'id': id, - 'error': { - 'code': resultCode, // type (enum) from SDL protocol - 'message': message, - 'data': { - 'method': method - } + // send response + var JSONMessage = { + 'jsonrpc': '2.0', + 'id': id, + 'error': { + 'code': resultCode, // type (enum) from SDL protocol + 'message': message, + 'data': { + 'method': method } - }; - this.sendMessage(JSONMessage); - } + } + }; + this.sendMessage(JSONMessage); }, /** * Send response from onRPCRequest @@ -250,21 +247,62 @@ FFW.VehicleInfo = FFW.RPCObserver.create( * id * @param {String} * method + * @param {String} + * info */ - sendVIResult: function(resultCode, id, method) { - Em.Logger.log('FFW.' + method + 'Response'); - if (resultCode === SDL.SDLModel.data.resultCode.SUCCESS) { + sendVIResult: function(resultCode, id, method, info, params) { + const is_successful_code = FFW.RPCHelper.isSuccessResultCode(resultCode); + if (is_successful_code && this.errorResponsePull[id] != null) { + // If request was successful but some error was observed upon validation + // Then result code assigned by RPCController should be considered instead + const errorStruct = this.errorResponsePull[id]; + this.errorResponsePull[id] = null; - // send repsonse + this.sendVIResult( + errorStruct.code, + id, + method, + `Unsupported ${errorStruct.type} type. Available data in request was processed.` + ); + return; + } + + let is_successful_response_format = function(is_success) { + // Successful response without params, but with not-empty message + // should be sent in errorneous format to properly forward info and result code + if (is_success && info != null && params == null) { + return false; + } + + // Error response with not empty params should be sent in regular format + // to properly forward result code and params (but sacrifice info) + if (!is_success && params != null) { + return true; + } + + // Otherwise use result code calculated according to regular HMI logic + return is_success; + }; + + Em.Logger.log('FFW.VI.' + method + 'Response'); + if (is_successful_response_format(is_successful_code)) { + // send response var JSONMessage = { 'jsonrpc': '2.0', 'id': id, 'result': { - 'code': resultCode, + 'code': resultCode, // type (enum) from SDL protocol 'method': method } }; + + if (params != null) { + Object.assign(JSONMessage.result, params); + } + this.sendMessage(JSONMessage); + } else { + this.sendError(resultCode, id, method, info); } }, /** @@ -277,17 +315,20 @@ FFW.VehicleInfo = FFW.RPCObserver.create( */ sendVISubscribeVehicleDataResult: function(resultCode, id, method, data) { Em.Logger.log('FFW.' + method + 'Response'); + if (FFW.RPCHelper.isSuccessResultCode(resultCode)) { - // send repsonse - var JSONMessage = { - 'jsonrpc': '2.0', - 'id': id, - 'result': data - }; - - JSONMessage.result.code = resultCode; - JSONMessage.result.method = method; - this.sendMessage(JSONMessage); + // send repsonse + var JSONMessage = { + 'jsonrpc': '2.0', + 'id': id, + 'result': data, + }; + JSONMessage.result.code = resultCode; + JSONMessage.result.method = method; + this.sendMessage(JSONMessage); + } else { + this.sendGetVehicleDataError(resultCode, id, method,'Erroneous response is assigned by settings', data); + } }, /** * Send error response from onRPCRequest diff --git a/images/home/controlButtons/PlayPauseButton.png b/images/home/controlButtons/PlayPauseButton.png new file mode 100644 index 000000000..4541786f2 Binary files /dev/null and b/images/home/controlButtons/PlayPauseButton.png differ diff --git a/images/home/controlButtons/PlayPauseButton_pressed.png b/images/home/controlButtons/PlayPauseButton_pressed.png new file mode 100644 index 000000000..d5accf641 Binary files /dev/null and b/images/home/controlButtons/PlayPauseButton_pressed.png differ diff --git a/index.html b/index.html index ddb9bd338..67b62bcd1 100644 --- a/index.html +++ b/index.html @@ -9,6 +9,7 @@ + @@ -46,6 +47,7 @@ + @@ -238,6 +240,18 @@ + + + + + + + + @@ -249,6 +263,7 @@ + @@ -288,6 +303,7 @@ +