diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index f53e329e10..e9cc9161ca 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1198,6 +1198,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo connect(&domainHandler, SIGNAL(domainURLChanged(QUrl)), SLOT(domainURLChanged(QUrl))); connect(&domainHandler, SIGNAL(redirectToErrorDomainURL(QUrl)), SLOT(goToErrorDomainURL(QUrl))); + connect(this, SIGNAL(loginScreenStateChanged(bool)), &domainHandler, SLOT((loginScreenStateChanged(bool)))); connect(&domainHandler, &DomainHandler::domainURLChanged, [](QUrl domainURL){ setCrashAnnotation("domain", domainURL.toString().toStdString()); }); @@ -1212,6 +1213,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo connect(&domainHandler, &DomainHandler::domainConnectionRefused, this, &Application::domainConnectionRefused); nodeList->getDomainHandler().setErrorDomainURL(QUrl(REDIRECT_HIFI_ADDRESS)); + nodeList->getDomainHandler().setLoginScreenDomainURL(QUrl(LOGIN_SCREEN_HIFI_ADDRESS)); // We could clear ATP assets only when changing domains, but it's possible that the domain you are connected // to has gone down and switched to a new content set, so when you reconnect the cached ATP assets will no longer be valid. @@ -2277,6 +2279,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo connect(this, &QCoreApplication::aboutToQuit, this, &Application::addAssetToWorldMessageClose); connect(&domainHandler, &DomainHandler::domainURLChanged, this, &Application::addAssetToWorldMessageClose); connect(&domainHandler, &DomainHandler::redirectToErrorDomainURL, this, &Application::addAssetToWorldMessageClose); + connect(&domainHandler, &DomainHandler::redirectToLoginScreenDomainURL, this, &Application::addAssetToWorldMessageClose); updateSystemTabletMode(); @@ -2878,22 +2881,31 @@ void Application::initializeRenderEngine() { extern void setupPreferences(); static void addDisplayPluginToMenu(const DisplayPluginPointer& displayPlugin, int index, bool active = false); +void Application::showLoginScreen() { + auto accountManager = DependencyManager::get(); + if (!accountManager->isLoggedIn()) { + Setting::Handle{"loginDialogPoppedUp", false}.set(true); +// dialogsManager->showLoginScreenDialog(); + QJsonObject loginData = {}; + loginData["action"] = "login dialog shown"; + UserActivityLogger::getInstance().logAction("encourageLoginDialog", loginData); + if (qApp->isHMDMode()) { + // create web overlay. + auto nodeList = DependencyManager::get(); + auto loginScreenDomainURL = nodeList->getDomainHandler().getLoginScreenDomainURL(); + goToLoginScreenDomainURL(loginScreenDomainURL); + } + } + Setting::Handle{"loginDialogPoppedUp", false}.set(false); +} + void Application::initializeQml() { if (QThread::currentThread() != thread()) { QMetaObject::invokeMethod(this, "initializeQml"); return; } #if !defined(Q_OS_ANDROID) - auto accountManager = DependencyManager::get(); - auto dialogsManager = DependencyManager::get(); - if (!accountManager->isLoggedIn()) { - Setting::Handle{"loginDialogPoppedUp", false}.set(true); - dialogsManager->showLoginDialog(); - QJsonObject loginData = {}; - loginData["action"] = "login dialog shown"; - UserActivityLogger::getInstance().logAction("encourageLoginDialog", loginData); - } - Setting::Handle{"loginDialogPoppedUp", false}.set(false); + showLoginScreen(); #endif } @@ -3551,13 +3563,9 @@ void Application::setIsServerlessMode(bool serverlessDomain) { } } -void Application::loadServerlessDomain(QUrl domainURL, bool errorDomain) { +std::map Application::prepareServerlessDomainContents(QUrl domainURL) { if (QThread::currentThread() != thread()) { - QMetaObject::invokeMethod(this, "loadServerlessDomain", Q_ARG(QUrl, domainURL), Q_ARG(bool, errorDomain)); - return; - } - - if (domainURL.isEmpty()) { + QMetaObject::invokeMethod(this, "prepareServerlessDomainContents", Q_ARG(QUrl, domainURL)); return; } @@ -3584,13 +3592,61 @@ void Application::loadServerlessDomain(QUrl domainURL, bool errorDomain) { tmpTree->sendEntities(&_entityEditSender, getEntities()->getTree(), 0, 0, 0); } - std::map namedPaths = tmpTree->getNamedPaths(); - if (errorDomain) { - nodeList->getDomainHandler().loadedErrorDomain(namedPaths); - } else { - nodeList->getDomainHandler().connectedToServerless(namedPaths); + return tmpTree->getNamedPaths(); + +} + +void Application::loadServerlessDomain(QUrl domainURL) { + if (QThread::currentThread() != thread()) { + QMetaObject::invokeMethod(this, "loadServerlessDomain", Q_ARG(QUrl, domainURL)); + return; } + if (domainURL.isEmpty()) { + return; + } + + auto namedPaths = prepareServerlessDomainContents(domainURL); + auto nodeList = DependencyManager::get(); + + nodeList->getDomainHandler().connectedToServerless(namedPaths); + + _fullSceneReceivedCounter++; +} + +void Application::loadErrorDomain(QUrl domainURL) { + if (QThread::currentThread() != thread()) { + QMetaObject::invokeMethod(this, "loadErrorDomain", Q_ARG(QUrl, domainURL)); + return; + } + + if (domainURL.isEmpty()) { + return; + } + + auto namedPaths = prepareServerlessDomainContents(domainURL); + auto nodeList = DependencyManager::get(); + + nodeList->getDomainHandler().loadedErrorDomain(namedPaths); + + _fullSceneReceivedCounter++; +} + +void Application::loadLoginScreenDomain(QUrl domainURL) { + if (QThread::currentThread() != thread()) { + QMetaObject::invokeMethod(this, "loadLoginScreenDomain", Q_ARG(QUrl, domainURL)); + return; + } + + if (domainURL.isEmpty()) { + return; + } + + auto namedPaths = prepareServerlessDomainContents(domainURL); + auto nodeList = DependencyManager::get(); + + nodeList->getDomainHandler().loadedLoginScreenDomain(namedPaths); + _fullSceneReceivedCounter++; } @@ -6410,6 +6466,7 @@ void Application::updateWindowTitle() const { auto nodeList = DependencyManager::get(); auto accountManager = DependencyManager::get(); auto isInErrorState = nodeList->getDomainHandler().isInErrorState(); + auto isInLoginScreenState = nodeList->getDomainHandler().isInLoginScreenState(); QString buildVersion = " - " + (BuildInfo::BUILD_TYPE == BuildInfo::BuildType::Stable ? QString("Version") : QString("Build")) @@ -6419,6 +6476,8 @@ void Application::updateWindowTitle() const { QString connectionStatus = isInErrorState ? " (ERROR CONNECTING)" : nodeList->getDomainHandler().isConnected() ? "" : " (NOT CONNECTED)"; + // check for login state - login state needs empty connection status + connectionStatus = isInLoginScreenState ? "" : connectionStatus; QString username = accountManager->getAccountInfo().getUsername(); setCrashAnnotation("username", username.toStdString()); @@ -6427,6 +6486,8 @@ void Application::updateWindowTitle() const { if (isServerlessMode()) { if (isInErrorState) { currentPlaceName = "serverless: " + nodeList->getDomainHandler().getErrorDomainURL().toString(); + } else if (isInLoginScreenState) { + currentPlaceName = "High Fidelity Interface"; } else { currentPlaceName = "serverless: " + DependencyManager::get()->getDomainURL().toString(); } @@ -6497,11 +6558,27 @@ void Application::goToErrorDomainURL(QUrl errorDomainURL) { resetPhysicsReadyInformation(); setIsServerlessMode(errorDomainURL.scheme() != URL_SCHEME_HIFI); if (isServerlessMode()) { - loadServerlessDomain(errorDomainURL, true); + loadErrorDomain(errorDomainURL); } updateWindowTitle(); } +void Application::goToLoginScreenDomainURL(QUrl loginScreenDomainURL) { + // disable physics until we have enough information about our new location to not cause craziness. + resetPhysicsReadyInformation(); + setIsServerlessMode(loginScreenDomainURL.scheme() != URL_SCHEME_HIFI); + + // show avatar as a mesh and show hand controllers. + qApp->getMyAvatar()->setEnableMeshVisible(false); + DependencyManager::get()->requestShowHandControllers(); + // set into login screen state. + emit loginScreenStateChanged(true); + + if (isServerlessMode()) { + loadLoginScreenDomain(loginScreenDomainURL); + } + updateWindowTitle(); +} void Application::resettingDomain() { _notifiedPacketVersionMismatchThisDomain = false; diff --git a/interface/src/Application.h b/interface/src/Application.h index 8b061dda07..38ceebbb8b 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -335,7 +335,7 @@ signals: void uploadRequest(QString path); - void loginDialogPoppedUp(); + void loginScreenStateChanged(bool isInLoginScreenState); public slots: QVector pasteEntities(float x, float y, float z); @@ -345,6 +345,7 @@ public slots: void updateThreadPoolCount() const; void updateSystemTabletMode(); void goToErrorDomainURL(QUrl errorDomainURL); + void goToLoginScreenDomainURL(QUrl loginScreenDomainURL); Q_INVOKABLE void loadDialog(); Q_INVOKABLE void loadScriptURLDialog() const; @@ -357,6 +358,8 @@ public slots: void showDialog(const QUrl& widgetUrl, const QUrl& tabletUrl, const QString& name) const; + void showLoginScreen(); + // FIXME: Move addAssetToWorld* methods to own class? void addAssetToWorldFromURL(QString url); void addAssetToWorldFromURLRequestFinished(); @@ -433,7 +436,11 @@ public slots: void setPreferredCursor(const QString& cursor); void setIsServerlessMode(bool serverlessDomain); - void loadServerlessDomain(QUrl domainURL, bool errorDomain = false); + std::map prepareServerlessDomainContents(QUrl domainURL); + + void loadServerlessDomain(QUrl domainURL); + void loadErrorDomain(QUrl domainURL); + void loadLoginScreenDomain(QUrl domainURL); void setIsInterstitialMode(bool interstitialMode); void updateVerboseLogging(); diff --git a/interface/src/ConnectionMonitor.cpp b/interface/src/ConnectionMonitor.cpp index e86061b090..ff89d9a0d6 100644 --- a/interface/src/ConnectionMonitor.cpp +++ b/interface/src/ConnectionMonitor.cpp @@ -33,6 +33,7 @@ void ConnectionMonitor::init() { connect(&domainHandler, &DomainHandler::connectedToDomain, this, &ConnectionMonitor::stopTimer); connect(&domainHandler, &DomainHandler::domainConnectionRefused, this, &ConnectionMonitor::stopTimer); connect(&domainHandler, &DomainHandler::redirectToErrorDomainURL, this, &ConnectionMonitor::stopTimer); + connect(&domainHandler, &DomainHandler::redirectToLoginScreenDomainURL, this, &ConnectionMonitor::stopTimer); connect(this, &ConnectionMonitor::setRedirectErrorState, &domainHandler, &DomainHandler::setRedirectErrorState); _timer.setSingleShot(true); diff --git a/interface/src/ui/DialogsManager.cpp b/interface/src/ui/DialogsManager.cpp index 83601a2797..e2721f4ebb 100644 --- a/interface/src/ui/DialogsManager.cpp +++ b/interface/src/ui/DialogsManager.cpp @@ -25,6 +25,7 @@ #include "HMDToolsDialog.h" #include "LodToolsDialog.h" #include "LoginDialog.h" +#include "LoginScreenDialog.h" #include "OctreeStatsDialog.h" #include "PreferencesDialog.h" #include "UpdateDialog.h" @@ -117,6 +118,10 @@ void DialogsManager::showLoginDialog() { LoginDialog::showWithSelection(); } +void DialogsManager::showLoginScreenDialog() { + LoginScreenDialog::showWithSelection(); +} + void DialogsManager::showUpdateDialog() { UpdateDialog::show(); } @@ -203,4 +208,4 @@ void DialogsManager::showDomainConnectionDialog() { _domainConnectionDialog->show(); _domainConnectionDialog->raise(); -} +} \ No newline at end of file diff --git a/interface/src/ui/DialogsManager.h b/interface/src/ui/DialogsManager.h index 0633dec573..9b8a051ade 100644 --- a/interface/src/ui/DialogsManager.h +++ b/interface/src/ui/DialogsManager.h @@ -46,8 +46,12 @@ public slots: void hideAddressBar(); void showFeed(); void setDomainConnectionFailureVisibility(bool visible); + // toggles login screen that appears upon `File > Log In/Sign Up`. void toggleLoginDialog(); + // shows login screen that appears upon `File > Log In/Sign Up`. void showLoginDialog(); + // toggles login screen that appears upon application startup. + void showLoginScreenDialog(); void octreeStatsDetails(); void lodTools(); void hmdTools(bool showTools); diff --git a/interface/src/ui/LoginScreenDialog.cpp b/interface/src/ui/LoginScreenDialog.cpp index b7e1c875eb..8ffc332ef1 100644 --- a/interface/src/ui/LoginScreenDialog.cpp +++ b/interface/src/ui/LoginScreenDialog.cpp @@ -8,6 +8,4 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -LoginScreenDialog::LoginScreenDialog() { - -} +#include "LoginScreenDialog.h" diff --git a/libraries/networking/src/AddressManager.cpp b/libraries/networking/src/AddressManager.cpp index f8ab8ceaec..137ce2ad4a 100644 --- a/libraries/networking/src/AddressManager.cpp +++ b/libraries/networking/src/AddressManager.cpp @@ -32,6 +32,7 @@ const QString DEFAULT_HIFI_ADDRESS = "file:///~/serverless/tutorial.json"; const QString REDIRECT_HIFI_ADDRESS = "file:///~/serverless/redirect.json"; +const QString LOGIN_SCREEN_HIFI_ADDRESS = "file:///~/serverless/login.json"; const QString ADDRESS_MANAGER_SETTINGS_GROUP = "AddressManager"; const QString SETTINGS_CURRENT_ADDRESS_KEY = "address"; @@ -162,11 +163,15 @@ void AddressManager::storeCurrentAddress() { // url.scheme() == URL_SCHEME_HTTP || // url.scheme() == URL_SCHEME_HTTPS || bool isInErrorState = DependencyManager::get()->getDomainHandler().isInErrorState(); + bool isInLoginScreenState = DependencyManager::get()->getDomainHandler().isInLoginScreenState(); + if (isInLoginScreenState) { + qCWarning(networking) << "Ignoring attempt to save current address because in login screen domain:" << url; + } if (isConnected()) { if (isInErrorState) { // save the last address visited before the problem url. currentAddressHandle.set(lastAddress()); - } else { + } else { currentAddressHandle.set(url); } } else { @@ -824,8 +829,10 @@ bool AddressManager::setDomainInfo(const QUrl& domainURL, LookupTrigger trigger) bool emitHostChanged { false }; // Check if domain handler is in error state. always emit host changed if true. bool isInErrorState = DependencyManager::get()->getDomainHandler().isInErrorState(); + // Check if domain handler is in login screen state. always emit host changed if true. + bool isInLoginScreenState = DependencyManager::get()->getDomainHandler().isInLoginScreenState(); - if (domainURL != _domainURL || isInErrorState) { + if (domainURL != _domainURL || isInErrorState || isInLoginScreenState) { addCurrentAddressToHistory(trigger); emitHostChanged = true; } diff --git a/libraries/networking/src/AddressManager.h b/libraries/networking/src/AddressManager.h index 5318822cdc..07c8e0f934 100644 --- a/libraries/networking/src/AddressManager.h +++ b/libraries/networking/src/AddressManager.h @@ -24,6 +24,7 @@ extern const QString DEFAULT_HIFI_ADDRESS; extern const QString REDIRECT_HIFI_ADDRESS; +extern const QString LOGIN_SCREEN_HIFI_ADDRESS; const QString SANDBOX_HIFI_ADDRESS = "hifi://localhost"; const QString INDEX_PATH = "/"; diff --git a/libraries/networking/src/DomainHandler.cpp b/libraries/networking/src/DomainHandler.cpp index 615546b410..4140ff1a64 100644 --- a/libraries/networking/src/DomainHandler.cpp +++ b/libraries/networking/src/DomainHandler.cpp @@ -62,6 +62,9 @@ DomainHandler::DomainHandler(QObject* parent) : // stop the refresh timer if redirected to the error domain connect(this, &DomainHandler::redirectToErrorDomainURL, &_apiRefreshTimer, &QTimer::stop); + + // stop the refresh timer if redirected to the login screen domain + connect(this, &DomainHandler::redirectToLoginScreenDomainURL, &_apiRefreshTimer, &QTimer::stop); } void DomainHandler::disconnect() { @@ -113,7 +116,7 @@ void DomainHandler::softReset() { QMetaObject::invokeMethod(&_settingsTimer, "stop"); // restart the API refresh timer in case we fail to connect and need to refresh information - if (!_isInErrorState) { + if (!_isInErrorState || !_isInLoginScreenState) { QMetaObject::invokeMethod(&_apiRefreshTimer, "start"); } } @@ -125,6 +128,9 @@ void DomainHandler::hardReset() { _isInErrorState = false; emit redirectErrorStateChanged(_isInErrorState); + _isInLoginScreenState = false; + emit loginScreenStateChanged(_isInLoginScreenState); + qCDebug(networking) << "Hard reset in NodeList DomainHandler."; _pendingDomainID = QUuid(); _iceServerSockAddr = HifiSockAddr(); @@ -363,6 +369,17 @@ void DomainHandler::loadedErrorDomain(std::map namedPaths) { DependencyManager::get()->goToViewpointForPath(viewpoint, QString()); } +void DomainHandler::loadedLoginScreenDomain(std::map namedPaths) { + auto lookup = namedPaths.find("/"); + QString viewpoint; + if (lookup != namedPaths.end()) { + viewpoint = lookup->second; + } else { + viewpoint = DOMAIN_SPAWNING_POINT; + } + DependencyManager::get()->goToViewpointForPath(viewpoint, QString()); +} + void DomainHandler::setRedirectErrorState(QUrl errorUrl, QString reasonMessage, int reasonCode, const QString& extraInfo) { _lastDomainConnectionError = reasonCode; if (getInterstitialModeEnabled() && isHardRefusal(reasonCode)) { @@ -376,6 +393,12 @@ void DomainHandler::setRedirectErrorState(QUrl errorUrl, QString reasonMessage, } } +void DomainHandler::redirectToLoginScreenDomainURL() { + _isInLoginScreenState = true; + qCDebug(networking) << "Redirecting user to " << _loginScreenDomainURL; + +} + void DomainHandler::requestDomainSettings() { qCDebug(networking) << "Requesting settings from domain server"; diff --git a/libraries/networking/src/DomainHandler.h b/libraries/networking/src/DomainHandler.h index ddd23339df..9bfbe26db0 100644 --- a/libraries/networking/src/DomainHandler.h +++ b/libraries/networking/src/DomainHandler.h @@ -58,6 +58,9 @@ public: int getLastDomainConnectionError() { return _lastDomainConnectionError; } + QUrl getLoginScreenDomainURL(){ return _loginScreenDomainURL; } + void setLoginScreenDomainURL(const QUrl& url); + const QHostAddress& getIP() const { return _sockAddr.getAddress(); } void setIPToLocalhost() { _sockAddr.setAddress(QHostAddress(QHostAddress::LocalHost)); } @@ -93,6 +96,8 @@ public: void loadedErrorDomain(std::map namedPaths); + void loadedLoginScreenDomain(std::map namedPaths); + QString getViewPointFromNamedPath(QString namedPath); bool hasSettings() const { return !_settingsObject.isEmpty(); } @@ -179,6 +184,7 @@ public slots: void setRedirectErrorState(QUrl errorUrl, QString reasonMessage = "", int reason = -1, const QString& extraInfo = ""); bool isInErrorState() { return _isInErrorState; } + bool isInLoginScreenState() { return _isInLoginScreenState; } private slots: void completedHostnameLookup(const QHostInfo& hostInfo); @@ -205,6 +211,9 @@ signals: void redirectToErrorDomainURL(QUrl errorDomainURL); void redirectErrorStateChanged(bool isInErrorState); + void redirectToLoginScreenDomainURL(); + void loginScreenStateChanged(bool isInLoginScreenState); + void limitOfSilentDomainCheckInsReached(); private: @@ -218,6 +227,7 @@ private: Node::LocalID _localID; QUrl _domainURL; QUrl _errorDomainURL; + QUrl _loginScreenDomainURL; HifiSockAddr _sockAddr; QUuid _assignmentUUID; QUuid _connectionToken; @@ -227,6 +237,7 @@ private: NetworkPeer _icePeer; bool _isConnected { false }; bool _isInErrorState { false }; + bool _isInLoginScreenState { false }; QJsonObject _settingsObject; QString _pendingPath; QTimer _settingsTimer; diff --git a/scripts/system/marketplaces/marketplaces.js b/scripts/system/marketplaces/marketplaces.js index cca535a064..ef5472271e 100644 --- a/scripts/system/marketplaces/marketplaces.js +++ b/scripts/system/marketplaces/marketplaces.js @@ -917,6 +917,7 @@ var onQmlMessageReceived = function onQmlMessageReceived(message) { Menu.setIsOptionChecked("Disable Preview", true); setTabletVisibleInSecondaryCamera(false); } +<<<<<<< Updated upstream break; case 'maybeEnableHmdPreview': maybeEnableHMDPreview(); @@ -962,6 +963,47 @@ var onQmlMessageReceived = function onQmlMessageReceived(message) { Script.update.connect(updateOverlays); isUpdateOverlaysWired = true; } +======= + } + +<<<<<<< Updated upstream + // Function Name: onTabletScreenChanged() + // + // Description: + // -Called when the TabletScriptingInterface::screenChanged() signal is emitted. The "type" argument can be either the string + // value of "Home", "Web", "Menu", "QML", or "Closed". The "url" argument is only valid for Web and QML. + var onWalletScreen = false; + var onCommerceScreen = false; + function onTabletScreenChanged(type, url) { + onMarketplaceScreen = type === "Web" && url.indexOf(MARKETPLACE_URL) !== -1; + var onWalletScreenNow = url.indexOf(MARKETPLACE_WALLET_QML_PATH) !== -1; + var onCommerceScreenNow = type === "QML" && (url.indexOf(MARKETPLACE_CHECKOUT_QML_PATH) !== -1 || url === MARKETPLACE_PURCHASES_QML_PATH + || url.indexOf(MARKETPLACE_INSPECTIONCERTIFICATE_QML_PATH) !== -1); + + if ((!onWalletScreenNow && onWalletScreen) || (!onCommerceScreenNow && onCommerceScreen)) { // exiting wallet or commerce screen + maybeEnableHMDPreview(); + } +======= + // console.debug(ui.buttonName + " app reports: Tablet screen changed.\nNew screen type: " + type + + // "\nNew screen URL: " + url + "\nCurrent app open status: " + ui.isOpen + "\n"); +}; + +function notificationDataProcessPage(data) { + return data.data.updates; +} +>>>>>>> Stashed changes + + onCommerceScreen = onCommerceScreenNow; + onWalletScreen = onWalletScreenNow; + wireEventBridge(onMarketplaceScreen || onCommerceScreen || onWalletScreen); + + if (url === MARKETPLACE_PURCHASES_QML_PATH) { + sendToQml({ + method: 'updatePurchases', + referrerURL: referrerURL, + filterText: filterText + }); +>>>>>>> Stashed changes } break; case 'disable_ChooseRecipientNearbyMode':