From 72e14a32f9d4c9b468429435bfa66954a61f1bb4 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Wed, 7 Aug 2019 17:13:20 -0400 Subject: [PATCH] Implement the Help App skeleton; Implement Help App Controls; Implement Help App About --- .../qml/hifi/simplifiedUI/helpApp/HelpApp.qml | 154 ++++++++ .../simplifiedUI/helpApp/about/HelpAbout.qml | 359 ++++++++++++++++++ .../helpApp/controls/HelpControls.qml | 91 +++++ .../simplifiedUI/helpApp/images/accent1.svg | 4 + .../simplifiedUI/helpApp/images/accent2.svg | 4 + .../simplifiedUI/helpApp/images/accent3.svg | 4 + .../simplifiedUI/topBar/SimplifiedTopBar.qml | 44 ++- scripts/simplifiedUI/ui/simplifiedUI.js | 69 ++++ 8 files changed, 728 insertions(+), 1 deletion(-) create mode 100644 interface/resources/qml/hifi/simplifiedUI/helpApp/HelpApp.qml create mode 100644 interface/resources/qml/hifi/simplifiedUI/helpApp/about/HelpAbout.qml create mode 100644 interface/resources/qml/hifi/simplifiedUI/helpApp/controls/HelpControls.qml create mode 100644 interface/resources/qml/hifi/simplifiedUI/helpApp/images/accent1.svg create mode 100644 interface/resources/qml/hifi/simplifiedUI/helpApp/images/accent2.svg create mode 100644 interface/resources/qml/hifi/simplifiedUI/helpApp/images/accent3.svg diff --git a/interface/resources/qml/hifi/simplifiedUI/helpApp/HelpApp.qml b/interface/resources/qml/hifi/simplifiedUI/helpApp/HelpApp.qml new file mode 100644 index 0000000000..59d0caf30a --- /dev/null +++ b/interface/resources/qml/hifi/simplifiedUI/helpApp/HelpApp.qml @@ -0,0 +1,154 @@ +// +// HelpApp.qml +// +// Created by Zach Fox on 2019-08-07 +// Copyright 2019 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +import QtQuick 2.10 +import QtQuick.Controls 2.3 +import "../simplifiedConstants" as SimplifiedConstants +import "../simplifiedControls" as SimplifiedControls +import stylesUit 1.0 as HifiStylesUit +import "./controls" as HelpControls +import "./about" as HelpAbout + +Rectangle { + property string activeTabView: "controlsTabView" + id: root + color: simplifiedUI.colors.darkBackground + anchors.fill: parent + + SimplifiedConstants.SimplifiedConstants { + id: simplifiedUI + } + + focus: true + + Component.onCompleted: { + root.forceActiveFocus(); + } + + + Rectangle { + id: tabContainer + anchors.top: parent.top + anchors.left: parent.left + anchors.right: parent.right + height: 64 + color: simplifiedUI.colors.highlightOnDark + + ListModel { + id: tabListModel + + ListElement { + tabTitle: "Controls" + tabViewName: "controlsTabView" + } + ListElement { + tabTitle: "About" + tabViewName: "aboutTabView" + } + } + + + Component { + id: highlightBar + Rectangle { + width: tabListView.currentItem.width + height: tabListView.currentItem.height + color: simplifiedUI.colors.darkBackground + x: tabListView.currentItem.x + Behavior on x { + SmoothedAnimation { + duration: 250 + } + } + Behavior on width { + SmoothedAnimation { + duration: 250 + } + } + } + } + + + ListView { + id: tabListView + anchors.fill: parent + contentHeight: parent.height + contentWidth: childrenRect.width + orientation: ListView.Horizontal + model: tabListModel + highlight: highlightBar + highlightFollowsCurrentItem: false + interactive: contentItem.width > width + delegate: Item { + width: tabTitleText.paintedWidth + 32 + height: parent.height + + HifiStylesUit.GraphikRegular { + id: tabTitleText + color: simplifiedUI.colors.text.white + anchors.fill: parent + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignHCenter + text: model.tabTitle + size: 24 + } + + MouseArea { + anchors.fill: parent + onClicked: { + tabListView.currentIndex = index; + root.activeTabView = model.tabViewName; + } + } + } + } + } + + Item { + id: tabViewContainers + anchors.top: tabContainer.bottom + anchors.left: parent.left + anchors.right: parent.right + anchors.bottom: parent.bottom + + + HelpControls.HelpControls { + id: controlsTabViewContainer + visible: activeTabView === "controlsTabView" + anchors.fill: parent + } + + HelpAbout.HelpAbout { + id: aboutTabViewContainer + visible: activeTabView === "aboutTabView" + anchors.fill: parent + } + + SimplifiedControls.VerticalScrollBar { + parent: { + if (activeTabView === "generalTabView") { + controlsTabViewContainers + } else if (activeTabView === "aboutTabView") { + aboutTabViewContainer + } + } + } + } + + + function fromScript(message) { + switch (message.method) { + default: + console.log('HelpApp.qml: Unrecognized message from JS'); + break; + } + } + signal sendToScript(var message); +} diff --git a/interface/resources/qml/hifi/simplifiedUI/helpApp/about/HelpAbout.qml b/interface/resources/qml/hifi/simplifiedUI/helpApp/about/HelpAbout.qml new file mode 100644 index 0000000000..25f1a14a6a --- /dev/null +++ b/interface/resources/qml/hifi/simplifiedUI/helpApp/about/HelpAbout.qml @@ -0,0 +1,359 @@ +// +// HelpAbout.qml +// +// Created by Zach Fox on 2019-08-07 +// Copyright 2019 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +import QtQuick 2.10 +import QtQuick.Controls 2.3 +import "../../simplifiedConstants" as SimplifiedConstants +import "../../simplifiedControls" as SimplifiedControls +import stylesUit 1.0 as HifiStylesUit +import QtQuick.Layouts 1.3 + +Flickable { + id: root + contentWidth: parent.width + contentHeight: aboutColumnLayout.height + clip: true + + onVisibleChanged: { + if (visible) { + root.contentX = 0; + root.contentY = 0; + + // When the user clicks the About tab, refresh the audio I/O model so that + // the delegate Component.onCompleted handlers fire, which will update + // the text that appears in the About screen. + audioOutputDevices.model = undefined; + audioOutputDevices.model = AudioScriptingInterface.devices.output; + audioInputDevices.model = undefined; + audioInputDevices.model = AudioScriptingInterface.devices.input; + } + } + + + SimplifiedConstants.SimplifiedConstants { + id: simplifiedUI + } + + + Image { + id: accent + source: "../images/accent3.svg" + anchors.left: parent.left + anchors.top: parent.top + width: 83 + height: 156 + transform: Scale { + xScale: -1 + origin.x: accent.width / 2 + origin.y: accent.height / 2 + } + } + + + ColumnLayout { + id: aboutColumnLayout + anchors.left: parent.left + anchors.leftMargin: 26 + anchors.right: parent.right + anchors.rightMargin: 26 + anchors.top: parent.top + spacing: 0 + + ColumnLayout { + id: platformInfoContainer + Layout.preferredWidth: parent.width + Layout.bottomMargin: 24 + spacing: 0 + + HifiStylesUit.GraphikSemiBold { + text: "About Your Configuration" + Layout.maximumWidth: parent.width + Layout.topMargin: 16 + Layout.bottomMargin: 8 + height: paintedHeight + size: 22 + color: simplifiedUI.colors.text.white + wrapMode: Text.Wrap + } + + HifiStylesUit.GraphikRegular { + text: "Use the button below to get a copy to share with us." + Layout.maximumWidth: parent.width + Layout.bottomMargin: 8 + height: paintedHeight + size: 18 + color: simplifiedUI.colors.text.white + wrapMode: Text.Wrap + } + + HifiStylesUit.GraphikRegular { + text: "Version " + Window.checkVersion() + Layout.maximumWidth: parent.width + Layout.topMargin: 8 + Layout.bottomMargin: 8 + height: paintedHeight + size: 16 + color: simplifiedUI.colors.text.white + wrapMode: Text.Wrap + } + + HifiStylesUit.GraphikSemiBold { + text: "Platform Info" + Layout.maximumWidth: parent.width + Layout.topMargin: 8 + Layout.bottomMargin: 8 + height: paintedHeight + size: 22 + color: simplifiedUI.colors.text.white + wrapMode: Text.Wrap + } + + HifiStylesUit.GraphikRegular { + text: "Computer Vendor/Model:" + Layout.maximumWidth: parent.width + height: paintedHeight + size: 16 + color: simplifiedUI.colors.text.white + wrapMode: Text.Wrap + + Component.onCompleted: { + var computer = JSON.parse(PlatformInfo.getComputer()); + var computerVendor = computer.vendor; + if (computerVendor.length === 0) { + computerVendor = "Unknown"; + } + var computerModel = computer.model; + if (computerModel.length === 0) { + computerModel = "Unknown"; + } + + text = "Computer Vendor/Model: " + computerVendor + "/" + computerModel; + } + } + + HifiStylesUit.GraphikRegular { + text: "Profiled Platform Tier: " + PlatformInfo.getTierProfiled() + Layout.maximumWidth: parent.width + height: paintedHeight + size: 16 + color: simplifiedUI.colors.text.white + wrapMode: Text.Wrap + } + + HifiStylesUit.GraphikRegular { + text: "OS Type: " + PlatformInfo.getOperatingSystemType() + Layout.maximumWidth: parent.width + height: paintedHeight + size: 16 + color: simplifiedUI.colors.text.white + wrapMode: Text.Wrap + } + + HifiStylesUit.GraphikRegular { + text: "CPU:" + Layout.maximumWidth: parent.width + height: paintedHeight + size: 16 + color: simplifiedUI.colors.text.white + wrapMode: Text.Wrap + + Component.onCompleted: { + var cpu = JSON.parse(PlatformInfo.getCPU(0)); + var cpuModel = cpu.model; + if (cpuModel.length === 0) { + cpuModel = "Unknown"; + } + + text = "CPU: " + cpuModel; + } + } + + HifiStylesUit.GraphikRegular { + text: "# CPUs: " + PlatformInfo.getNumCPUs() + Layout.maximumWidth: parent.width + height: paintedHeight + size: 16 + color: simplifiedUI.colors.text.white + wrapMode: Text.Wrap + } + + HifiStylesUit.GraphikRegular { + text: "# CPU Cores: " + PlatformInfo.getNumLogicalCores() + Layout.maximumWidth: parent.width + height: paintedHeight + size: 16 + color: simplifiedUI.colors.text.white + wrapMode: Text.Wrap + } + + HifiStylesUit.GraphikRegular { + text: "RAM: " + PlatformInfo.getTotalSystemMemoryMB() + " MB" + Layout.maximumWidth: parent.width + height: paintedHeight + size: 16 + color: simplifiedUI.colors.text.white + wrapMode: Text.Wrap + } + + HifiStylesUit.GraphikRegular { + text: "GPU: " + Layout.maximumWidth: parent.width + height: paintedHeight + size: 16 + color: simplifiedUI.colors.text.white + wrapMode: Text.Wrap + + Component.onCompleted: { + var gpu = JSON.parse(PlatformInfo.getGPU(PlatformInfo.getMasterGPU())); + var gpuModel = gpu.model; + if (gpuModel.length === 0) { + gpuModel = "Unknown"; + } + + text = "GPU: " + gpuModel; + } + } + + HifiStylesUit.GraphikRegular { + text: "VR Hand Controllers: " + (PlatformInfo.hasRiftControllers() ? "Rift" : (PlatformInfo.hasViveControllers() ? "Vive" : "None")) + Layout.maximumWidth: parent.width + height: paintedHeight + size: 16 + color: simplifiedUI.colors.text.white + wrapMode: Text.Wrap + } + + // This is a bit of a hack to get the name of the currently-selected audio input device + // in the current mode (Desktop or VR). The reason this is necessary is because it seems to me like + // the only way one can get a human-readable list of the audio I/O devices is by using a ListView + // and grabbing the names from the AudioScriptingInterface; you can't do it using a ListModel. + // See `AudioDevices.h`, specifically the comment above the declaration of `QVariant data()`. + ListView { + id: audioInputDevices + visible: false + property string selectedInputDeviceName + Layout.preferredWidth: parent.width + Layout.preferredHeight: contentItem.height + interactive: false + delegate: Item { + Component.onCompleted: { + if (HMD.active && selectedHMD) { + audioInputDevices.selectedInputDeviceName = model.devicename + } else if (!HMD.active && selectedDesktop) { + audioInputDevices.selectedInputDeviceName = model.devicename + } + } + } + } + + HifiStylesUit.GraphikRegular { + text: "Audio Input: " + audioInputDevices.selectedInputDeviceName + Layout.maximumWidth: parent.width + height: paintedHeight + size: 16 + color: simplifiedUI.colors.text.white + wrapMode: Text.Wrap + } + + + // This is a bit of a hack to get the name of the currently-selected audio output device + // in the current mode (Desktop or VR). The reason this is necessary is because it seems to me like + // the only way one can get a human-readable list of the audio I/O devices is by using a ListView + // and grabbing the names from the AudioScriptingInterface; you can't do it using a ListModel. + // See `AudioDevices.h`, specifically the comment above the declaration of `QVariant data()`. + ListView { + id: audioOutputDevices + visible: false + property string selectedOutputDeviceName + Layout.preferredWidth: parent.width + Layout.preferredHeight: contentItem.height + interactive: false + delegate: Item { + Component.onCompleted: { + if (HMD.active && selectedHMD) { + audioOutputDevices.selectedOutputDeviceName = model.devicename + } else if (!HMD.active && selectedDesktop) { + audioOutputDevices.selectedOutputDeviceName = model.devicename + } + } + } + } + + HifiStylesUit.GraphikRegular { + text: "Audio Output: " + audioOutputDevices.selectedOutputDeviceName + Layout.maximumWidth: parent.width + height: paintedHeight + size: 16 + color: simplifiedUI.colors.text.white + wrapMode: Text.Wrap + } + + SimplifiedControls.Button { + Layout.topMargin: 8 + width: 200 + height: 32 + text: "Copy to Clipboard" + temporaryText: "Copied!" + + onClicked: { + Window.copyToClipboard(root.buildPlatformInfoTextToCopy()); + showTemporaryText(); + } + } + } + } + + function buildPlatformInfoTextToCopy() { + var textToCopy = "**About Interface**\n"; + textToCopy += "Interface Version: " + Window.checkVersion() + "\n"; + textToCopy += "\n**Platform Info**\n"; + + var computer = JSON.parse(PlatformInfo.getComputer()); + var computerVendor = computer.vendor; + if (computerVendor.length === 0) { + computerVendor = "Unknown"; + } + var computerModel = computer.model; + if (computerModel.length === 0) { + computerModel = "Unknown"; + } + + textToCopy += "Computer Vendor/Model: " + computerVendor + "/" + computerModel + "\n"; + textToCopy += "Profiled Platform Tier: " + PlatformInfo.getTierProfiled() + "\n"; + textToCopy += "OS Type: " + PlatformInfo.getOperatingSystemType() + "\n"; + + var cpu = JSON.parse(PlatformInfo.getCPU(0)); + var cpuModel = cpu.model; + if (cpuModel.length === 0) { + cpuModel = "Unknown"; + } + + textToCopy += "CPU: " + cpuModel + "\n"; + textToCopy += "# CPUs: " + PlatformInfo.getNumCPUs() + "\n"; + textToCopy += "# CPU Cores: " + PlatformInfo.getNumLogicalCores() + "\n"; + textToCopy += "RAM: " + PlatformInfo.getTotalSystemMemoryMB() + " MB\n"; + + var gpu = JSON.parse(PlatformInfo.getGPU(PlatformInfo.getMasterGPU())); + var gpuModel = gpu.model; + if (gpuModel.length === 0) { + gpuModel = "Unknown"; + } + + textToCopy += "GPU: " + gpuModel + "\n"; + textToCopy += "VR Hand Controllers: " + (PlatformInfo.hasRiftControllers() ? "Rift" : (PlatformInfo.hasViveControllers() ? "Vive" : "None")) + "\n"; + textToCopy += "Audio Input: " + audioInputDevices.selectedInputDeviceName + "\n"; + textToCopy += "Audio Output: " + audioOutputDevices.selectedOutputDeviceName + "\n"; + + textToCopy += "\n**All Platform Info**\n"; + textToCopy += JSON.stringify(JSON.parse(PlatformInfo.getPlatform()), null, 4); + + return textToCopy; + } +} diff --git a/interface/resources/qml/hifi/simplifiedUI/helpApp/controls/HelpControls.qml b/interface/resources/qml/hifi/simplifiedUI/helpApp/controls/HelpControls.qml new file mode 100644 index 0000000000..b502f7524b --- /dev/null +++ b/interface/resources/qml/hifi/simplifiedUI/helpApp/controls/HelpControls.qml @@ -0,0 +1,91 @@ +// +// HelpControls.qml +// +// Created by Zach Fox on 2019-08-07 +// Copyright 2019 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +import QtQuick 2.10 +import QtQuick.Controls 2.3 +import "../../simplifiedConstants" as SimplifiedConstants +import "../../simplifiedControls" as SimplifiedControls +import stylesUit 1.0 as HifiStylesUit +import QtQuick.Layouts 1.3 +import PerformanceEnums 1.0 + +Flickable { + id: root + contentWidth: parent.width + contentHeight: controlsColumnLayout.height + clip: true + + onVisibleChanged: { + if (visible) { + root.contentX = 0; + root.contentY = 0; + } + } + + SimplifiedConstants.SimplifiedConstants { + id: simplifiedUI + } + + + Image { + id: accent + source: "../images/accent1.svg" + anchors.left: parent.left + anchors.top: parent.top + width: 83 + height: 156 + transform: Scale { + xScale: -1 + origin.x: accent.width / 2 + origin.y: accent.height / 2 + } + } + + + ColumnLayout { + id: controlsColumnLayout + anchors.left: parent.left + anchors.leftMargin: 26 + anchors.right: parent.right + anchors.rightMargin: 26 + anchors.top: parent.top + spacing: 0 + + HifiStylesUit.GraphikSemiBold { + text: "HQ Controls" + Layout.maximumWidth: parent.width + Layout.topMargin: 16 + height: paintedHeight + size: 22 + color: simplifiedUI.colors.text.white + } + + HifiStylesUit.GraphikRegular { + text: "You can use the following controls to move your avatar around your HQ:" + Layout.maximumWidth: parent.width + wrapMode: Text.Wrap + height: paintedHeight + size: 18 + color: simplifiedUI.colors.text.white + } + + SimplifiedControls.Button { + Layout.topMargin: 8 + width: 200 + height: 32 + text: "VIEW ALL CONTROLS" + temporaryText: "Viewing!" + + onClicked: { + Qt.openUrlExternally("http://docs.highfidelity.com/en/rc83/explore/get-started/desktop.html"); + } + } + } +} diff --git a/interface/resources/qml/hifi/simplifiedUI/helpApp/images/accent1.svg b/interface/resources/qml/hifi/simplifiedUI/helpApp/images/accent1.svg new file mode 100644 index 0000000000..885edef5ac --- /dev/null +++ b/interface/resources/qml/hifi/simplifiedUI/helpApp/images/accent1.svg @@ -0,0 +1,4 @@ + + + + diff --git a/interface/resources/qml/hifi/simplifiedUI/helpApp/images/accent2.svg b/interface/resources/qml/hifi/simplifiedUI/helpApp/images/accent2.svg new file mode 100644 index 0000000000..027d9bb623 --- /dev/null +++ b/interface/resources/qml/hifi/simplifiedUI/helpApp/images/accent2.svg @@ -0,0 +1,4 @@ + + + + diff --git a/interface/resources/qml/hifi/simplifiedUI/helpApp/images/accent3.svg b/interface/resources/qml/hifi/simplifiedUI/helpApp/images/accent3.svg new file mode 100644 index 0000000000..07cc23ef1e --- /dev/null +++ b/interface/resources/qml/hifi/simplifiedUI/helpApp/images/accent3.svg @@ -0,0 +1,4 @@ + + + + diff --git a/interface/resources/qml/hifi/simplifiedUI/topBar/SimplifiedTopBar.qml b/interface/resources/qml/hifi/simplifiedUI/topBar/SimplifiedTopBar.qml index acabbe9485..209966dee3 100644 --- a/interface/resources/qml/hifi/simplifiedUI/topBar/SimplifiedTopBar.qml +++ b/interface/resources/qml/hifi/simplifiedUI/topBar/SimplifiedTopBar.qml @@ -352,7 +352,7 @@ Rectangle { Item { id: hmdButtonContainer anchors.verticalCenter: parent.verticalCenter - anchors.right: settingsButtonContainer.left + anchors.right: helpButtonContainer.left anchors.rightMargin: 8 width: 48 height: width @@ -417,6 +417,48 @@ Rectangle { } + Item { + id: helpButtonContainer + anchors.verticalCenter: parent.verticalCenter + anchors.right: settingsButtonContainer.left + anchors.rightMargin: 3 + width: 36 + height: width + + Image { + id: helpButtonImage + source: "./images/settings.svg" + anchors.centerIn: parent + width: 22 + height: 22 + visible: false + } + + ColorOverlay { + opacity: helpButtonMouseArea.containsMouse ? 1.0 : 0.7 + anchors.fill: helpButtonImage + source: helpButtonImage + color: simplifiedUI.colors.text.white + } + + MouseArea { + id: helpButtonMouseArea + anchors.fill: parent + hoverEnabled: true + onEntered: { + Tablet.playSound(TabletEnums.ButtonHover); + } + onClicked: { + Tablet.playSound(TabletEnums.ButtonClick); + sendToScript({ + "source": "SimplifiedTopBar.qml", + "method": "toggleHelpApp" + }); + } + } + } + + Item { id: settingsButtonContainer diff --git a/scripts/simplifiedUI/ui/simplifiedUI.js b/scripts/simplifiedUI/ui/simplifiedUI.js index f4f2627c66..84d5d55e0d 100644 --- a/scripts/simplifiedUI/ui/simplifiedUI.js +++ b/scripts/simplifiedUI/ui/simplifiedUI.js @@ -187,6 +187,71 @@ function toggleSettingsApp() { settingsAppWindow.closed.connect(onSettingsAppClosed); } + +var HELP_APP_MESSAGE_SOURCE = "HelpApp.qml"; +function onMessageFromHelpApp(message) { + if (message.source !== HELP_APP_MESSAGE_SOURCE) { + return; + } + + switch (message.method) { + + default: + console.log("Unrecognized message from " + HELP_APP_MESSAGE_SOURCE + ": " + JSON.stringify(message)); + break; + } +} + + +function onHelpAppClosed() { + if (helpAppWindow) { + helpAppWindow.fromQml.disconnect(onMessageFromHelpApp); + helpAppWindow.closed.disconnect(onHelpAppClosed); + } + helpAppWindow = false; +} + + +var HELP_APP_QML_PATH = Script.resourcesPath() + "qml/hifi/simplifiedUI/helpApp/HelpApp.qml"; +var HELP_APP_WINDOW_TITLE = "Help"; +var HELP_APP_PRESENTATION_MODE = Desktop.PresentationMode.NATIVE; +var HELP_APP_WIDTH_PX = 480; +var HELP_APP_HEIGHT_PX = 615; +var HELP_APP_WINDOW_FLAGS = 0x00000001 | // Qt::Window + 0x00001000 | // Qt::WindowTitleHint + 0x00002000 | // Qt::WindowSystemMenuHint + 0x08000000 | // Qt::WindowCloseButtonHint + 0x00008000 | // Qt::WindowMaximizeButtonHint + 0x00004000; // Qt::WindowMinimizeButtonHint +var helpAppWindow = false; +function toggleHelpApp() { + if (helpAppWindow) { + helpAppWindow.close(); + // This really shouldn't be necessary. + // This signal really should automatically be called by the signal handler set up below. + // But fixing that requires an engine change, so this workaround will do. + onHelpAppClosed(); + return; + } + + helpAppWindow = Desktop.createWindow(HELP_APP_QML_PATH, { + title: HELP_APP_WINDOW_TITLE, + presentationMode: HELP_APP_PRESENTATION_MODE, + size: { + x: HELP_APP_WIDTH_PX, + y: HELP_APP_HEIGHT_PX + }, + position: { + x: Math.max(Window.x + POPOUT_SAFE_MARGIN_X, Window.x + Window.innerWidth / 2 - HELP_APP_WIDTH_PX / 2), + y: Math.max(Window.y + POPOUT_SAFE_MARGIN_Y, Window.y + Window.innerHeight / 2 - HELP_APP_HEIGHT_PX / 2) + }, + overrideFlags: HELP_APP_WINDOW_FLAGS + }); + + helpAppWindow.fromQml.connect(onMessageFromHelpApp); + helpAppWindow.closed.connect(onHelpAppClosed); +} + function updateEmoteAppBarPosition() { if (!emoteAppBarWindow) { return; @@ -374,6 +439,10 @@ function onMessageFromTopBar(message) { toggleSettingsApp(); break; + case "toggleHelpApp": + toggleHelpApp(); + break; + case "setOutputMuted": setOutputMuted(message.data.outputMuted); break;