Skip to content

Commit

Permalink
Consent & GetUserFriendlyMessage (#406)
Browse files Browse the repository at this point in the history
* add consent prompts, toast notifications, get user friendly message, app permissions view, include bootstrap, handle OnAppPermissionChanged, refactor tts controller so HMI can easily queue tts

* improve applist header icons

* GUFM response.result.messages param may be omitted

* replace consumer friendly message variables with proper values

* minor styling improvements

* remove menu icon from app permissions list

* address review comments: data consent before permissions, chain views, activate app once

* remove activate app when permissions consent

* consumer friendly message tts api parameter is called ttsString

* rename AppPermissionList to PermissionAppList to make it more clear that is the list of apps

* get revoked app name before waiting for GUFM response (while its still in app list)

* reply to TTS Speak correctly even when internal TTS is being used

* fixup! rename AppPermissionList to PermissionAppList to make it more clear that is the list of apps

fix links to renamed page

* handle ActivateApp request parameter level

* address review comment: fix warning

* address review comment: add comment explaining filePlaylist type REPLY

* nullcheck editing permissions app

* fix AppPermissionsRevoked tts

* handle app unregister while editing permissions

* fix AppPermissions prop name typo
  • Loading branch information
iCollin authored Jul 6, 2021
1 parent 76bd860 commit d97cbc0
Show file tree
Hide file tree
Showing 23 changed files with 712 additions and 154 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"rc-slider": "^9.7.2",
"react": "^16.13.1",
"react-dom": "^16.13.1",
"react-hot-toast": "^2.0.0",
"react-modal": "^3.11.2",
"react-redux": "^7.2.0",
"react-router": "^5.2.0",
Expand Down
1 change: 1 addition & 0 deletions public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
<head>
<meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-+0n0xVW2eSR5OomGNYDnhzAbDsOXxcvSN1TPprVMTNDbiYZCxYbOOl7+AMvyTG2x" crossorigin="anonymous">
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta
Expand Down
9 changes: 9 additions & 0 deletions src/css/base/_themes.scss
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@
background: color($primary-color);
}

.app-bg-color {
background: color($primary-color);
}


.app__header {
background-image: -webkit-linear-gradient(color($secondary-color), color($primary-color));
background-image: -o-linear-gradient(color($secondary-color), color($primary-color));
Expand Down Expand Up @@ -88,6 +93,10 @@
background: color(glass);
}

.app-bg-color {
background: color(glass);
}

