initial with pal

This commit is contained in:
howard-stearns 2018-07-16 11:54:05 -07:00
parent b5862c0ede
commit 46061a2a15
2 changed files with 201 additions and 61 deletions

161
scripts/modules/appUi.js Normal file
View file

@ -0,0 +1,161 @@
//
// libraries/appUi.js
//
// Created by Howard Stearns on 3/20/18.
// Copyright 2018 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 AppUi(properties) {
/* Example development order:
1. var AppUi = Script.require('appUi');
2. Put appname-i.svg, appname-a.svg in graphicsDirectory (where non-default graphicsDirectory can be added in #3).
3. ui = new AppUi({buttonName: "APPNAME", home: "qml-or-html-path"});
(and if converting an existing app,
define var tablet = ui.tablet, button = ui.button; as needed.
remove button.clicked.[dis]connect and tablet.remove(button).)
4. Define onOpened and onClosed behavior in #3, if any.
(and if converting an existing app, remove screenChanged.[dis]connect.)
5. Define onMessage in #3, if any.
(and if converting an existing app, remove code that [un]wires that message handling.)
x. lint!
*/
var that = this;
function defaultButton(name, suffix) {
var base = that[name] || (that.buttonPrefix + suffix);
that[name] = (base.indexOf('/') >= 0) ? base : (that.graphicsDirectory + base); //poor man's merge
}
// Defaults:
that.tabletName = "com.highfidelity.interface.tablet.system";
that.inject = "";
that.graphicsDirectory = "icons/tablet-icons/"; // Where to look for button svgs. See below.
that.checkIsOpen = function checkIsOpen(type, tabletUrl) { // Are we active? Value used to set isOpen.
return (type === that.type) && (tabletUrl.indexOf(that.home) >= 0); // Actual url may have prefix or suffix.
}
that.toOpen = function toOpen() { // How to open the app.
if (that.isQML()) {
that.tablet.loadQMLSource(that.home);
} else {
that.tablet.gotoWebScreen(that.home, that.inject);
}
};
that.toClose = function toClose() { // How to close the app.
// for toolbar-mode: go back to home screen, this will close the window.
that.tablet.gotoHomeScreen();
};
that.buttonActive = function buttonActive(isActive) { // How to make the button active (white).
that.button.editProperties({isActive: isActive});
};
that.messagesWaiting = function messagesWaiting(isWaiting) { // How to indicate a message light on button.
// Note that waitingButton doesn't have to exist unless someone explicitly calls this with isWaiting true.
that.button.editProperties({
icon: isWaiting ? that.normalMessagesButton : that.normalButton,
activeIcon: isWaiting ? that.activeMessagesButton : that.activeButton
});
};
that.isQML = function isQML() { // We set type property in onClick.
return that.type === 'QML';
}
that.eventSignal = function eventSignal() { // What signal to hook onMessage to.
return that.isQML() ? that.tablet.fromQml : that.tablet.webEventReceived;
};
// Overwrite with the given properties:
Object.keys(properties).forEach(function (key) { that[key] = properties[key]; });
// Properties:
that.tablet = Tablet.getTablet(that.tabletName);
// Must be after we gather properties.
that.buttonPrefix = that.buttonPrefix || that.buttonName.toLowerCase() + "-";
defaultButton('normalButton', 'i.svg');
defaultButton('activeButton', 'a.svg');
defaultButton('normalMessagesButton', 'i-msg.svg');
defaultButton('activeMessagesButton', 'a-msg.svg');
that.button = that.tablet.addButton({
icon: that.normalButton,
activeIcon: that.activeButton,
text: that.buttonName,
sortOrder: that.sortOrder
});
that.ignore = function ignore() { };
// Handlers
that.onScreenChanged = function onScreenChanged(type, url) {
// Set isOpen, wireEventBridge, set buttonActive as appropriate,
// and finally call onOpened() or onClosed() IFF defined.
print('hrs fixme onScreenChanged', type, url, that.isOpen);
if (that.checkIsOpen(type, url)) {
if (!that.isOpen) {
that.isOpen = true;
that.wireEventBridge(true);
that.buttonActive(true);
if (that.onOpened) {
that.onOpened();
}
}
} else { // Not us. Should we do something for type Home, Menu, and particularly Closed (meaning tablet hidden?
if (that.isOpen) {
that.isOpen = false;
that.wireEventBridge(false);
that.buttonActive(false);
if (that.onClosed) {
that.onClosed();
}
}
}
};
that.hasEventBridge = false;
that.wireEventBridge = function wireEventBridge(on) {
// Sets hasEventBridge and wires onMessage to eventSignal as appropriate, IFF onMessage defined.
print('hrs fixme wireEventBridge', on, that.hasEventBridge);
if (!that.onMessage) { return; }
if (on) {
if (!that.hasEventBridge) {
print('hrs fixme connecting', that.eventSignal());
that.eventSignal().connect(that.onMessage);
that.hasEventBridge = true;
}
} else {
if (that.hasEventBridge) {
print('hrs fixme connecting', that.eventSignal());
that.eventSignal().disconnect(that.onMessage);
that.hasEventBridge = false;
}
}
};
that.isOpen = false;
// To facilitate incremental development, only wire onClicked to do something when "home" is defined in properties.
that.onClicked = that.home
? function onClicked() {
// Call toOpen() or toClose(), and reset type based on current home property.
if (that.isOpen) {
that.toClose();
} else {
that.type = /.qml$/.test(that.home) ? 'QML' : 'Web'
that.toOpen();
}
} : that.ignore;
that.onScriptEnding = function onScriptEnding() {
// Close if necessary, clean up any remaining handlers, and remove the button.
if (that.isOpen) {
that.toClose();
}
that.tablet.screenChanged.disconnect(that.onScreenChanged);
if (that.button) {
if (that.onClicked) {
that.button.clicked.disconnect(that.onClicked);
}
that.tablet.removeButton(that.button);
}
};
// Set up the handlers.
that.tablet.screenChanged.connect(that.onScreenChanged);
that.button.clicked.connect(that.onClicked);
Script.scriptEnding.connect(that.onScriptEnding);
};
module.exports = AppUi;

