Merge branch 'master' into linux-actions-builds-pr-builds

This commit is contained in:
Simon Walton 2019-12-10 11:37:25 -08:00 committed by GitHub
commit 9a87fe0473
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 367 additions and 69 deletions

View file

@ -91,7 +91,6 @@ jobs:
# - os: ubuntu-latest
# build_type: client
runs-on: ${{matrix.os}}
if: github.event.action != 'labeled' || github.event.label.name == 'rebuild-mac' || github.event.label.name == 'rebuild'
needs: generate_build_number
steps:
- name: Download build number

View file

@ -9,18 +9,20 @@ env:
BUILD_TYPE: Release
CI_BUILD: Github
GIT_COMMIT: ${{ github.sha }}
GIT_COMMIT_SHORT: ${{ github.sha }}
HIFI_VCPKG_BOOTSTRAP: true
RELEASE_TYPE: PR
RELEASE_NUMBER: ${{ github.event.number }}
VERSION_CODE: ${{ github.event.number }}
# OSX specific variables
DEVELOPER_DIR: /Applications/Xcode_11.2.app/Contents/Developer
MACOSX_DEPLOYMENT_TARGET: '10.11'
# WIN32 specific variables
PreferredToolArchitecture: X64
GIT_COMMIT_SHORT: ${{ github.sha }}
jobs:
build:

View file