.app__header {
background-image: -webkit-linear-gradient(to bottom, #ffffff, rgba(255, 255, 255, 0.0));
background-image: -o-linear-gradient(to bottom, #ffffff, rgba(255, 255, 255, 0.0));
Expand Down
66 changes: 66 additions & 0 deletions src/css/components/_permissions-popup.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
.permissionsPopup {
@include display(flex);
@include flex-direction(row);
@include justify-content(space-between);
border: 1px solid #ccc;
overflow: auto;
-webkit-overflow-scrolling: 'touch';
border-radius: 4px;
outline: none;
width: 90%;
height: 30%;
}

.permissionsPopup-top {
@include display(flex);
@include justify-content(space-between);
@include flex-direction(column);
padding: 10px;
height: auto;
overflow-y: scroll;
flex-grow: 4;

h3 {
word-wrap: normal;
}
}

.permissionsPopup-buttons {
@include display(flex);
@include justify-content(space-around);
@include flex-direction(column);
@include flex-wrap(wrap);
@include align-items(stretch);
padding: 2%;
min-width: 20%;
}

.permissionsPopup-button {
flex: 1;
max-height: 50px;
height: 40px;
text-align: center;
border-radius: 8px;
border-width: 0.154px;
border-style: solid;
padding: 2%;
width: auto;

display: flex;
align-items: center;
justify-content: center;
}


.permissionsToggle {
height: 100%;
display: flex;
justify-content: center;
align-items: center;
margin-left: 20px;
margin-right: 20px;

input {
height: 40px;
}
}
6 changes: 3 additions & 3 deletions src/css/components/_subtle-alert.scss
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
left : 0;
right : 0;
bottom : 0;
background-color : rgba(0, 0, 0, 0.5);
background-color : rgba(0, 0, 0, 0);
width: $master-width;
height: $master-height;
margin: 25px;
Expand Down Expand Up @@ -46,8 +46,8 @@
overflow: hidden;
text-overflow: ellipsis;
max-width: 100%;
line-height: 1.5em;
height: 1.5em;
line-height: 1.25em;
height: 1.25em;
//max-width: calc(#{$master-width} * 0.55);
}

Expand Down
1 change: 1 addition & 0 deletions src/css/main.scss
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,5 @@
@import 'components/appstore-menu';
@import 'components/keyboard';
@import 'components/scrollable_message';
@import 'components/permissions-popup';

2 changes: 1 addition & 1 deletion src/img/icons/icon-cart.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
28 changes: 27 additions & 1 deletion src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ import InAppList from './js/InAppList';
import AppStore from './js/AppStore';
import AppStoreMenu from './js/AppStoreMenu';
import WebEngineAppContainer from './js/WebEngineAppContainer';
import AppPermissions from './js/AppPermissions';
import PermissionAppList from './js/PermissionAppList';
import Keyboard from './js/Keyboard';
import React from 'react';
import ReactDOM from 'react-dom';
Expand All @@ -34,6 +36,7 @@ import { Route, HashRouter } from 'react-router-dom'

import { Provider } from 'react-redux'
import store from './js/store'
import { Toaster } from 'react-hot-toast';

import Controller from './js/Controllers/Controller'
import FileSystemController from './js/Controllers/FileSystemController';
Expand Down Expand Up @@ -184,10 +187,31 @@ class HMIApp extends React.Component {
<div>
<div className={themeClass}>
<div className="app-body">
<Toaster position='top-center'
containerStyle={{
maxHeight: config.masterHeight,
overflowY: 'scroll',
overflowX: 'hidden',
marginTop: 10,
marginLeft: 10,
paddingTop: 10
}}
toastOptions={{ style: {
left: 0,
position: 'relative',
top: 0,
width: config.masterWidth,
backgroundColor: '#11111100',
maxWidth: '100%',
boxShadow: 'none',
marginRight: 'auto',
marginTop: 10,
padding: 0
} }}/>
{this.props.children}
</div>
</div>
<div>
<div>
<div className="toggle-button" onClick={this.handleClick}>Toggle theme</div>
<div className="shutdown-button" onClick={this.handleShutdown}>Shutdown</div>
<div className="toggle-ptu-with-modem-button" >
Expand Down Expand Up @@ -320,6 +344,8 @@ ReactDOM.render((
<Route path="/appstore" component={AppStore} />
<Route path="/appstoremenu" component={AppStoreMenu} />
<Route path="/keyboard" component={Keyboard} />
<Route path="/permissionapplist" component={PermissionAppList} />
<Route path="/apppermissions" component={AppPermissions} />
</HashRouter>
</HMIApp>
</Provider>
Expand Down
25 changes: 20 additions & 5 deletions src/js/AppHeader.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,24 +9,34 @@ import MenuIcon from './containers/MenuIcon';
import Name from './containers/Name';
import MenuLink from './containers/AppsButton'
import store from './store'
import {resetShowAppMenu} from './actions'
import {resetOpenPermissionsView, resetShowAppMenu} from './actions'
import { connect } from 'react-redux'
import { Link } from 'react-router-dom';
import uiController from './Controllers/UIController'
import ScrollableMessage from './ScrollableMessage';

import {ReactComponent as IconMenu} from '../img/icons/icon-menu.svg'
import {ReactComponent as IconCart} from '../img/icons/icon-cart.svg'
import {ReactComponent as PermissionsIcon} from '../img/static/0x49.svg'

class AppStoreIcon extends React.Component {
render() {
return (<div>
<Link to="/appstore">
return (<div style={{ display: 'flex', flexDirection: 'row', alignItems: 'center' }}>
<Link to="/permissionapplist" style={{ marginRight: 10, marginLeft: 'auto' }}>
<div className="app-icon">
<div className="static-icon">
<div className="svg-wrap">
<PermissionsIcon/>
</div>
</div>
</div>
</Link>
<Link to="/appstore" style={{ marginRight: 0 }}>
<div className="app-icon">
<div className="static-icon">
<span className="svg-wrap">
<div className="svg-wrap">
<IconCart/>
</span>
</div>
</div>
</div>
</Link>
Expand Down Expand Up @@ -114,6 +124,8 @@ class AppHeader extends React.Component {
else{
icon = (<div />)
}
} else if (this.props.icon === 'custom') {
icon = this.props.jsxIcon;
}

var colorScheme = null;
Expand Down Expand Up @@ -243,6 +255,9 @@ class AppHeader extends React.Component {
}
}
store.dispatch(resetShowAppMenu(nextProps.activeApp))
} else if (nextProps.openPermissionsView) {
store.dispatch(resetOpenPermissionsView());
this.props.history.push('/apppermissions');
}

}
Expand Down
105 changes: 105 additions & 0 deletions src/js/AppPermissions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
import React from 'react';
import { connect } from 'react-redux'
import { withRouter } from 'react-router-dom';

import AppHeader from './containers/Header';
import sdlController from './Controllers/SDLController';
import { Link } from 'react-router-dom';
import store from './store';
import { closePermissionsView, clearAppAwaitingPermissions } from './actions'

const mapStateToProps = (state) => {
var theme = state.theme
var editingAppID = state.system.editingPermissionsAppId;
var allowedFunctions = state.system.allowedFunctions;
var pendingActivation = state.system.permissionsAppAwaitingActivation;

return {
theme: theme,
editingAppID: editingAppID,
allowedFunctions: allowedFunctions,
activeLayout: state.ui[editingAppID]?.displayLayout,
appOptions: state.appList,
pendingActivation: pendingActivation
};
}

class Permissions extends React.Component {
constructor(props) {
super(props);

this.toggleFunction = this.toggleFunction.bind(this);
this.savePermissions = this.savePermissions.bind(this);

this.state = {
allowedFunctions: props.allowedFunctions,
appWasDisconnected: false
}
}

componentWillReceiveProps(nextProps) {
if (false === this.state.appWasDisconnected && undefined === nextProps.editingAppID) {
this.setState({ appWasDisconnected: true });
this.props.history.push("/permissionapplist");
}
}

toggleFunction(name) {
var functions = [ ...this.state.allowedFunctions ]
for (var f of functions) {
if (f.name === name) {
f.allowed = !f.allowed;
this.setState({ allowedFunctions: functions });
return;
}
}
}

savePermissions() {
var allowedFunctions = this.state.allowedFunctions.map((f) => ({
id: f.id, name: f.name, allowed: f.allowed
}));
sdlController.onAppPermissionConsent(this.props.editingAppID, allowedFunctions);

if (this.props.pendingActivation === this.props.editingAppID) {
store.dispatch(clearAppAwaitingPermissions());
}
}

componentWillUnmount() {
store.dispatch(closePermissionsView());
}

render() {
var options =this.state.allowedFunctions.map((f) => (
<div className="vscrollmenu-item th-b-color th-bb-color-secondary" key={f.id}
onClick={(e) => this.toggleFunction(f.name)} style={{ height: 'auto' }}>
<div className={"vscrollmenu-item__primary th-f-color"}>
<div class="form-check form-switch permissionsToggle">
<input class="form-check-input" type="checkbox" checked={f.allowed} style={{ width: '5em' }} />
</div>
<div className={"vscrollmenu-item__name th-f-color"} style={{ marginRight: '2%' }}>
<p class="t-large t-light th-f-color">{f.title || f.name}</p>
<p className="t-small t-light th-f-color-secondary">{f.body}</p>
</div>
</div>
</div>
));

return (
<div>
<AppHeader backLink={'/permissionapplist'} menuName="Back"
icon='custom'
jsxIcon={<div><Link to={this.props.pendingActivation === this.props.editingAppID?this.props.activeLayout:'/'}
className="t-small t-medium th-f-color t-ls1"
onClick={() => { this.savePermissions(); }}>SAVE</Link></div>} />
<div className="vscrollmenu">
{ options }
</div>
</div>
)
}
}

const PermissionsView = connect(mapStateToProps)(Permissions);
export default withRouter(PermissionsView);
6 changes: 5 additions & 1 deletion src/js/Controllers/BCController.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,11 @@ class BCController {
return true
case "ActivateApp":
store.dispatch(setAppIsConnected(rpc.params.appID))
store.dispatch(activateApp(rpc.params.appID))
if (!rpc.params.level || rpc.params.level === 'FULL') {
store.dispatch(activateApp(rpc.params.appID));
} else {
store.dispatch(deactivateApp(rpc.params.appID));
}
return true
case "CloseApplication":
store.dispatch(deactivateApp(rpc.params.appID, "APP_CLOSED"))
Expand Down
1 change: 1 addition & 0 deletions src/js/Controllers/Controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ export default class Controller {
this.subscribeToNotification("Navigation.OnVideoDataStreaming")
this.subscribeToNotification("Navigation.OnAudioDataStreaming")
this.subscribeToNotification("SDL.OnStatusUpdate")
this.subscribeToNotification("SDL.OnAppPermissionChanged")
this.subscribeToNotification("BasicCommunication.OnSystemCapabilityUpdated")
this.subscribeToNotification("AppService.OnAppServiceData")
this.subscribeToNotification("BasicCommunication.OnAppCapabilityUpdated")
Expand Down
Loading

0 comments on commit d97cbc0

Please sign in to comment.