Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initial React GUI support #26

Draft
wants to merge 11 commits into
base: dev
Choose a base branch
from
7 changes: 5 additions & 2 deletions ovos_gui/bus.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,6 @@ def open(self):
"""
GUIWebsocketHandler.clients.append(self)
LOG.info('New Connection opened!')
self.synchronize()

def on_close(self):
"""
Expand Down Expand Up @@ -221,12 +220,16 @@ def on_message(self, message: str):
if framework is None:
# mycroft-gui api
qt = msg_data.get("qt_version") or default_qt_version
LOG.debug(f"Backwards-compat handling for qt{qt} client")
if int(qt) == 6:
framework = "qt6"
else:
framework = "qt5"

LOG.info(f"New connection for framework: {framework}")
self._framework = framework

# sync after we've determined what framework this GUI uses
self.synchronize()
else:
# message not in spec
# https://github.com/MycroftAI/mycroft-gui/blob/master/transportProtocol.md
Expand Down
28 changes: 28 additions & 0 deletions ovos_gui/namespace.py
Original file line number Diff line number Diff line change
Expand Up @@ -494,6 +494,26 @@ def _define_message_handlers(self):
"""
Defines event handlers for core messagebus.
"""
# Audio Service
self.core_bus.on("recognizer_loop:audio_output_start",
self.forward_to_gui)
self.core_bus.on("recognizer_loop:audio_output_end",
self.forward_to_gui)

# Speech Service
self.core_bus.on("recognizer_loop:sleep", self.forward_to_gui)
self.core_bus.on("recognizer_loop:wake_up", self.forward_to_gui)
self.core_bus.on("recognizer_loop:wakeword", self.forward_to_gui)
self.core_bus.on("recognizer_loop:recognition_unknown", self.forward_to_gui)
self.core_bus.on("recognizer_loop:record_begin", self.forward_to_gui)
self.core_bus.on("recognizer_loop:record_end", self.forward_to_gui)

# Enclosure Service
self.core_bus.on("enclosure.mouth.viseme_list", self.forward_to_gui)
# TODO: Add other enclosure events

# self.core_bus.on("mycroft.gui.port", self.forward_to_gui)

NeonDaniel marked this conversation as resolved.
Show resolved Hide resolved
self.core_bus.on("gui.clear.namespace", self.handle_clear_namespace)
self.core_bus.on("gui.event.send", self.handle_send_event)
self.core_bus.on("gui.page.delete", self.handle_delete_page)
Expand All @@ -506,6 +526,14 @@ def _define_message_handlers(self):
self.core_bus.on("gui.page_gained_focus", self.handle_page_gained_focus)
self.core_bus.on("mycroft.skills.trained", self.handle_ready)

@staticmethod
def forward_to_gui(message: Message):
"""
Forward a core Message to the GUI
@param message: Core message to forward
"""
send_message_to_gui(message.as_dict)

def handle_ready(self, message):
self._ready_event.set()
self.core_bus.on("gui.volunteer_page_upload",
Expand Down
10 changes: 7 additions & 3 deletions ovos_gui/page.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from os.path import join, isfile, dirname
from typing import Union, Optional
from dataclasses import dataclass
from ovos_utils.log import LOG
from ovos_utils.log import LOG, log_deprecation


@dataclass
Expand Down Expand Up @@ -44,6 +44,8 @@ def get_file_extension(framework: str) -> str:
"""
if framework in ("qt5", "qt6"):
return "qml"
if framework == "react":
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are there different versions or flavors we should support here?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe vue?

return "jsx"
return ""

def get_uri(self, framework: str = "qt5", server_url: str = None) -> str:
Expand All @@ -66,9 +68,11 @@ def get_uri(self, framework: str = "qt5", server_url: str = None) -> str:
if server_url.startswith("/"):
LOG.debug(f"No schema in server_url, assuming 'file'")
server_url = f"file://{server_url}"
else:
LOG.debug(f"No schema in server_url, assuming 'http'")
elif ':' in server_url: # looks like host:port
log_deprecation(f"No schema in server_url, assuming 'http'",
"0.1.0")
server_url = f"http://{server_url}"
# React will use a path alias like `gui/`
path = f"{server_url}/{res_namespace}/{framework}/{res_filename}"
LOG.info(f"Resolved server URI: {path}")
return path
Expand Down
37 changes: 37 additions & 0 deletions ovos_gui/res/gui/react/SYSTEM_AnimatedImageFrame.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import React from "react";
import { ContentElement } from "CORE/utils";

function RenderPage(props) {
const skill_props = props.skillState;
console.log(skill_props)
return (
<div className="h-aligned-container text-center"
style={{justifyContent: "center",
alignItems: "center",
left: "1%",
right: "1%"}}>
<ContentElement
elementType="TextFrame"
id="title"
className="col-12 h2"
text={skill_props["title"] || null}
duration={15000}
/>
<ContentElement
elementType="ImageFrame"
id={"image"}
className="col-12"
src={skill_props["image"] || null}
duration={15000}
/>
<ContentElement
elementType="TextFrame"
className="col-12 h4"
text={skill_props["caption"] || null}
duration={15000}
/>
</div>
);
}

export default RenderPage
37 changes: 37 additions & 0 deletions ovos_gui/res/gui/react/SYSTEM_ImageFrame.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import React from "react";
import { ContentElement } from "CORE/utils";

function RenderPage(props) {
const skill_props = props.skillState;
console.log(skill_props)
return (
<div className="h-aligned-container text-center"
style={{justifyContent: "center",
alignItems: "center",
left: "1%",
right: "1%"}}>
<ContentElement
elementType="TextFrame"
id="title"
className="col-12 h2"
text={skill_props["title"] || null}
duration={15000}
/>
<ContentElement
elementType="ImageFrame"
id={"image"}
className="col-12"
src={skill_props["image"] || null}
duration={15000}
/>
<ContentElement
elementType="TextFrame"
className="col-12 h4"
text={skill_props["caption"] || null}
duration={15000}
/>
</div>
);
}

export default RenderPage
35 changes: 35 additions & 0 deletions ovos_gui/res/gui/react/SYSTEM_TextFrame.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import React from "react";
import { ContentElement } from "CORE/utils";

function RenderPage(props) {
const skill_props = props.skillState;
console.log(skill_props)
return (
<div className="h-aligned-container text-center"
style={{justifyContent: "center",
alignItems: "center",
left: "1%",
right: "1%"}}>
<ContentElement
elementType={"TextFrame"}
id={"title"}
className={"col-12 h1"}
text={skill_props.title}
display={skill_props.display}
duration={15000}
// TODO: duration from config
/>
<ContentElement
elementType={"TextFrame"}
id={"text"}
className={"col-12 h3"}
text={skill_props.text}
display={skill_props.display}
duration={15000}
// TODO: duration from config
/>
</div>
);
}

export default RenderPage
Loading