diff --git a/platypush/backend/http/static/css/source/common/modal.scss b/platypush/backend/http/static/css/source/common/modal.scss index c9f5edd0..1f35afe7 100644 --- a/platypush/backend/http/static/css/source/common/modal.scss +++ b/platypush/backend/http/static/css/source/common/modal.scss @@ -16,8 +16,17 @@ width: var(--width); height: var(--height); - div:first-child { border-radius: 1rem 1rem 0 0; } - div:last-child { border-radius: 0 0 1rem 1rem; } + .header { + border-radius: 1rem 1rem 0 0; + } + + .body:first-child { + border-radius: 1rem; + } + + .body:not(first-child) { + border-radius: 0 0 1rem 1rem; + } .header { border-bottom: $modal-header-border; diff --git a/platypush/backend/http/static/css/source/webpanel/plugins/assistant.google/index.scss b/platypush/backend/http/static/css/source/webpanel/plugins/assistant.google/index.scss new file mode 100644 index 00000000..64cec730 --- /dev/null +++ b/platypush/backend/http/static/css/source/webpanel/plugins/assistant.google/index.scss @@ -0,0 +1,34 @@ +$icon-color: #7e8; +$icon-border: 1px solid #ccc; +$icon-shadow: 2px 2px 2px #ccc; + +#assistant-google-modal { + .modal { + width: 50vw; + height: 50vh; + + .body { + width: 100%; + height: 100%; + display: flex; + align-items: center; + justify-content: center; + flex-direction: column; + text-align: center; + + .icon { + font-size: 3em; + color: $icon-color; + box-shadow: $icon-shadow; + border: $icon-border; + border-radius: 3em; + padding: .7em 1em .5em 1em; + } + + .text { + margin-top: 2.5em; + } + } + } +} + diff --git a/platypush/backend/http/static/js/events.js b/platypush/backend/http/static/js/events.js index b918a664..3d96bee3 100644 --- a/platypush/backend/http/static/js/events.js +++ b/platypush/backend/http/static/js/events.js @@ -117,3 +117,13 @@ function registerEventHandler(handler, ...events) { } } +function onReady(handler) { + if (document.readyState === "complete" || document.readyState === "loaded") { + handler(); + } else { + document.addEventListener("DOMContentLoaded", () => { + handler(); + }, false); + } +} + diff --git a/platypush/backend/http/static/js/plugins/assistant.google/index.js b/platypush/backend/http/static/js/plugins/assistant.google/index.js new file mode 100644 index 00000000..4ed37e15 --- /dev/null +++ b/platypush/backend/http/static/js/plugins/assistant.google/index.js @@ -0,0 +1,114 @@ +const Assistant = Vue.extend({ + template: ` + +
+ + + + +
+ +
+
+ Assistant listening +
+
+ +
+
+ +
+
+
+ `, + + data: function() { + return { + responseText: '', + phrase: '', + visible: false, + + state: { + listening: false, + speechRecognized: false, + responding: false, + alerting: false, + }, + }; + }, + + methods: { + reset: function() { + this.state.listening = false; + this.state.speechRecognized = false; + this.state.responding = false; + this.state.alerting = false; + this.phrase = ''; + this.responseText = ''; + }, + + conversationStart: function() { + this.reset(); + this.state.listening = true; + this.visible = true; + }, + + conversationEnd: function() { + this.reset(); + this.visible = false; + }, + + speechRecognized: function(event) { + this.reset(); + this.state.speechRecognized = true; + this.phrase = event.phrase; + this.visible = true; + }, + + response: function(event) { + this.reset(); + this.state.responding = true; + this.responseText = event.response_text; + this.visible = true; + }, + + alertOn: function() { + this.reset(); + this.state.alerting = true; + this.visible = true; + }, + + alertOff: function() { + this.reset(); + this.state.alerting = false; + this.visible = false; + }, + + registerHandlers: function() { + registerEventHandler(this.conversationStart, 'platypush.message.event.assistant.ConversationStartEvent'); + registerEventHandler(this.conversationStart, 'platypush.message.event.assistant.HotwordDetectedEvent'); + registerEventHandler(this.alertOn, 'platypush.message.event.assistant.AlertStartedEvent'); + registerEventHandler(this.alertOff, 'platypush.message.event.assistant.AlertEndEvent'); + registerEventHandler(this.speechRecognized, 'platypush.message.event.assistant.SpeechRecognizedEvent'); + registerEventHandler(this.response, 'platypush.message.event.assistant.ResponseEvent'); + registerEventHandler(this.conversationEnd, 'platypush.message.event.assistant.ConversationEndEvent'); + registerEventHandler(this.conversationEnd, 'platypush.message.event.assistant.NoResponseEvent'); + registerEventHandler(this.conversationEnd, 'platypush.message.event.assistant.ConversationTimeoutEvent'); + }, + }, + + mounted: function() { + this.registerHandlers(); + }, +}); + +onReady(() => { + const container = document.createElement('div'); + const containerId = 'assistant-google-container'; + + container.setAttribute('id', containerId); + document.querySelector('#app').appendChild(container); + + new Assistant().$mount('#' + containerId); +}); +