Integrate Status into top bar; improve Audio settings; improve spacing between settings

This commit is contained in:
Zach Fox 2019-05-17 17:25:48 -07:00
parent 4e86948c25
commit 15bdb66943
9 changed files with 356 additions and 14 deletions

View file

@ -19,8 +19,8 @@ Flickable {
id: root
contentWidth: parent.width
contentHeight: audioColumnLayout.height
topMargin: 16
bottomMargin: 16
topMargin: 24
bottomMargin: 24
clip: true
function changePeakValuesEnabled(enabled) {
@ -189,7 +189,7 @@ Flickable {
Layout.topMargin: simplifiedUI.margins.settings.settingsGroupTopMargin
interactive: false
height: contentItem.height
spacing: 4
spacing: simplifiedUI.margins.settings.spacingBetweenRadiobuttons
clip: true
model: AudioScriptingInterface.devices.input
delegate: Item {
@ -200,6 +200,8 @@ Flickable {
id: inputDeviceCheckbox
anchors.left: parent.left
width: parent.width - inputLevel.width
height: paintedHeight
wrapLabel: false
checked: selectedDesktop
text: model.devicename
ButtonGroup.group: inputDeviceButtonGroup
@ -288,7 +290,7 @@ Flickable {
Layout.topMargin: simplifiedUI.margins.settings.settingsGroupTopMargin
interactive: false
height: contentItem.height
spacing: 4
spacing: simplifiedUI.margins.settings.spacingBetweenRadiobuttons
clip: true
model: AudioScriptingInterface.devices.output
delegate: Item {
@ -299,8 +301,10 @@ Flickable {
id: outputDeviceCheckbox
anchors.left: parent.left
width: parent.width
height: paintedHeight
checked: selectedDesktop
text: model.devicename
wrapLabel: false
ButtonGroup.group: outputDeviceButtonGroup
onClicked: {
AudioScriptingInterface.setOutputDevice(model.info, false); // `false` argument for Desktop mode setting

View file

@ -20,8 +20,8 @@ Flickable {
id: root
contentWidth: parent.width
contentHeight: generalColumnLayout.height
topMargin: 16
bottomMargin: 16
topMargin: 24
bottomMargin: 24
clip: true
onAvatarNametagModeChanged: {
@ -63,6 +63,7 @@ Flickable {
ColumnLayout {
id: avatarNameTagsRadioButtonGroup
Layout.topMargin: simplifiedUI.margins.settings.settingsGroupTopMargin
spacing: simplifiedUI.margins.settings.spacingBetweenRadiobuttons
SimplifiedControls.RadioButton {
id: avatarNameTagsOff
@ -110,6 +111,7 @@ Flickable {
ColumnLayout {
id: performanceRadioButtonGroup
Layout.topMargin: simplifiedUI.margins.settings.settingsGroupTopMargin
spacing: simplifiedUI.margins.settings.spacingBetweenRadiobuttons
SimplifiedControls.RadioButton {
id: performanceLow
@ -157,6 +159,7 @@ Flickable {
ColumnLayout {
id: cameraRadioButtonGroup
Layout.topMargin: simplifiedUI.margins.settings.settingsGroupTopMargin
spacing: simplifiedUI.margins.settings.spacingBetweenRadiobuttons
SimplifiedControls.RadioButton {
id: firstPerson

View file

@ -19,8 +19,8 @@ Flickable {
id: root
contentWidth: parent.width
contentHeight: vrColumnLayout.height
topMargin: 16
bottomMargin: 16
topMargin: 24
bottomMargin: 24
clip: true
function changePeakValuesEnabled(enabled) {
@ -70,6 +70,7 @@ Flickable {
id: controlsRadioButtonGroup
width: parent.width
Layout.topMargin: simplifiedUI.margins.settings.settingsGroupTopMargin
spacing: simplifiedUI.margins.settings.spacingBetweenRadiobuttons
ButtonGroup { id: controlsButtonGroup }
@ -202,7 +203,7 @@ Flickable {
Layout.topMargin: simplifiedUI.margins.settings.settingsGroupTopMargin
interactive: false
height: contentItem.height
spacing: 4
spacing: simplifiedUI.margins.settings.spacingBetweenRadiobuttons
clip: true
model: AudioScriptingInterface.devices.input
delegate: Item {
@ -301,7 +302,7 @@ Flickable {
Layout.topMargin: simplifiedUI.margins.settings.settingsGroupTopMargin
interactive: false
height: contentItem.height
spacing: 4
spacing: simplifiedUI.margins.settings.spacingBetweenRadiobuttons
clip: true
model: AudioScriptingInterface.devices.output
delegate: Item {

View file

@ -182,9 +182,10 @@ QtObject {
}
readonly property QtObject settings: QtObject {
property real subtitleTopMargin: 2
property real settingsGroupTopMargin: 10
property real spacingBetweenSettings: 48
property int subtitleTopMargin: 2
property int settingsGroupTopMargin: 24
property int spacingBetweenSettings: 48
property int spacingBetweenRadiobuttons: 14
}
}

View file

@ -87,7 +87,6 @@ RadioButton {
contentItem: Text {
id: radioButtonLabel
height: root.radioButtonRadius
font.pixelSize: 14
font.family: "Graphik"
font.weight: Font.Normal
@ -99,5 +98,6 @@ RadioButton {
enabled: root.enabled
verticalAlignment: Text.AlignVCenter
leftPadding: radioButtonIndicator.width + root.labelLeftMargin
topPadding: -3 // For perfect alignment when using Graphik
}
}

View file

@ -242,6 +242,56 @@ Rectangle {
}
Item {
id: statusButtonContainer
anchors.verticalCenter: parent.verticalCenter
anchors.left: outputDeviceButtonContainer.right
anchors.leftMargin: 2
width: 32
height: width
Rectangle {
id: statusButton
property string currentStatus: ""
anchors.centerIn: parent
width: 20
height: width
radius: width/2
visible: false
}
ColorOverlay {
anchors.fill: statusButton
opacity: statusButtonMouseArea.containsMouse ? 1.0 : 0.7
source: statusButton
color: if (statusButton.currentStatus === "busy") {
"red"
} else if (statusButton.currentStatus === "available") {
"green"
} else {
"yellow"
}
}
MouseArea {
id: statusButtonMouseArea
anchors.fill: parent
hoverEnabled: true
onEntered: {
Tablet.playSound(TabletEnums.ButtonHover);
}
onClicked: {
Tablet.playSound(TabletEnums.ButtonClick);
sendToScript({
"source": "SimplifiedTopBar.qml",
"method": "toggleStatus"
});
}
}
}
Item {
id: hmdButtonContainer
@ -401,6 +451,10 @@ Rectangle {
outputDeviceButton.outputMuted = message.data.outputMuted;
break;
case "updateStatusButton":
statusButton.currentStatus = message.data.currentStatus;
break;
default:
console.log('SimplifiedTopBar.qml: Unrecognized message from JS');
break;

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 5.2 KiB

View file

@ -0,0 +1,244 @@
//
// simplifiedStatusIndicator.js
//
// Created by Robin Wilson on 2019-05-17
// 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
function simplifiedStatusIndicator(properties) {
var that = this;
var DEBUG = false;
// #region HEARTBEAT
// Send heartbeat with updates to database
// When this stops, the database will set status to offline
var HEARTBEAT_TIMEOUT_MS = 5000,
heartbeat;
function startHeartbeatTimer() {
if (heartbeat) {
Script.clearTimeout(heartbeat);
heartbeat = false;
}
heartbeat = Script.setTimeout(function() {
heartbeat = false;
getStatus(setStatus);
}, HEARTBEAT_TIMEOUT_MS);
}
// #endregion HEARTBEAT
// #region SEND/GET STATUS REQUEST
function setStatusExternally(newStatus) {
if (!newStatus) {
return;
}
setStatus(newStatus);
}
var request = Script.require('request').request,
REQUEST_URL = "https://highfidelity.co/api/statusIndicator/";
function setStatus(newStatus) {
if (heartbeat) {
Script.clearTimeout(heartbeat);
heartbeat = false;
}
if (newStatus && currentStatus !== newStatus) {
currentStatus = newStatus;
that.statusChanged();
}
var displayNameToSend = MyAvatar.sessionDisplayName;
queryParamString += currentStatus;
if (displayNameToSend === "") {
displayNameToSend = MyAvatar.displayName;
}
var queryParamString = "type=heartbeat";
queryParamString += "&username=" + AccountServices.username;
queryParamString += "&displayName=" + displayNameToSend;
queryParamString += "&status=";
queryParamString += currentStatus;
var uri = REQUEST_URL + "?" + queryParamString;
if (DEBUG) {
console.log("setStatus: " + uri);
}
request({
uri: uri
}, function (error, response) {
startHeartbeatTimer();
if (error || !response || response.status !== "success") {
console.error("Error with setStatus: " + JSON.stringify(response));
return;
}
});
}
// Get status from database
function getStatus(callback) {
var queryParamString = "type=getStatus";
queryParamString += "&username=" + AccountServices.username;
var uri = REQUEST_URL + "?" + queryParamString;
if (DEBUG) {
console.log("getStatus: " + uri);
}
request({
uri: uri
}, function (error, response) {
if (error || !response || response.status !== "success") {
console.error("Error with getStatus: " + JSON.stringify(response));
} else if (response.data.userStatus.toLowerCase() !== "offline") {
if (response.data.userStatus !== currentStatus) {
currentStatus = response.data.userStatus;
that.statusChanged();
}
}
if (callback) {
callback();
}
});
}
function getLocalStatus() {
return currentStatus;
}
// #endregion SEND/GET STATUS REQUEST
// #region SIGNALS
var currentStatus = "available"; // Default is available
function toggleStatus() {
if (currentStatus === "busy") {
currentStatus = "available";
// Else if current status is "available" OR anything else (custom)
} else {
currentStatus = "busy";
}
that.statusChanged();
setStatus();
}
// When avatar becomes active from being away
// Set status back to previousStatus
function onWentActive() {
if (currentStatus !== previousStatus) {
currentStatus = previousStatus;
that.statusChanged();
}
setStatus();
}
// When avatar goes away, set status to busy
var previousStatus;
function onWentAway() {
previousStatus = currentStatus;
if (currentStatus !== "busy") {
currentStatus = "busy";
that.statusChanged();
}
setStatus();
}
// Domain changed update avatar location
function onDomainChanged() {
var queryParamString = "type=updateEmployee";
queryParamString += "&username=" + AccountServices.username;
queryParamString += "&location=unknown";
var uri = REQUEST_URL + "?" + queryParamString;
if (DEBUG) {
console.log("simplifiedStatusIndicator onDomainChanged: " + uri);
}
request({
uri: uri
}, function (error, response) {
if (error || !response || response.status !== "success") {
console.error("Error with onDomainChanged: " + JSON.stringify(response));
} else {
// successfully sent updateLocation
if (DEBUG) {
console.log("Successfully updated location after domain change.");
}
}
});
}
function statusChanged() {
}
// #endregion SIGNALS
// #region APP LIFETIME
// Creates the app button and sets up signals and hearbeat
function startup() {
MyAvatar.wentAway.connect(onWentAway);
MyAvatar.wentActive.connect(onWentActive);
MyAvatar.displayNameChanged.connect(setStatus);
Window.domainChanged.connect(onDomainChanged);
getStatus(setStatus);
}
// Cleans up timeouts, signals, and overlays
function unload() {
MyAvatar.wentAway.disconnect(onWentAway);
MyAvatar.wentActive.disconnect(onWentActive);
MyAvatar.displayNameChanged.disconnect(setStatus);
Window.domainChanged.disconnect(onDomainChanged);
if (heartbeat) {
Script.clearTimeout(heartbeat);
heartbeat = false;
}
}
// #endregion APP LIFETIME
that.startup = startup;
that.unload = unload;
that.toggleStatus = toggleStatus;
that.setStatus = setStatus;
that.getLocalStatus = getLocalStatus;
that.statusChanged = statusChanged;
// Overwrite with the given properties
var overwriteableKeys = ["statusChanged"];
Object.keys(properties).forEach(function (key) {
if (overwriteableKeys.indexOf(key) > -1) {
that[key] = properties[key];
}
});
}
module.exports = simplifiedStatusIndicator;

View file

@ -276,6 +276,11 @@ function setOutputMuted(outputMuted) {
}
function toggleStatus() {
}
var TOP_BAR_MESSAGE_SOURCE = "SimplifiedTopBar.qml";
function onMessageFromTopBar(message) {
if (message.source !== TOP_BAR_MESSAGE_SOURCE) {
@ -295,6 +300,10 @@ function onMessageFromTopBar(message) {
setOutputMuted(message.data.outputMuted);
break;
case "toggleStatus":
si.toggleStatus();
break;
default:
console.log("Unrecognized message from " + TOP_BAR_MESSAGE_SOURCE + ": " + JSON.stringify(message));
break;
@ -435,7 +444,25 @@ function ensureFirstPersonCameraInHMD(isHMDMode) {
}
}
function onStatusChanged() {
var currentStatus = si.getLocalStatus();
if (topBarWindow) {
topBarWindow.sendToQml({
"source": "simplifiedUI.js",
"method": "updateStatusButton",
"data": {
"currentStatus": currentStatus
}
});
}
}
var simplifiedNametag = Script.require("./simplifiedNametag/simplifiedNametag.js");
var SimplifiedStatusIndicator = Script.require("./simplifiedStatusIndicator/simplifiedStatusIndicator.js");
var si;
var oldShowAudioTools;
var oldShowBubbleTools;
var keepExistingUIAndScriptsSetting = Settings.getValue("simplifiedUI/keepExistingUIAndScripts", false);
@ -456,6 +483,10 @@ function startup() {
loadSimplifiedTopBar();
simplifiedNametag.create();
si = new SimplifiedStatusIndicator({
statusChanged: onStatusChanged
});
si.startup();
updateInputDeviceMutedOverlay(Audio.muted);
updateOutputDeviceMutedOverlay(isOutputMuted());
Audio.mutedDesktopChanged.connect(onDesktopInputDeviceMutedChanged);
@ -506,6 +537,7 @@ function shutdown() {
maybeDeleteOutputDeviceMutedOverlay();
simplifiedNametag.destroy();
si.unload();
Audio.mutedDesktopChanged.disconnect(onDesktopInputDeviceMutedChanged);
Window.geometryChanged.disconnect(onGeometryChanged);