@ -3616,28 +3616,18 @@ void DomainServer::handleOctreeFileReplacementRequest(QSharedPointer<ReceivedMes
}
void DomainServer::processAvatarZonePresencePacket(QSharedPointer<ReceivedMessage> message) {
QUuid avatar = QUuid::fromRfc4122(message->readWithoutCopy(NUM_BYTES_RFC4122_UUID));
QUuid zone = QUuid::fromRfc4122(message->readWithoutCopy(NUM_BYTES_RFC4122_UUID));
QUuid avatarID = QUuid::fromRfc4122(message->readWithoutCopy(NUM_BYTES_RFC4122_UUID));
QUuid zoneID = QUuid::fromRfc4122(message->readWithoutCopy(NUM_BYTES_RFC4122_UUID));
if (avatar.isNull()) {
if (avatarID.isNull()) {
qCWarning(domain_server) << "Ignoring null avatar presence";
return;
}
auto limitedNodeList = DependencyManager::get<LimitedNodeList>();
auto matchingNode = limitedNodeList->nodeWithUUID(avatar);
if (!matchingNode) {
qCWarning(domain_server) << "Ignoring avatar presence for unknown avatar" << avatar;
return;
}
QString verifiedUsername = matchingNode->getPermissions().getVerifiedUserName();
if (verifiedUsername.isEmpty()) { // Silently bail for users who are not logged in.
return;
}
static const int SCREENSHARE_EXPIRATION_SECONDS = 24 * 60 * 60;
screensharePresence(zone.isNull() ? "" : zone.toString(), verifiedUsername, SCREENSHARE_EXPIRATION_SECONDS);
screensharePresence(zoneID.isNull() ? "" : zoneID.toString(), avatarID, SCREENSHARE_EXPIRATION_SECONDS);
}
void DomainServer::screensharePresence(QString roomname, QString username, int expirationSeconds) {
void DomainServer::screensharePresence(QString roomname, QUuid avatarID, int expirationSeconds) {
if (!DependencyManager::get<AccountManager>()->hasValidAccessToken()) {
static std::once_flag presenceAuthorityWarning;
std::call_once(presenceAuthorityWarning, [] {
@ -3645,14 +3635,33 @@ void DomainServer::screensharePresence(QString roomname, QString username, int e
});
return;
}
auto limitedNodeList = DependencyManager::get<LimitedNodeList>();
auto matchingNode = limitedNodeList->nodeWithUUID(avatarID);
if (!matchingNode) {
qCWarning(domain_server) << "Ignoring avatar presence for unknown avatar ID" << avatarID;
return;
}
QString verifiedUsername = matchingNode->getPermissions().getVerifiedUserName();
if (verifiedUsername.isEmpty()) { // Silently bail for users who are not logged in.
return;
}
JSONCallbackParameters callbackParams;
callbackParams.callbackReceiver = this;
callbackParams.jsonCallbackMethod = "handleSuccessfulScreensharePresence";
callbackParams.errorCallbackMethod = "handleFailedScreensharePresence";
// Construct `callbackData`, which is data that will be available to the callback functions.
// In this case, the "success" callback needs access to the "roomname" (the zone ID) and the
// relevant avatar's UUID.
QJsonObject callbackData;
callbackData.insert("roomname", roomname);
callbackData.insert("avatarID", avatarID.toString());
callbackParams.callbackData = callbackData;
const QString PATH = "api/v1/domains/%1/screenshare";
QString domain_id = uuidStringWithoutCurlyBraces(getID());
QJsonObject json, screenshare;
screenshare["username"] = username;
screenshare["username"] = verifiedUsername;
screenshare["roomname"] = roomname;
if (expirationSeconds > 0) {
screenshare["expiration"] = expirationSeconds;
@ -3666,11 +3675,18 @@ void DomainServer::screensharePresence(QString roomname, QString username, int e
);
}
void DomainServer::handleSuccessfulScreensharePresence(QNetworkReply* requestReply) {
void DomainServer::handleSuccessfulScreensharePresence(QNetworkReply* requestReply, QJsonObject callbackData) {
QJsonObject jsonObject = QJsonDocument::fromJson(requestReply->readAll()).object();
if (jsonObject["status"].toString() != "success") {
qCWarning(domain_server) << "screensharePresence api call failed:" << QJsonDocument(jsonObject).toJson(QJsonDocument::Compact);
return;
}
// Tell the client that we just authorized to screenshare which zone ID in which they are authorized to screenshare.
auto nodeList = DependencyManager::get<LimitedNodeList>();
auto packet = NLPacket::create(PacketType::AvatarZonePresence, NUM_BYTES_RFC4122_UUID, true);
packet->write(QUuid(callbackData["roomname"].toString()).toRfc4122());
nodeList->sendPacket(std::move(packet), *(nodeList->nodeWithUUID(QUuid(callbackData["avatarID"].toString()))));
}
void DomainServer::handleFailedScreensharePresence(QNetworkReply* requestReply) {

View file

@ -78,7 +78,7 @@ public:
bool isAssetServerEnabled();
void screensharePresence(QString roomname, QString username, int expiration_seconds = 0);
void screensharePresence(QString roomname, QUuid avatarID, int expiration_seconds = 0);
public slots:
/// Called by NodeList to inform us a node has been added
@ -132,7 +132,7 @@ private slots:
void handleSuccessfulICEServerAddressUpdate(QNetworkReply* requestReply);
void handleFailedICEServerAddressUpdate(QNetworkReply* requestReply);
void handleSuccessfulScreensharePresence(QNetworkReply* requestReply);
void handleSuccessfulScreensharePresence(QNetworkReply* requestReply, QJsonObject callbackData);
void handleFailedScreensharePresence(QNetworkReply* requestReply);
void updateReplicatedNodes();

View file

@ -436,38 +436,72 @@ class MyAvatar : public Avatar {
const bool DEFAULT_STRAFE_ENABLED = true;
public:
/**jsdoc
* The <code>DriveKeys</code> API provides constant numeric values that represent different logical keys that drive your
* avatar and camera.
*
* @namespace DriveKeys
*
* @hifi-interface
* @hifi-client-entity
* @hifi-avatar
*
* @property {number} TRANSLATE_X - Move the user's avatar in the direction of its x-axis, if the camera isn't in
* independent or mirror modes.
* @property {number} TRANSLATE_Y - Move the user's avatar in the direction of its y-axis, if the camera isn't in
* independent or mirror modes.
* @property {number} TRANSLATE_Z - Move the user's avatar in the direction of its z-axis, if the camera isn't in
* independent or mirror modes.
* @property {number} YAW - Rotate the user's avatar about its y-axis at a rate proportional to the control value, if the
* camera isn't in independent or mirror modes.
* @property {number} STEP_TRANSLATE_X - No action.
* @property {number} STEP_TRANSLATE_Y - No action.
* @property {number} STEP_TRANSLATE_Z - No action.
* @property {number} STEP_YAW - Rotate the user's avatar about its y-axis in a step increment, if the camera isn't in
* independent or mirror modes.
* @property {number} PITCH - Rotate the user's avatar head and attached camera about its negative x-axis (i.e., positive
* values pitch down) at a rate proportional to the control value, if the camera isn't in HMD, independent, or mirror
* modes.
* @property {number} ZOOM - Zoom the camera in or out.
* @property {number} DELTA_YAW - Rotate the user's avatar about its y-axis by an amount proportional to the control value,
* if the camera isn't in independent or mirror modes.
* @property {number} DELTA_PITCH - Rotate the user's avatar head and attached camera about its negative x-axis (i.e.,
* positive values pitch down) by an amount proportional to the control value, if the camera isn't in HMD, independent,
* or mirror modes.
*/
/**jsdoc
* <p>Logical keys that drive your avatar and camera.</p>
* <table>
* <thead>
* <tr><th>Value</th><th>Name</th><th>Description</th></tr>
* <tr><th>Value</th><th>Description</th></tr>
* </thead>
* <tbody>
* <tr><td><code>0</code></td><td>TRANSLATE_X</td><td>Move the user's avatar in the direction of its x-axis, if the
* camera isn't in independent or mirror modes.</td></tr>
* <tr><td><code>1</code></td><td>TRANSLATE_Y</td><td>Move the user's avatar in the direction of its y-axis, if the
* camera isn't in independent or mirror modes.</td></tr>
* <tr><td><code>2</code></td><td>TRANSLATE_Z</td><td>Move the user's avatar in the direction of its z-axis, if the
* camera isn't in independent or mirror modes</td></tr>
* <tr><td><code>3</code></td><td>YAW</td><td>Rotate the user's avatar about its y-axis at a rate proportional to the
* control value, if the camera isn't in independent or mirror modes.</td></tr>
* <tr><td><code>4</code></td><td>STEP_TRANSLATE_X</td><td>No action.</td></tr>
* <tr><td><code>5</code></td><td>STEP_TRANSLATE_Y</td><td>No action.</td></tr>
* <tr><td><code>6</code></td><td>STEP_TRANSLATE_Z</td><td>No action.</td></tr>
* <tr><td><code>7</code></td><td>STEP_YAW</td><td>Rotate the user's avatar about its y-axis in a step increment, if
* the camera isn't in independent or mirror modes.</td></tr>
* <tr><td><code>8</code></td><td>PITCH</td><td>Rotate the user's avatar head and attached camera about its negative
* x-axis (i.e., positive values pitch down) at a rate proportional to the control value, if the camera isn't in HMD,
* independent, or mirror modes.</td></tr>
* <tr><td><code>9</code></td><td>ZOOM</td><td>Zoom the camera in or out.</td></tr>
* <tr><td><code>10</code></td><td>DELTA_YAW</td><td>Rotate the user's avatar about its y-axis by an amount proportional
* to the control value, if the camera isn't in independent or mirror modes.</td></tr>
* <tr><td><code>11</code></td><td>DELTA_PITCH</td><td>Rotate the user's avatar head and attached camera about its
* negative x-axis (i.e., positive values pitch down) by an amount proportional to the control value, if the camera
* isn't in HMD, independent, or mirror modes.</td></tr>
* <tr><td><code>{@link DriveKeys|DriveKeys.TRANSLATE_X}</code></td><td>Move the user's avatar in the direction of its
* x-axis, if the camera isn't in independent or mirror modes.</td></tr>
* <tr><td><code>{@link DriveKeys|DriveKeys.TRANSLATE_Y}</code></td><td>Move the user's avatar in the direction of its
* -axis, if the camera isn't in independent or mirror modes.</td></tr>
* <tr><td><code>{@link DriveKeys|DriveKeys.TRANSLATE_Z}</code></td><td>Move the user's avatar in the direction of its
* z-axis, if the camera isn't in independent or mirror modes.</td></tr>
* <tr><td><code>{@link DriveKeys|DriveKeys.YAW}</code></td><td>Rotate the user's avatar about its y-axis at a rate
* proportional to the control value, if the camera isn't in independent or mirror modes.</td></tr>
* <tr><td><code>{@link DriveKeys|DriveKeys.STEP_TRANSLATE_X}</code></td><td>No action.</td></tr>
* <tr><td><code>{@link DriveKeys|DriveKeys.STEP_TRANSLATE_Y}</code></td><td>No action.</td></tr>
* <tr><td><code>{@link DriveKeys|DriveKeys.STEP_TRANSLATE_Z}</code></td><td>No action.</td></tr>
* <tr><td><code>{@link DriveKeys|DriveKeys.STEP_YAW}</code></td><td>Rotate the user's avatar about its y-axis in a
* step increment, if the camera isn't in independent or mirror modes.</td></tr>
* <tr><td><code>{@link DriveKeys|DriveKeys.PITCH}</code></td><td>Rotate the user's avatar head and attached camera
* about its negative x-axis (i.e., positive values pitch down) at a rate proportional to the control value, if the
* camera isn't in HMD, independent, or mirror modes.</td></tr>
* <tr><td><code>{@link DriveKeys|DriveKeys.ZOOM}</code></td><td>Zoom the camera in or out.</td></tr>
* <tr><td><code>{@link DriveKeys|DriveKeys.DELTA_YAW}</code></td><td>Rotate the user's avatar about its y-axis by an
* amount proportional to the control value, if the camera isn't in independent or mirror modes.</td></tr>
* <tr><td><code>{@link DriveKeys|DriveKeys.DELTA_PITCH}</code></td><td>Rotate the user's avatar head and attached
* camera about its negative x-axis (i.e., positive values pitch down) by an amount proportional to the control
* value, if the camera isn't in HMD, independent, or mirror modes.</td></tr>
* </tbody>
* </table>
* @typedef {number} MyAvatar.DriveKeys
* @typedef {number} DriveKey
*/
enum DriveKeys {
TRANSLATE_X = 0,
@ -1019,7 +1053,7 @@ public:
/**jsdoc
* Gets the value of a drive key, regardless of whether it is disabled.
* @function MyAvatar.getRawDriveKey
* @param {MyAvatar.DriveKeys} key - The drive key.
* @param {DriveKey} key - The drive key.
* @returns {number} The value of the drive key.
*/
Q_INVOKABLE float getRawDriveKey(DriveKeys key) const;
@ -1029,11 +1063,10 @@ public:
/**jsdoc
* Disables the action associated with a drive key.
* @function MyAvatar.disableDriveKey
* @param {MyAvatar.DriveKeys} key - The drive key to disable.
* @param {DriveKey} key - The drive key to disable.
* @example <caption>Disable rotating your avatar using the keyboard for a couple of seconds.</caption>
* var YAW = 3;
* print("Disable");
* MyAvatar.disableDriveKey(YAW);
* MyAvatar.disableDriveKey(DriveKeys.YAW);
* Script.setTimeout(function () {
* print("Enable");
* MyAvatar.enableDriveKey(YAW);
@ -1045,14 +1078,14 @@ public:
* Enables the action associated with a drive key. The action may have been disabled with
* {@link MyAvatar.disableDriveKey|disableDriveKey}.
* @function MyAvatar.enableDriveKey
* @param {MyAvatar.DriveKeys} key - The drive key to enable.
* @param {DriveKey} key - The drive key to enable.
*/
Q_INVOKABLE void enableDriveKey(DriveKeys key);
/**jsdoc
* Checks whether a drive key is disabled.
* @function MyAvatar.isDriveKeyDisabled
* @param {DriveKeys} key - The drive key to check.
* @param {DriveKey} key - The drive key to check.
* @returns {boolean} <code>true</code> if the drive key is disabled, <code>false</code> if it isn't.
*/
Q_INVOKABLE bool isDriveKeyDisabled(DriveKeys key) const;

View file

@ -46,6 +46,7 @@ class AccountServicesScriptingInterface : public QObject {
* @hifi-avatar
*
* @namespace AccountServices
*
* @property {string} username - The user name of the user logged in. If there is no user logged in, it is
* <code>"Unknown user"</code>. <em>Read-only.</em>
* @property {boolean} loggedIn - <code>true</code> if the user is logged in, otherwise <code>false</code>.
@ -61,6 +62,86 @@ class AccountServicesScriptingInterface : public QObject {
* &mdash; typically <code>"https://metaverse.highfidelity.com"</code>. <em>Read-only.</em>
*/
/**jsdoc
* The <code>Account</code> API provides functions that give information on user connectivity, visibility, and asset
* download progress.
*
* @deprecated This API is the same as the {@link AccountServices} API and will be removed.
*
* @hifi-interface
* @hifi-client-entity
* @hifi-avatar
*
* @namespace Account
*
* @property {string} username - The user name of the user logged in. If there is no user logged in, it is
* <code>"Unknown user"</code>. <em>Read-only.</em>
* @property {boolean} loggedIn - <code>true</code> if the user is logged in, otherwise <code>false</code>.
* <em>Read-only.</em>
* @property {string} findableBy - The user's visibility to other users:
* <ul>
* <li><code>"none"</code> &mdash; user appears offline.</li>
* <li><code>"friends"</code> &mdash; user is visible only to friends.</li>
* <li><code>"connections"</code> &mdash; user is visible to friends and connections.</li>
* <li><code>"all"</code> &mdash; user is visible to everyone.</li>
* </ul>
* @property {string} metaverseServerURL - The metaverse server that the user is authenticated against when logged in
* &mdash; typically <code>"https://metaverse.highfidelity.com"</code>. <em>Read-only.</em>
*
* @borrows AccountServices.getDownloadInfo as getDownloadInfo
* @borrows AccountServices.updateDownloadInfo as updateDownloadInfo
* @borrows AccountServices.isLoggedIn as isLoggedIn
* @borrows AccountServices.checkAndSignalForAccessToken as checkAndSignalForAccessToken
* @borrows AccountServices.logOut as logOut
*
* @borrows AccountServices.connected as connected
* @borrows AccountServices.disconnected as disconnected
* @borrows AccountServices.myUsernameChanged as myUsernameChanged
* @borrows AccountServices.downloadInfoChanged as downloadInfoChanged
* @borrows AccountServices.findableByChanged as findableByChanged
* @borrows AccountServices.loggedInChanged as loggedInChanged
*/
/**jsdoc
* The <code>GlobalServices</code> API provides functions that give information on user connectivity, visibility, and asset
* download progress.
*
* @deprecated This API is the same as the {@link AccountServices} API and will be removed.
*
* @hifi-interface
* @hifi-client-entity
* @hifi-avatar
*
* @namespace GlobalServices
*
* @property {string} username - The user name of the user logged in. If there is no user logged in, it is
* <code>"Unknown user"</code>. <em>Read-only.</em>
* @property {boolean} loggedIn - <code>true</code> if the user is logged in, otherwise <code>false</code>.
* <em>Read-only.</em>
* @property {string} findableBy - The user's visibility to other users:
* <ul>
* <li><code>"none"</code> &mdash; user appears offline.</li>
* <li><code>"friends"</code> &mdash; user is visible only to friends.</li>
* <li><code>"connections"</code> &mdash; user is visible to friends and connections.</li>
* <li><code>"all"</code> &mdash; user is visible to everyone.</li>
* </ul>
* @property {string} metaverseServerURL - The metaverse server that the user is authenticated against when logged in
* &mdash; typically <code>"https://metaverse.highfidelity.com"</code>. <em>Read-only.</em>
*
* @borrows AccountServices.getDownloadInfo as getDownloadInfo
* @borrows AccountServices.updateDownloadInfo as updateDownloadInfo
* @borrows AccountServices.isLoggedIn as isLoggedIn
* @borrows AccountServices.checkAndSignalForAccessToken as checkAndSignalForAccessToken
* @borrows AccountServices.logOut as logOut
*
* @borrows AccountServices.connected as connected
* @borrows AccountServices.disconnected as disconnected
* @borrows AccountServices.myUsernameChanged as myUsernameChanged
* @borrows AccountServices.downloadInfoChanged as downloadInfoChanged
* @borrows AccountServices.findableByChanged as findableByChanged
* @borrows AccountServices.loggedInChanged as loggedInChanged
*/
Q_PROPERTY(QString username READ getUsername NOTIFY myUsernameChanged)
Q_PROPERTY(bool loggedIn READ loggedIn NOTIFY loggedInChanged)
Q_PROPERTY(QString findableBy READ getFindableBy WRITE setFindableBy NOTIFY findableByChanged)

View file

@ -14,19 +14,56 @@
#include <QObject>
/**jsdoc
* The <code>DialogsMamnager</code> API provides facilities to work with some key dialogs.
*
* @namespace DialogsManager
*
* @hifi-interface
* @hifi-client-entity
* @hifi-avatar
*/
class DialogsManagerScriptingInterface : public QObject {
Q_OBJECT
public:
DialogsManagerScriptingInterface();
static DialogsManagerScriptingInterface* getInstance();
/**jsdoc
* <em>Currently performs no action.</em>
* @function DialogsManager.showFeed
*/
Q_INVOKABLE void showFeed();
public slots:
/**jsdoc
* Shows the "Goto" dialog.
* @function DialogsManager.showAddressBar
*/
void showAddressBar();
/**jsdoc
* Hides the "Goto" dialog.
* @function DialogsManager.hideAddressBar
*/
void hideAddressBar();
/**jsdoc
* Shows the login dialog.
* @function DialogsManager.showLoginDialog
*/
void showLoginDialog();
signals:
/**jsdoc
* Triggered when the "Goto" dialog is opened or closed.
* <p><strong>Warning:</strong> Currently isn't always triggered.</p>
* @function DialogsManager.addressBarShown
* @param {boolean} visible - <code>true</code> if the Goto dialog has been opened, <code>false</code> if it has been
* closed.
* @returns {Signal}
*/
void addressBarShown(bool visible);
};

View file

@ -18,6 +18,7 @@
#include <AccountManager.h>
#include <AddressManager.h>
#include <DependencyManager.h>
#include <NodeList.h>
#include <UUID.h>
#include "EntityScriptingInterface.h"
@ -37,14 +38,48 @@ ScreenshareScriptingInterface::ScreenshareScriptingInterface() {
_requestScreenshareInfoRetryTimer->setSingleShot(true);
_requestScreenshareInfoRetryTimer->setInterval(SCREENSHARE_INFO_REQUEST_RETRY_TIMEOUT_MS);
connect(_requestScreenshareInfoRetryTimer, &QTimer::timeout, this, &ScreenshareScriptingInterface::requestScreenshareInfo);
// This packet listener handles the packet containing information about the latest zone ID in which we are allowed to share.
auto nodeList = DependencyManager::get<NodeList>();
PacketReceiver& packetReceiver = nodeList->getPacketReceiver();
packetReceiver.registerListener(PacketType::AvatarZonePresence, this, "processAvatarZonePresencePacketOnClient");
};
ScreenshareScriptingInterface::~ScreenshareScriptingInterface() {
stopScreenshare();
}
void ScreenshareScriptingInterface::processAvatarZonePresencePacketOnClient(QSharedPointer<ReceivedMessage> message) {
QUuid zone = QUuid::fromRfc4122(message->readWithoutCopy(NUM_BYTES_RFC4122_UUID));
if (zone.isNull()) {
qWarning() << "Ignoring avatar zone presence packet that doesn't specify a zone.";
return;
}
// Set the last known authorized screenshare zone ID to the zone that the Domain Server just told us about.
_lastAuthorizedZoneID = zone;
// If we had previously started the screenshare process but knew that we weren't going to be authorized to screenshare,
// let's continue the screenshare process here.
if (_waitingForAuthorization) {
requestScreenshareInfo();
}
}
static const int MAX_NUM_SCREENSHARE_INFO_REQUEST_RETRIES = 5;
void ScreenshareScriptingInterface::requestScreenshareInfo() {
// If the screenshare zone that we're currently in (i.e. `startScreenshare()` was called) is different from
// the zone in which we are authorized to screenshare...
// ...return early here and wait for the DS to send us a packet containing this zone's ID.
if (_screenshareZoneID != _lastAuthorizedZoneID) {
qDebug() << "Client not yet authorized to screenshare. Waiting for authorization message from domain server...";
_waitingForAuthorization = true;
return;
}
_waitingForAuthorization = false;
_requestScreenshareInfoRetries++;
if (_requestScreenshareInfoRetries >= MAX_NUM_SCREENSHARE_INFO_REQUEST_RETRIES) {
@ -174,6 +209,7 @@ void ScreenshareScriptingInterface::stopScreenshare() {
_projectAPIKey = "";
_sessionID = "";
_isPresenter = false;
_waitingForAuthorization = false;
}
// Called when the Metaverse returns the information necessary to start/view a screen share.

View file

@ -18,6 +18,7 @@
#include <QNetworkReply>
#include <PathUtils.h>
#include <ReceivedMessage.h>
class ScreenshareScriptingInterface : public QObject, public Dependency {
Q_OBJECT
@ -36,6 +37,7 @@ signals:
void localWebEntityZOffsetChanged(const float& newZOffset);
private slots:
void processAvatarZonePresencePacketOnClient(QSharedPointer<ReceivedMessage> message);
void onWebEventReceived(const QUuid& entityID, const QVariant& message);
void handleSuccessfulScreenshareInfoGet(QNetworkReply* reply);
void handleFailedScreenshareInfoGet(QNetworkReply* reply);
@ -82,6 +84,9 @@ private:
QUuid _screenshareZoneID;
QUuid _smartboardEntityID;
bool _isPresenter{ false };
QUuid _lastAuthorizedZoneID;
bool _waitingForAuthorization{ false };
};
#endif // hifi_ScreenshareScriptingInterface_h

View file

@ -52,11 +52,13 @@ const int PULL_SETTINGS_RETRY_INTERVAL = 2 * MSECS_PER_SECOND;
const int MAX_PULL_RETRIES = 10;
JSONCallbackParameters::JSONCallbackParameters(QObject* callbackReceiver,
const QString& jsonCallbackMethod,
const QString& errorCallbackMethod) :
const QString& jsonCallbackMethod,
const QString& errorCallbackMethod,
const QJsonObject& callbackData) :
callbackReceiver(callbackReceiver),
jsonCallbackMethod(jsonCallbackMethod),
errorCallbackMethod(errorCallbackMethod)
errorCallbackMethod(errorCallbackMethod),
callbackData(callbackData)
{
}
@ -348,9 +350,17 @@ void AccountManager::sendRequest(const QString& path,
[callbackParams, networkReply] {
if (networkReply->error() == QNetworkReply::NoError) {
if (!callbackParams.jsonCallbackMethod.isEmpty()) {
bool invoked = QMetaObject::invokeMethod(callbackParams.callbackReceiver,
qPrintable(callbackParams.jsonCallbackMethod),
Q_ARG(QNetworkReply*, networkReply));
bool invoked = false;
if (callbackParams.callbackData.isEmpty()) {
invoked = QMetaObject::invokeMethod(callbackParams.callbackReceiver,
qPrintable(callbackParams.jsonCallbackMethod),
Q_ARG(QNetworkReply*, networkReply));
} else {
invoked = QMetaObject::invokeMethod(callbackParams.callbackReceiver,
qPrintable(callbackParams.jsonCallbackMethod),
Q_ARG(QNetworkReply*, networkReply),
Q_ARG(QJsonObject, callbackParams.callbackData));
}
if (!invoked) {
QString error = "Could not invoke " + callbackParams.jsonCallbackMethod + " with QNetworkReply* "
@ -366,9 +376,18 @@ void AccountManager::sendRequest(const QString& path,
}
} else {
if (!callbackParams.errorCallbackMethod.isEmpty()) {
bool invoked = QMetaObject::invokeMethod(callbackParams.callbackReceiver,
qPrintable(callbackParams.errorCallbackMethod),
Q_ARG(QNetworkReply*, networkReply));
bool invoked = false;
if (callbackParams.callbackData.isEmpty()) {
invoked = QMetaObject::invokeMethod(callbackParams.callbackReceiver,
qPrintable(callbackParams.errorCallbackMethod),
Q_ARG(QNetworkReply*, networkReply));
}
else {
invoked = QMetaObject::invokeMethod(callbackParams.callbackReceiver,
qPrintable(callbackParams.errorCallbackMethod),
Q_ARG(QNetworkReply*, networkReply),
Q_ARG(QJsonObject, callbackParams.callbackData));
}
if (!invoked) {
QString error = "Could not invoke " + callbackParams.errorCallbackMethod + " with QNetworkReply* "

View file

@ -30,14 +30,16 @@
class JSONCallbackParameters {
public:
JSONCallbackParameters(QObject* callbackReceiver = nullptr,
const QString& jsonCallbackMethod = QString(),
const QString& errorCallbackMethod = QString());
const QString& jsonCallbackMethod = QString(),
const QString& errorCallbackMethod = QString(),
const QJsonObject& callbackData = QJsonObject());
bool isEmpty() const { return !callbackReceiver; }
QObject* callbackReceiver;
QString jsonCallbackMethod;
QString errorCallbackMethod;
QJsonObject callbackData;
};
namespace AccountManagerAuth {

View file

@ -68,6 +68,66 @@ const QString GET_PLACE = "/api/v1/places/%1";
* <em>Read-only.</em>
*/
/**jsdoc
* The <code>AddressManager</code> API provides facilities related to your current location in the metaverse.
*
* @namespace AddressManager
*
* @hifi-interface
* @hifi-client-entity
* @hifi-avatar
*
* @deprecated This API is deprecated and will be removed. Use the {@link location} or {@link Window|Window.location} APIs
* instead.
*
* @property {Uuid} domainID - A UUID uniquely identifying the domain you're visiting. Is {@link Uuid(0)|Uuid.NULL} if you're not
* connected to the domain or are in a serverless domain.
* <em>Read-only.</em>
* @property {string} hostname - The name of the domain for your current metaverse address (e.g., <code>"DomainName"</code>,
* <code>localhost</code>, or an IP address). Is blank if you're in a serverless domain.
* <em>Read-only.</em>
* @property {string} href - Your current metaverse address (e.g., <code>"hifi://domainname/15,-10,26/0,0,0,1"</code>)
* regardless of whether or not you're connected to the domain. Starts with <code>"file:///"</code> if you're in a
* serverless domain.
* <em>Read-only.</em>
* @property {boolean} isConnected - <code>true</code> if you're connected to the domain in your current <code>href</code>
* metaverse address, otherwise <code>false</code>.
* @property {string} pathname - The location and orientation in your current <code>href</code> metaverse address
* (e.g., <code>"/15,-10,26/0,0,0,1"</code>).
* <em>Read-only.</em>
* @property {string} placename - The place name in your current <code>href</code> metaverse address
* (e.g., <code>"DomainName"</code>). Is blank if your <code>hostname</code> is an IP address.
* <em>Read-only.</em>
* @property {string} protocol - The protocol of your current <code>href</code> metaverse address (e.g., <code>"hifi"</code>).
* <em>Read-only.</em>
*
* @borrows location.handleLookupString as handleLookupString
* @borrows location.goToViewpointForPath as goToViewpointForPath
* @borrows location.goBack as goBack
* @borrows location.goForward as goForward
* @borrows location.goToLocalSandbox as goToLocalSandbox
* @borrows location.goToEntry as goToEntry
* @borrows location.goToUser as goToUser
* @borrows location.goToLastAddress as goToLastAddress
* @borrows location.canGoBack as canGoBack
* @borrows location.refreshPreviousLookup as refreshPreviousLookup
* @borrows location.storeCurrentAddress as storeCurrentAddress
* @borrows location.copyAddress as copyAddress
* @borrows location.copyPath as copyPath
* @borrows location.lookupShareableNameForDomainID as lookupShareableNameForDomainID
*
* @borrows location.lookupResultsFinished as lookupResultsFinished
* @borrows location.lookupResultIsOffline as lookupResultIsOffline
* @borrows location.lookupResultIsNotFound as lookupResultIsNotFound
* @borrows location.possibleDomainChangeRequired as possibleDomainChangeRequired
* @borrows location.locationChangeRequired as locationChangeRequired
* @borrows location.possibleDomainChangeRequiredViaICEForID as possibleDomainChangeRequiredViaICEForID
* @borrows location.pathChangeRequired as pathChangeRequired
* @borrows location.hostChanged as hostChanged
* @borrows location.goBackPossible as goBackPossible
* @borrows location.goForwardPossible as goForwardPossible
*/
class AddressManager : public QObject, public Dependency {
Q_OBJECT
SINGLETON_DEPENDENCY

View file

@ -93,7 +93,7 @@ public:
* collisions.
*/
/**jsdoc
/**jsdoc
* <p>A type of pick.</p>
* <table>
* <thead>

View file

@ -33,13 +33,20 @@
#include "MainWindow.h"
/**jsdoc
* The <code>OffscreenFlags</code> API enables gamepad joystick navigation of UI.
*
* <p><em>This API currently has no effect and is not used.</em></p>
*
* @namespace OffscreenFlags
*
* @hifi-interface
* @hifi-client-entity
* @hifi-avatar
* @property {boolean} navigationFocused
* @property {boolean} navigationFocusDisabled
*
* @property {boolean} navigationFocused - <code>true</code> if UI has joystick navigation focus, <code>false</code> if it
* doesn't.
* @property {boolean} navigationFocusDisabled - <code>true</code> if UI joystick navigation focus is disabled,
* <code>false</code> if it isn't.
*/
// Needs to match the constants in resources/qml/Global.js
@ -72,12 +79,14 @@ public:
signals:
/**jsdoc
* Triggered when the value of the <code>navigationFocused</code> property changes.
* @function OffscreenFlags.navigationFocusedChanged
* @returns {Signal}
*/
void navigationFocusedChanged();
/**jsdoc
* Triggered when the value of the <code>navigationFocusDisabled</code> property changes.
* @function OffscreenFlags.navigationFocusDisabledChanged
* @returns {Signal}
*/

View file

@ -223,10 +223,9 @@ function onAccessApproved(desktop_id) {
mandatory: {
chromeMediaSource: 'desktop',
chromeMediaSourceId: desktop_id,
minWidth: 1280,
maxWidth: 1280,
minHeight: 720,
maxHeight: 720
maxHeight: 720,
maxFrameRate: 7
}
}
}, gotStream, handleError);
@ -261,7 +260,7 @@ function startTokboxPublisher(stream) {
audioFallbackEnabled: false,
audioSource: null,
fitMode: 'contain',
frameRate: 30,
frameRate: 7,
height: 720,
insertMode: 'append',
publishAudio: false,