View file

@ -15,9 +15,10 @@
(function() { // BEGIN LOCAL_SCOPE (function() { // BEGIN LOCAL_SCOPE
var request = Script.require('request').request; var request = Script.require('request').request;
var AppUi = Script.require('appUi');
var populateNearbyUserList, color, textures, removeOverlays, var populateNearbyUserList, color, textures, removeOverlays,
controllerComputePickRay, onTabletButtonClicked, onTabletScreenChanged, controllerComputePickRay, off,
receiveMessage, avatarDisconnected, clearLocalQMLDataAndClosePAL, receiveMessage, avatarDisconnected, clearLocalQMLDataAndClosePAL,
createAudioInterval, tablet, CHANNEL, getConnectionData, findableByChanged, createAudioInterval, tablet, CHANNEL, getConnectionData, findableByChanged,
avatarAdded, avatarRemoved, avatarSessionChanged; // forward references; avatarAdded, avatarRemoved, avatarSessionChanged; // forward references;
@ -678,20 +679,7 @@ function tabletVisibilityChanged() {
var wasOnPalScreen = false; var wasOnPalScreen = false;
var onPalScreen = false; var onPalScreen = false;
var PAL_QML_SOURCE = "hifi/Pal.qml"; /*var hasEventBridge = false;
function onTabletButtonClicked() {
if (!tablet) {
print("Warning in onTabletButtonClicked(): 'tablet' undefined!");
return;
}
if (onPalScreen) {
// In Toolbar Mode, `gotoHomeScreen` will close the app window.
tablet.gotoHomeScreen();
} else {
tablet.loadQMLSource(PAL_QML_SOURCE);
}
}
var hasEventBridge = false;
function wireEventBridge(on) { function wireEventBridge(on) {
if (on) { if (on) {
if (!hasEventBridge) { if (!hasEventBridge) {
@ -704,16 +692,14 @@ function wireEventBridge(on) {
hasEventBridge = false; hasEventBridge = false;
} }
} }
} }*/
function captureState() {
function onTabletScreenChanged(type, url) {
wasOnPalScreen = onPalScreen; wasOnPalScreen = onPalScreen;
onPalScreen = (type === "QML" && url === PAL_QML_SOURCE); onPalScreen = ui.isOpen;
wireEventBridge(onPalScreen); //wireEventBridge(onPalScreen);
// for toolbar mode: change button to active when window is first openend, false otherwise. }
button.editProperties({isActive: onPalScreen}); function on() {
captureState();
if (onPalScreen) {
isWired = true; isWired = true;
ContextOverlay.enabled = false; ContextOverlay.enabled = false;
@ -729,13 +715,8 @@ function onTabletScreenChanged(type, url) {
triggerMapping.enable(); triggerMapping.enable();
triggerPressMapping.enable(); triggerPressMapping.enable();
populateNearbyUserList(); populateNearbyUserList();
} else {
off();
if (wasOnPalScreen) {
ContextOverlay.enabled = true;
}
}
} }
var button, ui, tablet;
// //
// Message from other scripts, such as edit.js // Message from other scripts, such as edit.js
@ -749,7 +730,7 @@ function receiveMessage(channel, messageString, senderID) {
switch (message.method) { switch (message.method) {
case 'select': case 'select':
if (!onPalScreen) { if (!onPalScreen) {
tablet.loadQMLSource(PAL_QML_SOURCE); tablet.loadQMLSource(ui.home);
Script.setTimeout(function () { sendToQml(message); }, 1000); Script.setTimeout(function () { sendToQml(message); }, 1000);
} else { } else {
sendToQml(message); // Accepts objects, not just strings. sendToQml(message); // Accepts objects, not just strings.
@ -847,20 +828,17 @@ function avatarSessionChanged(avatarID) {
sendToQml({ method: 'palIsStale', params: [avatarID, 'avatarSessionChanged'] }); sendToQml({ method: 'palIsStale', params: [avatarID, 'avatarSessionChanged'] });
} }
var button;
var buttonName = "PEOPLE";
var tablet = null;
function startup() { function startup() {
tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); ui = new AppUi({
button = tablet.addButton({ buttonName: "PEOPLE",
text: buttonName, sortOrder: 7,
icon: "icons/tablet-icons/people-i.svg", home: "hifi/Pal.qml",
activeIcon: "icons/tablet-icons/people-a.svg", onOpened: on,
sortOrder: 7 onClosed: off,
onMessage: fromQml
}); });
button.clicked.connect(onTabletButtonClicked); tablet = ui.tablet;
tablet.screenChanged.connect(onTabletScreenChanged); button = ui.button;
Window.domainChanged.connect(clearLocalQMLDataAndClosePAL); Window.domainChanged.connect(clearLocalQMLDataAndClosePAL);
Window.domainConnectionRefused.connect(clearLocalQMLDataAndClosePAL); Window.domainConnectionRefused.connect(clearLocalQMLDataAndClosePAL);
Messages.subscribe(CHANNEL); Messages.subscribe(CHANNEL);
@ -877,6 +855,7 @@ var isWired = false;
var audioTimer; var audioTimer;
var AUDIO_LEVEL_UPDATE_INTERVAL_MS = 100; // 10hz for now (change this and change the AVERAGING_RATIO too) var AUDIO_LEVEL_UPDATE_INTERVAL_MS = 100; // 10hz for now (change this and change the AVERAGING_RATIO too)
function off() { function off() {
captureState();
if (isWired) { if (isWired) {
Script.update.disconnect(updateOverlays); Script.update.disconnect(updateOverlays);
Controller.mousePressEvent.disconnect(handleMouseEvent); Controller.mousePressEvent.disconnect(handleMouseEvent);
@ -896,15 +875,15 @@ function off() {
} }
removeOverlays(); removeOverlays();
if (wasOnPalScreen) {
ContextOverlay.enabled = true;
}
} }
function shutdown() { function shutdown() {
if (onPalScreen) { if (onPalScreen) {
tablet.gotoHomeScreen(); tablet.gotoHomeScreen();
} }
button.clicked.disconnect(onTabletButtonClicked);
tablet.removeButton(button);
tablet.screenChanged.disconnect(onTabletScreenChanged);
Window.domainChanged.disconnect(clearLocalQMLDataAndClosePAL); Window.domainChanged.disconnect(clearLocalQMLDataAndClosePAL);
Window.domainConnectionRefused.disconnect(clearLocalQMLDataAndClosePAL); Window.domainConnectionRefused.disconnect(clearLocalQMLDataAndClosePAL);
Messages.subscribe(CHANNEL); Messages.subscribe(CHANNEL);