diff --git a/.github/workflows/master_build.yml b/.github/workflows/master_build.yml index 314578d01d..6f87f59d1d 100644 --- a/.github/workflows/master_build.yml +++ b/.github/workflows/master_build.yml @@ -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 diff --git a/.github/workflows/pr_build.yml b/.github/workflows/pr_build.yml index a0fdc633ce..872f112289 100644 --- a/.github/workflows/pr_build.yml +++ b/.github/workflows/pr_build.yml @@ -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: diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index de41927fe2..c2de9c78ce 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -3616,28 +3616,18 @@ void DomainServer::handleOctreeFileReplacementRequest(QSharedPointer 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(); - 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()->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(); + 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(); + 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) { diff --git a/domain-server/src/DomainServer.h b/domain-server/src/DomainServer.h index 034ccb5a18..95b4b784cb 100644 --- a/domain-server/src/DomainServer.h +++ b/domain-server/src/DomainServer.h @@ -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(); diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index cc12e4fcee..d8353796b6 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -436,38 +436,72 @@ class MyAvatar : public Avatar { const bool DEFAULT_STRAFE_ENABLED = true; public: + /**jsdoc + * The DriveKeys 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 *

Logical keys that drive your avatar and camera.

* * - * + * * * - * - * - * - * - * - * - * - * - * - * - * - * + * + * + * + * + * + * + * + * + * + * + * + * * *
ValueNameDescription
ValueDescription
0TRANSLATE_XMove the user's avatar in the direction of its x-axis, if the - * camera isn't in independent or mirror modes.
1TRANSLATE_YMove the user's avatar in the direction of its y-axis, if the - * camera isn't in independent or mirror modes.
2TRANSLATE_ZMove the user's avatar in the direction of its z-axis, if the - * camera isn't in independent or mirror modes
3YAWRotate 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.
4STEP_TRANSLATE_XNo action.
5STEP_TRANSLATE_YNo action.
6STEP_TRANSLATE_ZNo action.
7STEP_YAWRotate the user's avatar about its y-axis in a step increment, if - * the camera isn't in independent or mirror modes.
8PITCHRotate 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.
9ZOOMZoom the camera in or out.
10DELTA_YAWRotate 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.
11DELTA_PITCHRotate 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.
{@link DriveKeys|DriveKeys.TRANSLATE_X}Move the user's avatar in the direction of its + * x-axis, if the camera isn't in independent or mirror modes.
{@link DriveKeys|DriveKeys.TRANSLATE_Y}Move the user's avatar in the direction of its + * -axis, if the camera isn't in independent or mirror modes.
{@link DriveKeys|DriveKeys.TRANSLATE_Z}Move the user's avatar in the direction of its + * z-axis, if the camera isn't in independent or mirror modes.
{@link DriveKeys|DriveKeys.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.
{@link DriveKeys|DriveKeys.STEP_TRANSLATE_X}No action.
{@link DriveKeys|DriveKeys.STEP_TRANSLATE_Y}No action.
{@link DriveKeys|DriveKeys.STEP_TRANSLATE_Z}No action.
{@link DriveKeys|DriveKeys.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.
{@link DriveKeys|DriveKeys.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.
{@link DriveKeys|DriveKeys.ZOOM}Zoom the camera in or out.
{@link DriveKeys|DriveKeys.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.
{@link DriveKeys|DriveKeys.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.
- * @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 Disable rotating your avatar using the keyboard for a couple of seconds. - * 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} true if the drive key is disabled, false if it isn't. */ Q_INVOKABLE bool isDriveKeyDisabled(DriveKeys key) const; diff --git a/interface/src/scripting/AccountServicesScriptingInterface.h b/interface/src/scripting/AccountServicesScriptingInterface.h index 3ad637d0e6..288137e166 100644 --- a/interface/src/scripting/AccountServicesScriptingInterface.h +++ b/interface/src/scripting/AccountServicesScriptingInterface.h @@ -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 * "Unknown user". Read-only. * @property {boolean} loggedIn - true if the user is logged in, otherwise false. @@ -61,6 +62,86 @@ class AccountServicesScriptingInterface : public QObject { * — typically "https://metaverse.highfidelity.com". Read-only. */ + /**jsdoc + * The Account 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 + * "Unknown user". Read-only. + * @property {boolean} loggedIn - true if the user is logged in, otherwise false. + * Read-only. + * @property {string} findableBy - The user's visibility to other users: + *
    + *
  • "none" — user appears offline.
  • + *
  • "friends" — user is visible only to friends.
  • + *
  • "connections" — user is visible to friends and connections.
  • + *
  • "all" — user is visible to everyone.
  • + *
+ * @property {string} metaverseServerURL - The metaverse server that the user is authenticated against when logged in + * — typically "https://metaverse.highfidelity.com". Read-only. + * + * @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 GlobalServices 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 + * "Unknown user". Read-only. + * @property {boolean} loggedIn - true if the user is logged in, otherwise false. + * Read-only. + * @property {string} findableBy - The user's visibility to other users: + *
    + *
  • "none" — user appears offline.
  • + *
  • "friends" — user is visible only to friends.
  • + *
  • "connections" — user is visible to friends and connections.
  • + *
  • "all" — user is visible to everyone.
  • + *
+ * @property {string} metaverseServerURL - The metaverse server that the user is authenticated against when logged in + * — typically "https://metaverse.highfidelity.com". Read-only. + * + * @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) diff --git a/interface/src/scripting/DialogsManagerScriptingInterface.h b/interface/src/scripting/DialogsManagerScriptingInterface.h index b223799cfe..ee1baeecf5 100644 --- a/interface/src/scripting/DialogsManagerScriptingInterface.h +++ b/interface/src/scripting/DialogsManagerScriptingInterface.h @@ -14,19 +14,56 @@ #include +/**jsdoc + * The DialogsMamnager 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 + * Currently performs no action. + * @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. + *

Warning: Currently isn't always triggered.

+ * @function DialogsManager.addressBarShown + * @param {boolean} visible - true if the Goto dialog has been opened, false if it has been + * closed. + * @returns {Signal} + */ void addressBarShown(bool visible); }; diff --git a/interface/src/scripting/ScreenshareScriptingInterface.cpp b/interface/src/scripting/ScreenshareScriptingInterface.cpp index 37365c1b89..3bf8336fe4 100644 --- a/interface/src/scripting/ScreenshareScriptingInterface.cpp +++ b/interface/src/scripting/ScreenshareScriptingInterface.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include #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(); + PacketReceiver& packetReceiver = nodeList->getPacketReceiver(); + packetReceiver.registerListener(PacketType::AvatarZonePresence, this, "processAvatarZonePresencePacketOnClient"); }; ScreenshareScriptingInterface::~ScreenshareScriptingInterface() { stopScreenshare(); } +void ScreenshareScriptingInterface::processAvatarZonePresencePacketOnClient(QSharedPointer 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. diff --git a/interface/src/scripting/ScreenshareScriptingInterface.h b/interface/src/scripting/ScreenshareScriptingInterface.h index 2e9cd79fcf..ec8f3cd619 100644 --- a/interface/src/scripting/ScreenshareScriptingInterface.h +++ b/interface/src/scripting/ScreenshareScriptingInterface.h @@ -18,6 +18,7 @@ #include #include +#include class ScreenshareScriptingInterface : public QObject, public Dependency { Q_OBJECT @@ -36,6 +37,7 @@ signals: void localWebEntityZOffsetChanged(const float& newZOffset); private slots: + void processAvatarZonePresencePacketOnClient(QSharedPointer 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 diff --git a/libraries/networking/src/AccountManager.cpp b/libraries/networking/src/AccountManager.cpp index 5473f1a010..83c0fd28dd 100644 --- a/libraries/networking/src/AccountManager.cpp +++ b/libraries/networking/src/AccountManager.cpp @@ -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* " diff --git a/libraries/networking/src/AccountManager.h b/libraries/networking/src/AccountManager.h index 2e94ccf0ea..7dc4d0dc13 100644 --- a/libraries/networking/src/AccountManager.h +++ b/libraries/networking/src/AccountManager.h @@ -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 { diff --git a/libraries/networking/src/AddressManager.h b/libraries/networking/src/AddressManager.h index 7a67371ab5..8bdb777f96 100644 --- a/libraries/networking/src/AddressManager.h +++ b/libraries/networking/src/AddressManager.h @@ -68,6 +68,66 @@ const QString GET_PLACE = "/api/v1/places/%1"; * Read-only. */ +/**jsdoc + * The AddressManager 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. + * Read-only. + * @property {string} hostname - The name of the domain for your current metaverse address (e.g., "DomainName", + * localhost, or an IP address). Is blank if you're in a serverless domain. + * Read-only. + * @property {string} href - Your current metaverse address (e.g., "hifi://domainname/15,-10,26/0,0,0,1") + * regardless of whether or not you're connected to the domain. Starts with "file:///" if you're in a + * serverless domain. + * Read-only. + * @property {boolean} isConnected - true if you're connected to the domain in your current href + * metaverse address, otherwise false. + * @property {string} pathname - The location and orientation in your current href metaverse address + * (e.g., "/15,-10,26/0,0,0,1"). + * Read-only. + * @property {string} placename - The place name in your current href metaverse address + * (e.g., "DomainName"). Is blank if your hostname is an IP address. + * Read-only. + * @property {string} protocol - The protocol of your current href metaverse address (e.g., "hifi"). + * Read-only. + * + * @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 diff --git a/libraries/pointers/src/Pick.h b/libraries/pointers/src/Pick.h index e4257140fd..9e6c5f9898 100644 --- a/libraries/pointers/src/Pick.h +++ b/libraries/pointers/src/Pick.h @@ -93,7 +93,7 @@ public: * collisions. */ - /**jsdoc + /**jsdoc *

A type of pick.

* * diff --git a/libraries/ui/src/OffscreenUi.cpp b/libraries/ui/src/OffscreenUi.cpp index f0b27904ae..34184057e0 100644 --- a/libraries/ui/src/OffscreenUi.cpp +++ b/libraries/ui/src/OffscreenUi.cpp @@ -33,13 +33,20 @@ #include "MainWindow.h" /**jsdoc + * The OffscreenFlags API enables gamepad joystick navigation of UI. + * + *

This API currently has no effect and is not used.

+ * * @namespace OffscreenFlags * * @hifi-interface * @hifi-client-entity * @hifi-avatar - * @property {boolean} navigationFocused - * @property {boolean} navigationFocusDisabled + * + * @property {boolean} navigationFocused - true if UI has joystick navigation focus, false if it + * doesn't. + * @property {boolean} navigationFocusDisabled - true if UI joystick navigation focus is disabled, + * false 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 navigationFocused property changes. * @function OffscreenFlags.navigationFocusedChanged * @returns {Signal} */ void navigationFocusedChanged(); /**jsdoc + * Triggered when the value of the navigationFocusDisabled property changes. * @function OffscreenFlags.navigationFocusDisabledChanged * @returns {Signal} */ diff --git a/screenshare/src/screenshareApp.js b/screenshare/src/screenshareApp.js index b16f5ca993..6a33b827d4 100644 --- a/screenshare/src/screenshareApp.js +++ b/screenshare/src/screenshareApp.js @@ -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,