From 45921a5c8db47ed6e5266f9903eee71acb9da7d2 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 20 Jun 2016 14:15:45 -0700 Subject: [PATCH 01/22] Restore split behavior for inputs/displays on quit --- plugins/openvr/src/OpenVrDisplayPlugin.cpp | 5 ++++- plugins/openvr/src/OpenVrHelpers.cpp | 8 +++++++- plugins/openvr/src/ViveControllerManager.cpp | 4 ++++ 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/plugins/openvr/src/OpenVrDisplayPlugin.cpp b/plugins/openvr/src/OpenVrDisplayPlugin.cpp index 4e84c6d0fa..a532261014 100644 --- a/plugins/openvr/src/OpenVrDisplayPlugin.cpp +++ b/plugins/openvr/src/OpenVrDisplayPlugin.cpp @@ -161,7 +161,10 @@ static bool isBadPose(vr::HmdMatrix34_t* mat) { bool OpenVrDisplayPlugin::beginFrameRender(uint32_t frameIndex) { handleOpenVrEvents(); - + if (openVrQuitRequested()) { + QMetaObject::invokeMethod(qApp, "quit"); + return false; + } double displayFrequency = _system->GetFloatTrackedDeviceProperty(vr::k_unTrackedDeviceIndex_Hmd, vr::Prop_DisplayFrequency_Float); double frameDuration = 1.f / displayFrequency; double vsyncToPhotons = _system->GetFloatTrackedDeviceProperty(vr::k_unTrackedDeviceIndex_Hmd, vr::Prop_SecondsFromVsyncToPhotons_Float); diff --git a/plugins/openvr/src/OpenVrHelpers.cpp b/plugins/openvr/src/OpenVrHelpers.cpp index c93a2178b5..ee61a07da6 100644 --- a/plugins/openvr/src/OpenVrHelpers.cpp +++ b/plugins/openvr/src/OpenVrHelpers.cpp @@ -34,6 +34,11 @@ using Lock = std::unique_lock; static int refCount { 0 }; static Mutex mutex; static vr::IVRSystem* activeHmd { nullptr }; +static bool _openVrQuitRequested { false }; + +bool openVrQuitRequested() { + return _openVrQuitRequested; +} static const uint32_t RELEASE_OPENVR_HMD_DELAY_MS = 5000; @@ -99,6 +104,7 @@ void releaseOpenVrSystem() { qCDebug(displayplugins) << "OpenVR: zero refcount, deallocate VR system"; #endif vr::VR_Shutdown(); + _openVrQuitRequested = false; activeHmd = nullptr; } } @@ -257,8 +263,8 @@ void handleOpenVrEvents() { while (activeHmd->PollNextEvent(&event, sizeof(event))) { switch (event.eventType) { case vr::VREvent_Quit: + _openVrQuitRequested = true; activeHmd->AcknowledgeQuit_Exiting(); - QMetaObject::invokeMethod(qApp, "quit"); break; case vr::VREvent_KeyboardDone: diff --git a/plugins/openvr/src/ViveControllerManager.cpp b/plugins/openvr/src/ViveControllerManager.cpp index 85feebda11..930b3dd450 100644 --- a/plugins/openvr/src/ViveControllerManager.cpp +++ b/plugins/openvr/src/ViveControllerManager.cpp @@ -214,6 +214,10 @@ void ViveControllerManager::renderHand(const controller::Pose& pose, gpu::Batch& void ViveControllerManager::pluginUpdate(float deltaTime, const controller::InputCalibrationData& inputCalibrationData) { auto userInputMapper = DependencyManager::get(); handleOpenVrEvents(); + if (openVrQuitRequested()) { + deactivate(); + return; + } // because update mutates the internal state we need to lock userInputMapper->withLock([&, this]() { From cea0e182c0b24928aae74352355fe552167dcf4c Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 14 Jul 2016 11:02:32 -0700 Subject: [PATCH 02/22] Interface login through steam --- interface/resources/images/steam-sign-in.png | Bin 0 -> 5861 bytes interface/resources/qml/LoginDialog.qml | 50 +++-- interface/src/Application.cpp | 7 +- interface/src/main.cpp | 9 +- interface/src/ui/LoginDialog.cpp | 15 ++ interface/src/ui/LoginDialog.h | 1 + libraries/networking/src/AccountManager.cpp | 23 +++ libraries/networking/src/AccountManager.h | 1 + .../src/steamworks-wrapper/SteamClient.cpp | 171 ++++++++++++++++++ .../src/steamworks-wrapper/SteamClient.h | 15 +- 10 files changed, 275 insertions(+), 17 deletions(-) create mode 100644 interface/resources/images/steam-sign-in.png diff --git a/interface/resources/images/steam-sign-in.png b/interface/resources/images/steam-sign-in.png new file mode 100644 index 0000000000000000000000000000000000000000..148e6ab280472d5b4b3f069a2c267790e19d13c2 GIT binary patch literal 5861 zcmVb^P)`OA)6Ov3q zNJ0{}gg}rTBA|j15CJI&ZYUtNb!oLerCO9)D{A@erc{9{{w)f!2#6s276=3r!jg~> zvqBcK%w(3#{(tApWXOhz7B&74C(mKd+<V9tuRpDPgM%0}v;zKqfw#7;2bD%$J?gTxT*0~o(&=<^5M@d+N*Ye1sk!#n z4)%cJs|Z1;It~G;WgN`z011u87o`nnVX)i+v8NQBsRj;*3%vu9QA-$g3rMHa0lUKj zm(z7?2YXOyGS|TA=inGg#ta+ujh!dnGaF8qgM&!@e{#iCD?n-vf=1E{Qi&24n+baB zRX9`)P=$SW!Bon8F>m;5h!4Gue=n-Z!j?0yAu=F|AAe>0M3}8j-)Zb8Cw$1q`{LZ+ zy6nraaX1{`tdWe-GPE5oI|tGE6VgaiwFtfCqcLar1JL;S!)~{+1wjxAaM~TXR$GI^ zxm!``Itg{S<6DnEEM^8G{gbeK8v{&_;juGtt*L_7+_Js@)xG~^?}Bdkbz?&sdGu6X zryZ6oS(G4?D|*@Ob~wniI$h46jA^x%1!Hl>>j>}`-FEqd&p`yX8N zPFPr&HYqUyp&`K#1c9HENv5N$tQemhTm>Qe3Pj?b38J}1is$G2m1`hdoFIs>arfU* zVa*zxpO4iz(%W=7WA0`c%i>Kzkg@0^V27Ag2QZt> zuvxA6XwM3meZEGJq(4dW?eI|spk7yvbESt-tvrL(pFfL5cfSb-^;P@$V5D{qvW)8> zR(9<|f_x&O4eF2F(l5#FxV+%Dcpt_mOcp(Y)RDZ+Oe5>o!ZVyVXt&nL?)2rRm8>Qc zM#Lo~ZAczC0CBN>@YUIK*!Ul$voMd%~=2C3KW){#{*NIgSFC^57v{a z?V1u96BeMcu^uv+3_Fjlg-Kn4@!Fqb>FkwAP8^9CZ34NEaacHQImU)AfmKEt^mqVRGtva+(iN=!^j9WYR5W8`m0ZF?I4BZ25d0E=jlcD2)s>48fBRtVB&s6>4j$vElS@5v>}ANALR` zu2hzTn-IoY$z3pyp;D=_?aQ?&wC=@&Bj19rTthBHgl+p*quTG}O}nqCpnfQ?yNH)& zZO8F~&Dfi_?xwCgCagaScLqQb7#zAJI!X)1PIL3lK^qm7I%IINHyOY`Z8i+*Ka~3& zT|)x~Cym9qFOLGDHIOQMhK-E~iYHQIghVVsUhy$5!PCb*&Ov3q(rvG zq43Z_9M9X18RHj|R+HrlN=s1)SOj5lYq zzsy<7>-SmgP8<11Ms@^2&ZJmxY+@!yB^67F(zXZE$<0yA@+=k$m+}FLLyIWt|wSGvuJsnM?Wg@ySiAW9-J-SaTzjv3@ErbI56A5k7j}GGa zQjwBNwVl4(?Dn5j28$&(m^Bp>O_VWwEv`LR*>Gc0Wdiaw-r55IT!IKU8eygPkm^a}?5;6&_RyzkSA|Meqml9DJ_z*NTHSzNeP1POd7?m`OSJocf=T7{6aV`{6 z&G)`GHV2!F&3U6fb_zW>kQPhxrmI!eP%4xN@DI>l$iGCuxi_Sxx;MZBD48D{tJH^W zkexow&1MQ&^e_?gOYA!skIh(tpQZf~k>+$XUy%{LceAeVqoxE-M^t1YvDHStAR`6& zNpV9Uw)kTA*>}156e#eud)C3gX6A(j(tC5)68uVxPMwTK3boi;su~MB%#jp1oL9~q zTd~p~qIzS;8=SW~Y#dDS9d}JRXEK?d5AW3r!6Cu;x}*eE)iqG7ReTeeNoppbm|<#3 z)p2m`Zga)Hvo?#R*m0}P%E4AB)#w*brnk>TNDP6ft*nRHriV!8_E9&Z3U#4)c*b%v z?N|7{**${A?$u8gfue>ZIF+{-eL@GrNA1s@q?ox8T|GWNxDpm+4W=aj0urYZ&6Z}E zi7e$*?|@5Y^Ug6O?oLb{z7!FGaYUr#Xf)Iyt?ym@_?)r7;m0nNWn#w2XRv7UoAmiK zCZs%o(}lZ{q#c3hXMV_!#f7IL^WtZ?YsjN`j*jik`3Qqz#$)-st-Q_7zxv=V+;iI# z{Cb{}yK)AThb}~PNPj+8%NVWqKqXV6HeU|O@)v(sx9p{tR^*<|dogWDDuxeB!-f0; zoIG_Jz7!-!X|)Io4WSLPa=O5i&-BS;MG!f;<76O;L?SNf?0}eSfP*&2LOx5t;DPB# z8$1c6Wd%5WVHd8NFF+E|3{ED$Yd%#k#*&N`6mHbQLIJ&t>`V(8V{RZSA_=3-3vsmg zU-%^JcaYhGAccw~*a(ZH0b+?5lMcc4{vWi zx(Y-4-pSkl{QOtw7d-;^jeZ7SoLa;8!PuB=s9fLD!2?4h?}J$CgZk=f zJ~q3@mT-xQQ**P0OzuF;4SyX+&TK@rr2uAu<`OFqs~LsKqaK36U?kxxp_tN#V(70> z={gO;<-ESZ?GofXSofT(ZY)QTM(fG8xYK4P0+RKqZYbyMS4FX@u~~<&tIqRtO1Z{+ zz0>7t(`J2ZX-u9GqP}ix=k8F`Si#5eSlKq29UC*PEkJs}T)2G29|}%poq9beFc2&x zQ7V;Ox_2D;8_cRoxI}hj76hSx)a{6mPK8{i;H1apYPDb%a1&!>0J8v_X(WAxL@MQ} zFcS%gl-eWGGB8#=4OKOzICT0G)Y|hQ(b&89nnQCO(nrt5<;$1dAq7!zcvv<2&geMX z1PiwaB8*6x$%T(sv6%bz(z0@{#Vj#UR&fC*D*p|!pUs=}ZeQ3&xAt4@+ivi$A2XVC z91su*&p75hpAv3#@z+7Ej zQ{hG20&3`v>{UrnHg7}>lU$^aBO#U9NR zxVA9r&;IN*xn9@AV>drdIA-7d8#J2?$jLu|oZ{VZYDj}`@TAnClVMiIb0{t@cE`5t zrUZdYrOV?uoF47u7J>PAb2C{fmnWWdaWGlP#qK9FXDiAbCn525-Z1RQ%HNHp)BcQ^ zW1dAxwMR3YxGun+Hn)bY#`xEs<#_1M<(P8YLR=`##DScRP!mYwl4s+k`6RrJ72fMN z9$JN8-~T?={OUY6(R@6om+Q1?x1NKon-Nc8blSjglzxdi*cCsufqb3~oxM6~YZ5_j z2_sfF4skK5p22Ny6Gz&>6p{hyR#pO)Hc>_z$&b<2GQiomEKE?T)m*xY%W{xgxEHmy z0!VylgLO(o`457>IvjmthLR-+q_C&a?TeibkCeKBE@5X`Ljo5kO{VuPON@OV79?&(Ako&vhGwRXR z`>zhhg$%xk)TAJx_b6!mgUFZJJ&%*X0c6@J@|ZWKjcfLB*q zvjY2!k&og2+n?p_^IvD;?^~YXn%Pxh>n_?E*fo%Lv5%|o)W&beD0LD9i2I^%>)B_rpvErWZ(373RMf$ZYd@@`22SL@I++Cgl%+MS>IO3l5;9?hNlA9W)e4 zvFSw0OkQnl4lmkj8+MOoUt9atWcXmju7x2!BqbSX^a zi}G=)FNpyOiueIblJ)wllljs)Q`CevL1(5=MqSD|miAG7& z5ttf{hzJ`%gvRXEOodW`iK>N1gNpTPSvEwov6IFY{wcAsmc?&!coGe$jv^dYn0qx3_w)r2zz`?3Al z`)F*s#?L=>|J#VyCUcM-6tJ@Jg}DQZ)r?oxEr8xw$NMGqPQ&7R|Hv&1%NDg1y|ErI zubD^I#L{68o|*GkM25uS<+bzCWUB9Qe#ZEv7&rJ{d~squcAs2-Jyh|J#0&G^gU(Qg zRUbcz@KCTUnipW0&89O?}Nv*<07UM?Ql2cfEk{ zz!(mEpl=vI78jo4?W2&XsH&k+1)x`8Zv^>;dyc6%Xf6GG6#o2tNPyOR4X^Cck4xw< zcX(hdh9*tqKn_iu(COZU1w`{Pr;lC4#KU`h&V;A=b=uH)icO6uuPSV_K70E(vQsw7 zf&3o$IWxOz9V+ZcQF`hGLKKM@7?%#Mwx2sWZ?Sp_kyI+UU+19XJa(i%rYV9`%F|df zsf5gpfKvSth?F-D>eEwaa!q@A%>opZX2ah%gm2Ed%bDIjE7vdKVbhqDsd(bP*Kqpc zKK$jAUwMSu+U5}$_fI9+cxBD}>&qhTWiLauFQb$1;o%Z1w-1?#{iil|qBQRD1AId< zW%vT@IJOQ!nlPmGo8&#uI78{x0$y8V)U|2l!S(k`_XOJfYdD7km(D|+r@_ena}Y~0 zsfA)bCf!b_+q}EuQ5Tm$nM_U^c!|f65n-|Xbq(UJ{ZH|i^go^4S)az<^Z9~wU zHct-I>IIBxe+MGxnTN%}EOG8m4GP>`cQ)s!K^bJ8P0*3)?GrJOzzU;ywyNEGbJxq= zqaVg+N7iC``Vy}3p1hIwU7hwAiMpeaKg4rI&TT{ll2V7`7dG&Oy-Xs&WWEM}e}6K) zYA6*7s8uQi1_V%N3$hBgAXE{Lu+T`G!M zNB&cS_I+Dt2|B%3&t4`(r((^rEMDJVb`m27PU+CMPsAXE2gl%S(Q*7|&nh0oPZ~D& zhGSOOmvfUo_s(ZAlEyPNH*p^=qWGz^dvSEjM>-rg)kk)x+9Y~hDmsP8$S4$jorMp# zzJ$}cpL0+Rh8mp8*?~_Fy-Lhej7Mg^2wg)R%IdQ{8J-)DyZ!Jwyt)1tIL_W?xKaR> z(w8=LHtwJJ%Z~kBZPR0&Rrf291~PN`yp~lJ5NWFK(C?1he#ZOmKeZW$PJhO=cI2SR z9r`gQ&C2e~e-n5H%ph&lr~~oY;k7W+Jj~>Gb|3bxe*59pNXHNVn-5yguB_E$UK25E z`cizn^{+TvvJW{Wds;X+diliR$p>G9zR85o54{Jyv#MJ|AItrMS62E)CF6~!Ho9@N3K`Gx+d4mQ**P z@=7s(E*hnchgz*cd3h-|?tB|pZFybhOPQa#d+dXVAQQLa$OkYO8!;f({Yxr?sj=f4 zTc;#DTfgU+QszTUGur!BK8x>a>MOh{&6I>OT&q|((mNuF`%xCw2!aCRhfJsVI;X>& zN@BnN*|myTc^nR&+KMJa1Ie!F`n>IdbaaQca)55hI%~y%6Kw`Zqjpa`eW`VA=_TZzLT4Ho880P&+owaw0rT< z&Q&m)^_~Q{n=~opJ~WOFFaFK_t1P8lP0U>0#$UI`=!U<>YAG6x=EwaNme_$>dm%QT zcnfI%x~U9pp5}j3X)-k8`Bk%#F>V17loXzHxLR9^Z3otpZ!7H3zwAm8PUd}yukw#| zx_)*oJ1?-be5*I}^rSs3Ok&rtSh%vf7}pxBu;=*4oUpJ`Tz&yt_PtLU7fb9lgsg-6 zIc09aaSmE(<)t=rG6sG4%nttP^t_hZ9!R09ry4#!KCbZ(h2U1{x#iFYwcRtVF6XVy z>dD2?9oEVMVvAk^sgLc}j`hG|Gf3TUUvy #include #include +#include #include #include #include #include #include -#include +#include #include #include -#include +#include #include #include #include @@ -2910,6 +2911,8 @@ void Application::idle(float nsecsElapsed) { PROFILE_RANGE(__FUNCTION__); + SteamClient::runCallbacks(); + float secondsSinceLastUpdate = nsecsElapsed / NSECS_PER_MSEC / MSECS_PER_SECOND; // If the offscreen Ui has something active that is NOT the root, then assume it has keyboard focus. diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 8fc0384aee..527b7f2331 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -8,6 +8,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include + #include #include #include @@ -20,12 +22,13 @@ #include #include +#include + #include "AddressManager.h" #include "Application.h" #include "InterfaceLogging.h" #include "UserActivityLogger.h" #include "MainWindow.h" -#include #ifdef HAS_BUGSPLAT #include @@ -137,6 +140,8 @@ int main(int argc, const char* argv[]) { // or in the main window ctor, before GL startup. Application::initPlugins(arguments); + SteamClient::init(); + int exitCode; { QSettings::setDefaultFormat(QSettings::IniFormat); @@ -202,6 +207,8 @@ int main(int argc, const char* argv[]) { Application::shutdownPlugins(); + SteamClient::shutdown(); + qCDebug(interfaceapp, "Normal exit."); #if !defined(DEBUG) && !defined(Q_OS_LINUX) // HACK: exit immediately (don't handle shutdown callbacks) for Release build diff --git a/interface/src/ui/LoginDialog.cpp b/interface/src/ui/LoginDialog.cpp index 80d52b7a07..8240340381 100644 --- a/interface/src/ui/LoginDialog.cpp +++ b/interface/src/ui/LoginDialog.cpp @@ -14,6 +14,7 @@ #include #include +#include #include "AccountManager.h" #include "DependencyManager.h" @@ -82,6 +83,20 @@ void LoginDialog::login(const QString& username, const QString& password) { DependencyManager::get()->requestAccessToken(username, password); } +void LoginDialog::loginThroughSteam() { + qDebug() << "Attempting to login through Steam"; + setStatusText("Logging in..."); + + SteamClient::requestTicket([this](Ticket ticket) { + if (ticket.isNull()) { + setStatusText("Steam client not logged into an account"); + return; + } + + DependencyManager::get()->requestAccessTokenWithSteam(ticket); + }); +} + void LoginDialog::openUrl(const QString& url) { qDebug() << url; QDesktopServices::openUrl(url); diff --git a/interface/src/ui/LoginDialog.h b/interface/src/ui/LoginDialog.h index 25ecf45898..0dd4b5e96f 100644 --- a/interface/src/ui/LoginDialog.h +++ b/interface/src/ui/LoginDialog.h @@ -41,6 +41,7 @@ protected: void handleLoginFailed(); Q_INVOKABLE void login(const QString& username, const QString& password); + Q_INVOKABLE void loginThroughSteam(); Q_INVOKABLE void openUrl(const QString& url); private: QString _statusText; diff --git a/libraries/networking/src/AccountManager.cpp b/libraries/networking/src/AccountManager.cpp index c4bfae7cac..8c0fa5ed92 100644 --- a/libraries/networking/src/AccountManager.cpp +++ b/libraries/networking/src/AccountManager.cpp @@ -505,6 +505,29 @@ void AccountManager::requestAccessToken(const QString& login, const QString& pas connect(requestReply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(requestAccessTokenError(QNetworkReply::NetworkError))); } +void AccountManager::requestAccessTokenWithSteam(QByteArray authSessionTicket) { + QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance(); + + QNetworkRequest request; + request.setHeader(QNetworkRequest::UserAgentHeader, _userAgentGetter()); + + QUrl grantURL = _authURL; + grantURL.setPath("/oauth/token"); + + const QString ACCOUNT_MANAGER_REQUESTED_SCOPE = "owner"; + + QByteArray postData; + postData.append("grant_type=password&"); + postData.append("ticket=" + QUrl::toPercentEncoding(authSessionTicket) + "&"); + postData.append("scope=" + ACCOUNT_MANAGER_REQUESTED_SCOPE); + + request.setUrl(grantURL); + request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded"); + + QNetworkReply* requestReply = networkAccessManager.post(request, postData); + connect(requestReply, &QNetworkReply::finished, this, &AccountManager::requestAccessTokenFinished); + connect(requestReply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(requestAccessTokenError(QNetworkReply::NetworkError))); +} void AccountManager::requestAccessTokenFinished() { QNetworkReply* requestReply = reinterpret_cast(sender()); diff --git a/libraries/networking/src/AccountManager.h b/libraries/networking/src/AccountManager.h index 846cdb6220..eb4d224501 100644 --- a/libraries/networking/src/AccountManager.h +++ b/libraries/networking/src/AccountManager.h @@ -96,6 +96,7 @@ public: public slots: void requestAccessToken(const QString& login, const QString& password); + void requestAccessTokenWithSteam(QByteArray authSessionTicket); void requestAccessTokenFinished(); void requestProfileFinished(); diff --git a/libraries/steamworks-wrapper/src/steamworks-wrapper/SteamClient.cpp b/libraries/steamworks-wrapper/src/steamworks-wrapper/SteamClient.cpp index 0f06e03672..1dbfc0ce00 100644 --- a/libraries/steamworks-wrapper/src/steamworks-wrapper/SteamClient.cpp +++ b/libraries/steamworks-wrapper/src/steamworks-wrapper/SteamClient.cpp @@ -11,9 +11,180 @@ #include "SteamClient.h" +#include +#include + +#include + +#if defined(__GNUC__) && !defined(__clang__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Woverloaded-virtual" +#endif + #include +#if defined(__GNUC__) && !defined(__clang__) +#pragma GCC diagnostic pop +#endif + + +static const Ticket INVALID_TICKET = Ticket(); + +class SteamTicketRequests { +public: + SteamTicketRequests(); + ~SteamTicketRequests(); + + HAuthTicket startRequest(TicketRequestCallback callback); + void stopRequest(HAuthTicket authTicket); + + STEAM_CALLBACK(SteamTicketRequests, onGetAuthSessionTicketResponse, + GetAuthSessionTicketResponse_t, _getAuthSessionTicketResponse); + +private: + void stopAll(); + + struct PendingTicket { + HAuthTicket authTicket; + Ticket ticket; + TicketRequestCallback callback; + }; + + std::vector _pendingTickets; +}; + +SteamTicketRequests::SteamTicketRequests() : + _getAuthSessionTicketResponse(this, &SteamTicketRequests::onGetAuthSessionTicketResponse) +{ +} + +SteamTicketRequests::~SteamTicketRequests() { + stopAll(); +} + +HAuthTicket SteamTicketRequests::startRequest(TicketRequestCallback callback) { + static const uint32 MAX_TICKET_SIZE { 1024 }; + uint32 ticketSize { 0 }; + char ticket[MAX_TICKET_SIZE]; + + auto authTicket = SteamUser()->GetAuthSessionTicket(ticket, MAX_TICKET_SIZE, &ticketSize); + qDebug() << "Got Steam auth session ticket:" << authTicket; + + if (authTicket == k_HAuthTicketInvalid) { + qWarning() << "Auth session ticket is invalid."; + callback(INVALID_TICKET); + } else { + PendingTicket pendingTicket{ authTicket, QByteArray(ticket, ticketSize).toHex(), callback }; + _pendingTickets.push_back(pendingTicket); + } + + return authTicket; +} + +void SteamTicketRequests::stopRequest(HAuthTicket authTicket) { + auto it = std::find_if(_pendingTickets.begin(), _pendingTickets.end(), [&authTicket](const PendingTicket& pendingTicket) { + return pendingTicket.authTicket == authTicket; + }); + + if (it != _pendingTickets.end()) { + SteamUser()->CancelAuthTicket(it->authTicket); + it->callback(INVALID_TICKET); + _pendingTickets.erase(it); + } +} + +void SteamTicketRequests::stopAll() { + auto steamUser = SteamUser(); + if (steamUser) { + for (const auto& pendingTicket : _pendingTickets) { + steamUser->CancelAuthTicket(pendingTicket.authTicket); + pendingTicket.callback(INVALID_TICKET); + } + } + _pendingTickets.clear(); +} + +void SteamTicketRequests::onGetAuthSessionTicketResponse(GetAuthSessionTicketResponse_t* pCallback) { + auto authTicket = pCallback->m_hAuthTicket; + + auto it = std::find_if(_pendingTickets.begin(), _pendingTickets.end(), [&authTicket](const PendingTicket& pendingTicket) { + return pendingTicket.authTicket == authTicket; + }); + + + if (it != _pendingTickets.end()) { + + if (pCallback->m_eResult == k_EResultOK) { + qDebug() << "Got steam callback, auth session ticket is valid. Send it." << authTicket; + it->callback(it->ticket); + } else { + qWarning() << "Steam auth session ticket callback encountered an error:" << pCallback->m_eResult; + it->callback(INVALID_TICKET); + } + + _pendingTickets.erase(it); + } else { + qWarning() << "Could not find steam auth session ticket in list of pending tickets:" << authTicket; + } +} +static std::atomic_bool initialized { false }; +static std::unique_ptr steamTicketRequests; + +bool SteamClient::init() { + if (!initialized) { + initialized = SteamAPI_Init(); + } + + if (!steamTicketRequests && initialized) { + steamTicketRequests.reset(new SteamTicketRequests()); + } + + return initialized; +} + +void SteamClient::shutdown() { + if (initialized) { + SteamAPI_Shutdown(); + } + + if (steamTicketRequests) { + steamTicketRequests.reset(); + } +} + +void SteamClient::runCallbacks() { + if (!initialized) { + init(); + } + + if (!initialized) { + qDebug() << "Steam not initialized"; + return; + } + + auto steamPipe = SteamAPI_GetHSteamPipe(); + if (!steamPipe) { + qDebug() << "Could not get SteamPipe"; + return; + } + + Steam_RunCallbacks(steamPipe, false); +} + +void SteamClient::requestTicket(TicketRequestCallback callback) { + if (!initialized) { + init(); + } + + if (!initialized) { + qDebug() << "Steam not initialized"; + return; + } + + steamTicketRequests->startRequest(callback); +} + diff --git a/libraries/steamworks-wrapper/src/steamworks-wrapper/SteamClient.h b/libraries/steamworks-wrapper/src/steamworks-wrapper/SteamClient.h index 369641b0c7..ac5c648ead 100644 --- a/libraries/steamworks-wrapper/src/steamworks-wrapper/SteamClient.h +++ b/libraries/steamworks-wrapper/src/steamworks-wrapper/SteamClient.h @@ -13,8 +13,21 @@ #ifndef hifi_SteamClient_h #define hifi_SteamClient_h -class SteamClient { +#include +#include + +using Ticket = QByteArray; +using TicketRequestCallback = std::function; + +class SteamClient { +public: + static bool init(); + static void shutdown(); + + static void runCallbacks(); + + static void requestTicket(TicketRequestCallback callback); }; From 205df0cf5170a1ab663dd7ca94f7c0571f917f1d Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 20 Jul 2016 10:23:10 -0700 Subject: [PATCH 03/22] login UI first draft --- interface/resources/qml/LoginDialog.qml | 355 ++++-------------- .../qml/LoginDialog/CompleteProfileBody.qml | 93 +++++ .../qml/LoginDialog/EmailSentBody.qml | 83 ++++ .../qml/LoginDialog/LinkAccountBody.qml | 165 ++++++++ .../qml/LoginDialog/RecoverPasswordBody.qml | 106 ++++++ .../resources/qml/LoginDialog/SignInBody.qml | 110 ++++++ .../qml/LoginDialog/UsernameCollisionBody.qml | 162 ++++++++ .../resources/qml/LoginDialog/WelcomeBody.qml | 83 ++++ interface/resources/qml/LoginDialogSave.qml | 197 ++++++++++ .../qml/controls-uit/HorizontalRule.qml | 20 + .../qml/controls-uit/HorizontalSpacer.qml | 21 ++ .../qml/controls-uit/VerticalSpacer.qml | 3 + .../resources/qml/dialogs/MessageDialog.qml | 6 +- .../resources/qml/styles-uit/ButtonLabel.qml | 18 + .../resources/qml/styles-uit/IconButton.qml | 20 + .../resources/qml/styles-uit/InputLabel.qml | 18 + .../resources/qml/styles-uit/ListItem.qml | 18 + interface/resources/qml/styles-uit/Logs.qml | 18 + .../resources/qml/styles-uit/MenuItem.qml | 19 + .../resources/qml/styles-uit/OverlayTitle.qml | 18 + .../resources/qml/styles-uit/SectionName.qml | 19 + .../resources/qml/styles-uit/ShortcutText.qml | 18 + .../resources/qml/styles-uit/TabName.qml | 19 + .../qml/styles-uit/TextFieldInput.qml | 18 + interface/src/Application.cpp | 9 +- interface/src/ui/LoginDialog.cpp | 33 +- interface/src/ui/LoginDialog.h | 17 +- .../networking/src/NetworkingConstants.h | 2 +- 28 files changed, 1321 insertions(+), 347 deletions(-) create mode 100644 interface/resources/qml/LoginDialog/CompleteProfileBody.qml create mode 100644 interface/resources/qml/LoginDialog/EmailSentBody.qml create mode 100644 interface/resources/qml/LoginDialog/LinkAccountBody.qml create mode 100644 interface/resources/qml/LoginDialog/RecoverPasswordBody.qml create mode 100644 interface/resources/qml/LoginDialog/SignInBody.qml create mode 100644 interface/resources/qml/LoginDialog/UsernameCollisionBody.qml create mode 100644 interface/resources/qml/LoginDialog/WelcomeBody.qml create mode 100644 interface/resources/qml/LoginDialogSave.qml create mode 100644 interface/resources/qml/controls-uit/HorizontalRule.qml create mode 100644 interface/resources/qml/controls-uit/HorizontalSpacer.qml create mode 100644 interface/resources/qml/styles-uit/ButtonLabel.qml create mode 100644 interface/resources/qml/styles-uit/IconButton.qml create mode 100644 interface/resources/qml/styles-uit/InputLabel.qml create mode 100644 interface/resources/qml/styles-uit/ListItem.qml create mode 100644 interface/resources/qml/styles-uit/Logs.qml create mode 100644 interface/resources/qml/styles-uit/MenuItem.qml create mode 100644 interface/resources/qml/styles-uit/OverlayTitle.qml create mode 100644 interface/resources/qml/styles-uit/SectionName.qml create mode 100644 interface/resources/qml/styles-uit/ShortcutText.qml create mode 100644 interface/resources/qml/styles-uit/TabName.qml create mode 100644 interface/resources/qml/styles-uit/TextFieldInput.qml diff --git a/interface/resources/qml/LoginDialog.qml b/interface/resources/qml/LoginDialog.qml index eccea00143..3e8747c076 100644 --- a/interface/resources/qml/LoginDialog.qml +++ b/interface/resources/qml/LoginDialog.qml @@ -10,320 +10,91 @@ import Hifi 1.0 import QtQuick 2.4 -import "controls" -import "styles" + +import "controls-uit" +import "styles-uit" import "windows" -ScrollingWindow { +import "LoginDialog" + +ModalWindow { id: root HifiConstants { id: hifi } objectName: "LoginDialog" - height: loginDialog.implicitHeight - width: loginDialog.implicitWidth - // FIXME make movable - anchors.centerIn: parent - destroyOnHidden: false - hideBackground: true - shown: false + implicitWidth: 520 + implicitHeight: 320 + destroyOnCloseButton: true + destroyOnHidden: true + visible: true + + property string iconText: "" + property int iconSize: 50 + + property string title: "" + property int titleWidth: 0 + + Component { + id: signInBody + SignInBody {} + } + Component { + id: welcomeBody + WelcomeBody {} + } LoginDialog { id: loginDialog - implicitWidth: backgroundRectangle.width - implicitHeight: backgroundRectangle.height - readonly property int inputWidth: 500 - readonly property int inputHeight: 60 - readonly property int borderWidth: 30 - readonly property int closeMargin: 16 - readonly property real tan30: 0.577 // tan(30°) - readonly property int inputSpacing: 16 - Rectangle { - id: backgroundRectangle - width: loginDialog.inputWidth + loginDialog.borderWidth * 2 - height: loginDialog.inputHeight * 6 + loginDialog.closeMargin * 2 - radius: loginDialog.closeMargin * 2 - color: "#2c86b1" - opacity: 0.85 + Loader { + id: bodyLoader + anchors.fill: parent + sourceComponent: signInBody } - Column { - id: mainContent - width: loginDialog.inputWidth - spacing: loginDialog.inputSpacing - anchors { - horizontalCenter: parent.horizontalCenter - verticalCenter: parent.verticalCenter + Connections { + target: loginDialog + onHandleLoginCompleted: { + console.log("Login Succeeded") + bodyLoader.sourceComponent = welcomeBody + bodyLoader.active = true } - - Item { - // Offset content down a little - width: loginDialog.inputWidth - height: loginDialog.closeMargin + onHandleLoginFailed: { + console.log("Login Failed") } - - Rectangle { - width: loginDialog.inputWidth - height: loginDialog.inputHeight - radius: height / 2 - color: "#ebebeb" - - Image { - source: "../images/login-username.svg" - width: loginDialog.inputHeight * 0.65 - height: width - sourceSize: Qt.size(width, height); - anchors { - verticalCenter: parent.verticalCenter - left: parent.left - leftMargin: loginDialog.inputHeight / 4 - } - } - - TextInput { - id: username - anchors { - fill: parent - leftMargin: loginDialog.inputHeight - rightMargin: loginDialog.inputHeight / 2 - } - - helperText: "username or email" - color: hifi.colors.text - - KeyNavigation.tab: password - KeyNavigation.backtab: password - } - } - - Rectangle { - width: loginDialog.inputWidth - height: loginDialog.inputHeight - radius: height / 2 - color: "#ebebeb" - - Image { - source: "../images/login-password.svg" - width: loginDialog.inputHeight * 0.65 - height: width - sourceSize: Qt.size(width, height); - anchors { - verticalCenter: parent.verticalCenter - left: parent.left - leftMargin: loginDialog.inputHeight / 4 - } - } - - TextInput { - id: password - anchors { - fill: parent - leftMargin: loginDialog.inputHeight - rightMargin: loginDialog.inputHeight / 2 - } - - helperText: "password" - echoMode: TextInput.Password - color: hifi.colors.text - - KeyNavigation.tab: username - KeyNavigation.backtab: username - onFocusChanged: { - if (password.focus) { - password.selectAll() - } - } - } - } - - Item { - width: loginDialog.inputWidth - height: loginDialog.inputHeight / 2 - - Text { - id: messageText - - visible: loginDialog.statusText != "" && loginDialog.statusText != "Logging in..." - - width: loginDialog.inputWidth - height: loginDialog.inputHeight / 2 - horizontalAlignment: Text.AlignHCenter - verticalAlignment: Text.AlignVCenter - - text: loginDialog.statusText - color: "white" - } - - Row { - id: messageSpinner - - visible: loginDialog.statusText == "Logging in..." - onVisibleChanged: visible ? messageSpinnerAnimation.restart() : messageSpinnerAnimation.stop() - - spacing: 24 - anchors { - verticalCenter: parent.verticalCenter - horizontalCenter: parent.horizontalCenter - } - - Rectangle { - id: spinner1 - width: 10 - height: 10 - color: "#ebebeb" - opacity: 0.05 - } - - Rectangle { - id: spinner2 - width: 10 - height: 10 - color: "#ebebeb" - opacity: 0.05 - } - - Rectangle { - id: spinner3 - width: 10 - height: 10 - color: "#ebebeb" - opacity: 0.05 - } - - SequentialAnimation { - id: messageSpinnerAnimation - running: messageSpinner.visible - loops: Animation.Infinite - NumberAnimation { target: spinner1; property: "opacity"; to: 1.0; duration: 1000 } - NumberAnimation { target: spinner2; property: "opacity"; to: 1.0; duration: 1000 } - NumberAnimation { target: spinner3; property: "opacity"; to: 1.0; duration: 1000 } - NumberAnimation { target: spinner1; property: "opacity"; to: 0.05; duration: 0 } - NumberAnimation { target: spinner2; property: "opacity"; to: 0.05; duration: 0 } - NumberAnimation { target: spinner3; property: "opacity"; to: 0.05; duration: 0 } - } - } - } - - Row { - width: loginDialog.inputWidth - height: loginDialog.inputHeight - - Rectangle { - width: loginDialog.inputWidth / 3 - height: loginDialog.inputHeight - radius: height / 2 - color: "#353535" - - TextInput { - anchors.fill: parent - text: "Login" - color: "white" - horizontalAlignment: Text.AlignHCenter - } - - MouseArea { - anchors.fill: parent - cursorShape: Qt.PointingHandCursor - onClicked: { - loginDialog.login(username.text, password.text) - } - } - } - - Image { - source: "../images/steam-sign-in.png" - width: loginDialog.inputWidth / 3 - height: loginDialog.inputHeight - anchors { - verticalCenter: parent.verticalCenter - right: parent.right - leftMargin: loginDialog.inputHeight / 4 - } - - MouseArea { - anchors.fill: parent - cursorShape: Qt.PointingHandCursor - onClicked: { - loginDialog.loginThroughSteam() - } - } - } - } - - Item { - anchors { left: parent.left; right: parent.right; } - height: loginDialog.inputHeight - - Image { - id: hifiIcon - source: "../images/hifi-logo-blackish.svg" - width: loginDialog.inputHeight - height: width - sourceSize: Qt.size(width, height); - anchors { verticalCenter: parent.verticalCenter; horizontalCenter: parent.horizontalCenter } - } - - Text { - anchors { verticalCenter: parent.verticalCenter; right: hifiIcon.left; margins: loginDialog.inputSpacing } - text: "Password?" - scale: 0.8 - font.underline: true - color: "#e0e0e0" - MouseArea { - anchors { fill: parent; margins: -loginDialog.inputSpacing / 2 } - cursorShape: Qt.PointingHandCursor - onClicked: loginDialog.openUrl(loginDialog.rootUrl + "/users/password/new") - } - } - - Text { - anchors { verticalCenter: parent.verticalCenter; left: hifiIcon.right; margins: loginDialog.inputSpacing } - text: "Register" - scale: 0.8 - font.underline: true - color: "#e0e0e0" - - MouseArea { - anchors { fill: parent; margins: -loginDialog.inputSpacing / 2 } - cursorShape: Qt.PointingHandCursor - onClicked: loginDialog.openUrl(loginDialog.rootUrl + "/signup") - } - } - - } - } - } - - onShownChanged: { - if (!shown) { - username.text = "" - password.text = "" - loginDialog.statusText = "" - } else { - username.forceActiveFocus() } } Keys.onPressed: { - switch (event.key) { + if (!visible) { + return + } + + if (event.modifiers === Qt.ControlModifier) + switch (event.key) { + case Qt.Key_A: + event.accepted = true + detailedText.selectAll() + break + case Qt.Key_C: + event.accepted = true + detailedText.copy() + break + case Qt.Key_Period: + if (Qt.platform.os === "osx") { + event.accepted = true + content.reject() + } + break + } else switch (event.key) { case Qt.Key_Escape: case Qt.Key_Back: - root.shown = false; - event.accepted = true; - break; + event.accepted = true + destroy() + break case Qt.Key_Enter: case Qt.Key_Return: - if (username.activeFocus) { - event.accepted = true - password.forceActiveFocus() - } else if (password.activeFocus) { - event.accepted = true - if (username.text == "") { - username.forceActiveFocus() - } else { - loginDialog.login(username.text, password.text) - } - } + event.accepted = true break } } diff --git a/interface/resources/qml/LoginDialog/CompleteProfileBody.qml b/interface/resources/qml/LoginDialog/CompleteProfileBody.qml new file mode 100644 index 0000000000..b6ef012e2a --- /dev/null +++ b/interface/resources/qml/LoginDialog/CompleteProfileBody.qml @@ -0,0 +1,93 @@ +// +// CompleteProfileBody.qml +// +// Created by Clement on 7/18/16 +// Copyright 2015 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 +// + +import Hifi 1.0 +import QtQuick 2.4 +import QtQuick.Controls.Styles 1.4 as OriginalStyles + +import "../controls-uit" +import "../styles-uit" + +Item { + id: completeProfileBody + clip: true + width: pane.width + height: pane.height + + QtObject { + id: d + readonly property int minWidth: 480 + readonly property int maxWidth: 1280 + readonly property int minHeight: 120 + readonly property int maxHeight: 720 + + function resize() { + var targetWidth = Math.max(titleWidth, additionalTextContainer.contentWidth) + var targetHeight = 4 * hifi.dimensions.contentSpacing.y + buttons.height + additionalTextContainer.height + + root.width = Math.max(d.minWidth, Math.min(d.maxWidth, targetWidth)) + root.height = Math.max(d.minHeight, Math.min(d.maxHeight, targetHeight)) + } + } + + Row { + id: buttons + anchors { + top: parent.top + horizontalCenter: parent.horizontalCenter + margins: 0 + topMargin: 3 * hifi.dimensions.contentSpacing.y + } + spacing: hifi.dimensions.contentSpacing.x + onHeightChanged: d.resize(); onWidthChanged: d.resize(); + + Button { + anchors.verticalCenter: parent.verticalCenter + width: 200 + + text: qsTr("Create your profile") + color: hifi.buttons.blue + } + + Button { + anchors.verticalCenter: parent.verticalCenter + + text: qsTr("Cancel") + + + onClicked: root.destroy() + } + } + + ShortcutText { + id: additionalTextContainer + anchors { + top: buttons.bottom + horizontalCenter: parent.horizontalCenter + margins: 0 + topMargin: hifi.dimensions.contentSpacing.y + } + + text: "Already have a High Fidelity profile? Link to an existing profile here." + + font.underline: true + wrapMode: Text.WordWrap + color: hifi.colors.blueAccent + lineHeight: 2 + lineHeightMode: Text.ProportionalHeight + horizontalAlignment: Text.AlignHCenter + } + + Component.onCompleted: { + root.title = qsTr("Complete Your Profile") + root.iconText = "<" + d.resize(); + } +} diff --git a/interface/resources/qml/LoginDialog/EmailSentBody.qml b/interface/resources/qml/LoginDialog/EmailSentBody.qml new file mode 100644 index 0000000000..eede996412 --- /dev/null +++ b/interface/resources/qml/LoginDialog/EmailSentBody.qml @@ -0,0 +1,83 @@ +// +// EmailSentBody.qml +// +// Created by Clement on 7/18/16 +// Copyright 2015 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 +// + +import Hifi 1.0 +import QtQuick 2.4 + +import "../controls-uit" +import "../styles-uit" + +Item { + id: emailSentBody + clip: true + width: pane.width + height: pane.height + + property string email: "clement@highfidelity.com" + + QtObject { + id: d + readonly property int minWidth: 480 + readonly property int maxWidth: 1280 + readonly property int minHeight: 120 + readonly property int maxHeight: 720 + + function resize() { + var targetWidth = Math.max(titleWidth, mainTextContainer.contentWidth) + var targetHeight = mainTextContainer.height + 3 * hifi.dimensions.contentSpacing.y + buttons.height + + root.width = Math.max(d.minWidth, Math.min(d.maxWidth, targetWidth)) + root.height = Math.max(d.minHeight, Math.min(d.maxHeight, targetHeight)) + } + } + + MenuItem { + id: mainTextContainer + anchors { + top: parent.top + horizontalCenter: parent.horizontalCenter + margins: 0 + topMargin: hifi.dimensions.contentSpacing.y + } + + text: qsTr("An email with instructions on reseting your password was sent to
") + email + "" + wrapMode: Text.WordWrap + color: hifi.colors.baseGrayHighlight + lineHeight: 2 + lineHeightMode: Text.ProportionalHeight + horizontalAlignment: Text.AlignHCenter + } + + Row { + id: buttons + anchors { + top: mainTextContainer.bottom + horizontalCenter: parent.horizontalCenter + margins: 0 + topMargin: 2 * hifi.dimensions.contentSpacing.y + } + spacing: hifi.dimensions.contentSpacing.x + onHeightChanged: d.resize(); onWidthChanged: d.resize(); + + Button { + anchors.verticalCenter: parent.verticalCenter + + text: qsTr("Close"); + + onClicked: root.destroy() + } + } + + Component.onCompleted: { + root.title = qsTr("Email Sent") + root.iconText = "" + d.resize(); + } +} diff --git a/interface/resources/qml/LoginDialog/LinkAccountBody.qml b/interface/resources/qml/LoginDialog/LinkAccountBody.qml new file mode 100644 index 0000000000..b7ff756fa3 --- /dev/null +++ b/interface/resources/qml/LoginDialog/LinkAccountBody.qml @@ -0,0 +1,165 @@ +// +// LinkAccountBody.qml +// +// Created by Clement on 7/18/16 +// Copyright 2015 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 +// + +import Hifi 1.0 +import QtQuick 2.4 +import QtQuick.Controls 1.4 +import QtQuick.Controls.Styles 1.4 as OriginalStyles + +import "../controls-uit" +import "../styles-uit" + +Item { + id: linkAccountBody + clip: true + width: pane.width + height: pane.height + + property bool existingEmail: true + + QtObject { + id: d + readonly property int minWidth: 480 + readonly property int maxWidth: 1280 + readonly property int minHeight: 120 + readonly property int maxHeight: 720 + + function resize() { + var targetWidth = Math.max(titleWidth, mainTextContainer.visible ? mainTextContainer.contentWidth : 0) + var targetHeight = (mainTextContainer.visible ? mainTextContainer.height : 0) + + 4 * hifi.dimensions.contentSpacing.y + form.height + + 4 * hifi.dimensions.contentSpacing.y + buttons.height + + root.width = Math.max(d.minWidth, Math.min(d.maxWidth, targetWidth)) + root.height = Math.max(d.minHeight, Math.min(d.maxHeight, targetHeight)) + } + } + + MenuItem { + id: mainTextContainer + anchors { + top: parent.top + horizontalCenter: parent.horizontalCenter + margins: 0 + topMargin: hifi.dimensions.contentSpacing.y + } + visible: existingEmail + + text: qsTr("Your Steam account's email matches an existing High Fidelity Profile") + wrapMode: Text.WordWrap + color: hifi.colors.redAccent + lineHeight: 2 + lineHeightMode: Text.ProportionalHeight + horizontalAlignment: Text.AlignHCenter + } + + + Column { + id: form + anchors { + top: mainTextContainer.bottom + left: parent.left + margins: 0 + topMargin: 2 * hifi.dimensions.contentSpacing.y + } + spacing: 2 * hifi.dimensions.contentSpacing.y + + Row { + spacing: hifi.dimensions.contentSpacing.x + + TextField { + id: usernameField + anchors { + verticalCenter: parent.verticalCenter + } + width: 350 + + label: "User Name or Email" + } + + ShortcutText { + anchors { + verticalCenter: parent.verticalCenter + } + + text: "Need help?" + + color: hifi.colors.blueAccent + font.underline: true + + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignHCenter + } + } + Row { + spacing: hifi.dimensions.contentSpacing.x + + TextField { + id: passwordField + anchors { + verticalCenter: parent.verticalCenter + } + width: 350 + + label: "Password" + echoMode: TextInput.Password + } + + ShortcutText { + anchors { + verticalCenter: parent.verticalCenter + } + + text: "Need help?" + + color: hifi.colors.blueAccent + font.underline: true + + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignHCenter + } + } + + } + + Row { + id: buttons + anchors { + top: form.bottom + right: parent.right + margins: 0 + topMargin: 3 * hifi.dimensions.contentSpacing.y + } + spacing: hifi.dimensions.contentSpacing.x + onHeightChanged: d.resize(); onWidthChanged: d.resize(); + + Button { + anchors.verticalCenter: parent.verticalCenter + width: 200 + + text: qsTr("Link Account") + color: hifi.buttons.blue + } + + Button { + anchors.verticalCenter: parent.verticalCenter + + text: qsTr("Cancel") + + onClicked: root.destroy() + } + } + + Component.onCompleted: { + root.title = qsTr("Sign Into High Fidelity") + root.iconText = "<" + d.resize(); + } +} diff --git a/interface/resources/qml/LoginDialog/RecoverPasswordBody.qml b/interface/resources/qml/LoginDialog/RecoverPasswordBody.qml new file mode 100644 index 0000000000..74dcb18054 --- /dev/null +++ b/interface/resources/qml/LoginDialog/RecoverPasswordBody.qml @@ -0,0 +1,106 @@ +// +// RecoverPasswordBody.qml +// +// Created by Clement on 7/18/16 +// Copyright 2015 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 +// + +import Hifi 1.0 +import QtQuick 2.4 +import QtQuick.Controls 1.4 +import QtQuick.Controls.Styles 1.4 as OriginalStyles + +import "../controls-uit" +import "../styles-uit" + +Item { + id: recoverPasswordBody + clip: true + width: pane.width + height: pane.height + + QtObject { + id: d + readonly property int minWidth: 480 + readonly property int maxWidth: 1280 + readonly property int minHeight: 120 + readonly property int maxHeight: 720 + + function resize() { + var targetWidth = Math.max(titleWidth, mainTextContainer.contentWidth) + var targetHeight = mainTextContainer.height + + 3 * hifi.dimensions.contentSpacing.y + emailField.height + + 4 * hifi.dimensions.contentSpacing.y + buttons.height + + root.width = Math.max(d.minWidth, Math.min(d.maxWidth, targetWidth)) + root.height = Math.max(d.minHeight, Math.min(d.maxHeight, targetHeight)) + } + } + + MenuItem { + id: mainTextContainer + anchors { + top: parent.top + left: parent.left + right: parent.right + margins: 0 + topMargin: hifi.dimensions.contentSpacing.y + } + + text: qsTr("In order to help you reset your password, we will send an
email with instructions to your email address.") + wrapMode: Text.WordWrap + color: hifi.colors.baseGrayHighlight + lineHeight: 1 + horizontalAlignment: Text.AlignHLeft + } + + + TextField { + id: emailField + anchors { + top: mainTextContainer.bottom + left: parent.left + margins: 0 + topMargin: 2 * hifi.dimensions.contentSpacing.y + } + + width: 350 + + label: "Email address" + } + + Row { + id: buttons + anchors { + top: emailField.bottom + right: parent.right + margins: 0 + topMargin: 3 * hifi.dimensions.contentSpacing.y + } + spacing: hifi.dimensions.contentSpacing.x + onHeightChanged: d.resize(); onWidthChanged: d.resize(); + + Button { + anchors.verticalCenter: parent.verticalCenter + width: 200 + + text: qsTr("Send recovery email") + color: hifi.buttons.blue + } + + Button { + anchors.verticalCenter: parent.verticalCenter + + text: qsTr("Back") + } + } + + Component.onCompleted: { + root.title = qsTr("Recover Password") + root.iconText = "<" + d.resize(); + } +} diff --git a/interface/resources/qml/LoginDialog/SignInBody.qml b/interface/resources/qml/LoginDialog/SignInBody.qml new file mode 100644 index 0000000000..d3f6926bd2 --- /dev/null +++ b/interface/resources/qml/LoginDialog/SignInBody.qml @@ -0,0 +1,110 @@ +// +// SignInBody.qml +// +// Created by Clement on 7/18/16 +// Copyright 2015 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 +// + +import Hifi 1.0 +import QtQuick 2.4 +import QtQuick.Controls.Styles 1.4 as OriginalStyles + +import "../controls-uit" +import "../styles-uit" + +Item { + id: signInBody + clip: true + width: pane.width + height: pane.height + + property bool required: false + + function login() { + console.log("Trying to log in") + loginDialog.loginThroughSteam() + } + + function cancel() { + root.destroy() + } + + QtObject { + id: d + readonly property int minWidth: 480 + readonly property int maxWidth: 1280 + readonly property int minHeight: 120 + readonly property int maxHeight: 720 + + function resize() { + var targetWidth = Math.max(titleWidth, mainTextContainer.contentWidth) + var targetHeight = mainTextContainer.height + 3 * hifi.dimensions.contentSpacing.y + buttons.height + + root.width = Math.max(d.minWidth, Math.min(d.maxWidth, targetWidth)) + root.height = Math.max(d.minHeight, Math.min(d.maxHeight, targetHeight)) + } + } + + MenuItem { + id: mainTextContainer + anchors { + top: parent.top + horizontalCenter: parent.horizontalCenter + margins: 0 + topMargin: hifi.dimensions.contentSpacing.y + } + + text: required ? qsTr("This domain's owner requires that you sign in:") + : qsTr("Sign in to access your user account:") + wrapMode: Text.WordWrap + color: hifi.colors.baseGrayHighlight + lineHeight: 2 + lineHeightMode: Text.ProportionalHeight + horizontalAlignment: Text.AlignHCenter + } + + Row { + id: buttons + anchors { + top: mainTextContainer.bottom + horizontalCenter: parent.horizontalCenter + margins: 0 + topMargin: 2 * hifi.dimensions.contentSpacing.y + } + spacing: hifi.dimensions.contentSpacing.x + onHeightChanged: d.resize(); onWidthChanged: d.resize(); + + Button { + anchors.verticalCenter: parent.verticalCenter + + width: undefined // invalidate so that the image's size sets the width + height: undefined // invalidate so that the image's size sets the height + focus: true + + style: OriginalStyles.ButtonStyle { + background: Image { + id: buttonImage + source: "../../images/steam-sign-in.png" + } + } + onClicked: signInBody.login() + } + Button { + anchors.verticalCenter: parent.verticalCenter + + text: qsTr("Cancel"); + + onClicked: signInBody.cancel() + } + } + + Component.onCompleted: { + root.title = required ? qsTr("Sign In Required") + : qsTr("Sign In") + root.iconText = "" + d.resize(); + } +} diff --git a/interface/resources/qml/LoginDialog/UsernameCollisionBody.qml b/interface/resources/qml/LoginDialog/UsernameCollisionBody.qml new file mode 100644 index 0000000000..ea5a9bb614 --- /dev/null +++ b/interface/resources/qml/LoginDialog/UsernameCollisionBody.qml @@ -0,0 +1,162 @@ +// +// UsernameCollisionBody.qml +// +// Created by Clement on 7/18/16 +// Copyright 2015 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 +// + +import Hifi 1.0 +import QtQuick 2.4 +import QtQuick.Controls 1.4 +import QtQuick.Controls.Styles 1.4 as OriginalStyles + +import "../controls-uit" +import "../styles-uit" + +Item { + id: usernameCollisionBody + clip: true + width: pane.width + height: pane.height + + QtObject { + id: d + readonly property int minWidth: 480 + readonly property int maxWidth: 1280 + readonly property int minHeight: 120 + readonly property int maxHeight: 720 + + function resize() { + var targetWidth = Math.max(titleWidth, mainTextContainer.visible ? mainTextContainer.contentWidth : 0) + var targetHeight = (mainTextContainer.visible ? mainTextContainer.height : 0) + + 4 * hifi.dimensions.contentSpacing.y + form.height + + 4 * hifi.dimensions.contentSpacing.y + buttons.height + + root.width = Math.max(d.minWidth, Math.min(d.maxWidth, targetWidth)) + root.height = Math.max(d.minHeight, Math.min(d.maxHeight, targetHeight)) + } + } + + MenuItem { + id: mainTextContainer + anchors { + top: parent.top + horizontalCenter: parent.horizontalCenter + margins: 0 + topMargin: hifi.dimensions.contentSpacing.y + } + + text: qsTr("Choose your High Fidelity user name:") + wrapMode: Text.WordWrap + color: hifi.colors.baseGrayHighlight + lineHeight: 1 + lineHeightMode: Text.ProportionalHeight + horizontalAlignment: Text.AlignHCenter + } + + + Column { + id: form + anchors { + top: mainTextContainer.bottom + left: parent.left + margins: 0 + topMargin: 2 * hifi.dimensions.contentSpacing.y + } + spacing: 2 * hifi.dimensions.contentSpacing.y + + Row { + spacing: hifi.dimensions.contentSpacing.x + + TextField { + id: usernameField + anchors { + verticalCenter: parent.verticalCenter + } + width: 350 + + label: "User Name or Email" + } + + ShortcutText { + anchors { + verticalCenter: parent.verticalCenter + } + + text: "Need help?" + + color: hifi.colors.blueAccent + font.underline: true + + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignHCenter + } + } + Row { + spacing: hifi.dimensions.contentSpacing.x + + TextField { + id: passwordField + anchors { + verticalCenter: parent.verticalCenter + } + width: 350 + + label: "Password" + echoMode: TextInput.Password + } + + ShortcutText { + anchors { + verticalCenter: parent.verticalCenter + } + + text: "Need help?" + + color: hifi.colors.blueAccent + font.underline: true + + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignHCenter + } + } + + } + + Row { + id: buttons + anchors { + top: form.bottom + right: parent.right + margins: 0 + topMargin: 3 * hifi.dimensions.contentSpacing.y + } + spacing: hifi.dimensions.contentSpacing.x + onHeightChanged: d.resize(); onWidthChanged: d.resize(); + + Button { + anchors.verticalCenter: parent.verticalCenter + width: 200 + + text: qsTr("Create your profile") + color: hifi.buttons.blue + } + + Button { + anchors.verticalCenter: parent.verticalCenter + + text: qsTr("Cancel") + + onClicked: root.destroy() + } + } + + Component.onCompleted: { + root.title = qsTr("Complete Your Profile") + root.iconText = "<" + d.resize(); + } +} diff --git a/interface/resources/qml/LoginDialog/WelcomeBody.qml b/interface/resources/qml/LoginDialog/WelcomeBody.qml new file mode 100644 index 0000000000..8b771eac1f --- /dev/null +++ b/interface/resources/qml/LoginDialog/WelcomeBody.qml @@ -0,0 +1,83 @@ +// +// WelcomeBody.qml +// +// Created by Clement on 7/18/16 +// Copyright 2015 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 +// + +import Hifi 1.0 +import QtQuick 2.4 + +import "../controls-uit" +import "../styles-uit" + +Item { + id: welcomeBody + clip: true + width: pane.width + height: pane.height + + property bool welcomeBack: true + + QtObject { + id: d + readonly property int minWidth: 480 + readonly property int maxWidth: 1280 + readonly property int minHeight: 120 + readonly property int maxHeight: 720 + + function resize() { + var targetWidth = Math.max(titleWidth, mainTextContainer.contentWidth) + var targetHeight = mainTextContainer.height + 3 * hifi.dimensions.contentSpacing.y + buttons.height + + root.width = Math.max(d.minWidth, Math.min(d.maxWidth, targetWidth)) + root.height = Math.max(d.minHeight, Math.min(d.maxHeight, targetHeight)) + } + } + + MenuItem { + id: mainTextContainer + anchors { + top: parent.top + horizontalCenter: parent.horizontalCenter + margins: 0 + topMargin: hifi.dimensions.contentSpacing.y + } + + text: qsTr("You are now signed into High Fidelity") + wrapMode: Text.WordWrap + color: hifi.colors.baseGrayHighlight + lineHeight: 2 + lineHeightMode: Text.ProportionalHeight + horizontalAlignment: Text.AlignHCenter + } + + Row { + id: buttons + anchors { + top: mainTextContainer.bottom + horizontalCenter: parent.horizontalCenter + margins: 0 + topMargin: 2 * hifi.dimensions.contentSpacing.y + } + spacing: hifi.dimensions.contentSpacing.x + onHeightChanged: d.resize(); onWidthChanged: d.resize(); + + Button { + anchors.verticalCenter: parent.verticalCenter + + text: qsTr("Close"); + + onClicked: root.destroy() + } + } + + Component.onCompleted: { + root.title = (welcomeBack ? qsTr("Welcome back ") : qsTr("Welcome ")) + Account.getUsername() + qsTr("!") + root.iconText = "" + d.resize(); + } +} diff --git a/interface/resources/qml/LoginDialogSave.qml b/interface/resources/qml/LoginDialogSave.qml new file mode 100644 index 0000000000..46246fc1a5 --- /dev/null +++ b/interface/resources/qml/LoginDialogSave.qml @@ -0,0 +1,197 @@ +Window { + id: root + HifiConstants { id: hifi } + + width: 550 + height: 200 + + anchors.centerIn: parent + resizable: true + + property bool required: false + + Component { + id: welcomeBody + + Column { + anchors.centerIn: parent + + OverlayTitle { + anchors.horizontalCenter: parent.horizontalCenter + + text: "Welcomeback Atlante45!" + color: hifi.colors.baseGrayHighlight + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignHCenter + } + + VerticalSpacer {} + + HorizontalRule {} + + MenuItem { + id: details + anchors.horizontalCenter: parent.horizontalCenter + + text: "You are now signed into High Fidelity" + color: hifi.colors.baseGrayHighlight + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignHCenter + } + + VerticalSpacer {} + + Button { + anchors.horizontalCenter: parent.horizontalCenter + + text: "Close" + } + } + } + + Component { + id: signInBody + + Column { + anchors.centerIn: parent + + OverlayTitle { + anchors.horizontalCenter: parent.horizontalCenter + + text: required ? "Sign In Required" : "Sign In" + color: hifi.colors.baseGrayHighlight + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignHCenter + } + + VerticalSpacer {} + + HorizontalRule {} + + MenuItem { + id: details + anchors.horizontalCenter: parent.horizontalCenter + + text: required ? "This domain's owner requires that you sign in:" + : "Sign in to access your user account:" + color: hifi.colors.baseGrayHighlight + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignHCenter + } + + VerticalSpacer {} + + Row { + anchors.horizontalCenter: parent.horizontalCenter + + Button { + anchors.verticalCenter: parent.verticalCenter + width: undefined // invalidate so that the image's size sets the width + height: undefined // invalidate so that the image's size sets the height + + style: Original.ButtonStyle { + background: Image { + id: buttonImage + source: "../images/steam-sign-in.png" + } + } + + onClicked: body.sourceComponent = completeProfileBody + } + + HorizontalSpacer {} + + Button { + anchors.verticalCenter: parent.verticalCenter + + text: "Cancel" + + onClicked: required = !required + } + } + } + } + + Component { + id: completeProfileBody + + Column { + anchors.centerIn: parent + + Row { + anchors.horizontalCenter: parent.horizontalCenter + + HiFiGlyphs { + anchors.verticalCenter: parent.verticalCenter + + text: hifi.glyphs.avatar + } + + OverlayTitle { + anchors.verticalCenter: parent.verticalCenter + + text: "Complete Your Profile" + color: hifi.colors.baseGrayHighlight + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignHCenter + } + } + + VerticalSpacer {} + + HorizontalRule {} + + VerticalSpacer {} + + Row { + anchors.horizontalCenter: parent.horizontalCenter + + Button { + anchors.verticalCenter: parent.verticalCenter + + width: 200 + + text: "Create your profile" + color: hifi.buttons.blue + + onClicked: body.sourceComponent = welcomeBody + } + + HorizontalSpacer {} + + Button { + anchors.verticalCenter: parent.verticalCenter + + text: "Cancel" + + onClicked: body.sourceComponent = signInBody + + } + } + + VerticalSpacer {} + + ShortcutText { + text: "Already have a High Fidelity profile? Link to an existing profile here." + + color: hifi.colors.blueAccent + font.underline: true + + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignHCenter + } + } + } + + Rectangle { + anchors.fill: root + color: hifi.colors.faintGray + radius: hifi.dimensions.borderRadius + + Loader { + id: body + anchors.centerIn: parent + sourceComponent: signInBody + } + } +} diff --git a/interface/resources/qml/controls-uit/HorizontalRule.qml b/interface/resources/qml/controls-uit/HorizontalRule.qml new file mode 100644 index 0000000000..425500f1d4 --- /dev/null +++ b/interface/resources/qml/controls-uit/HorizontalRule.qml @@ -0,0 +1,20 @@ +// +// HorizontalRule.qml +// +// Created by Clement on 7/18/16 +// Copyright 2016 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 +// + +import QtQuick 2.5 +import QtQuick.Controls 1.4 +import QtQuick.Controls.Styles 1.4 + +Rectangle { + anchors.left: parent.left + anchors.right: parent.right + height: 1 + color: hifi.colors.lightGray +} diff --git a/interface/resources/qml/controls-uit/HorizontalSpacer.qml b/interface/resources/qml/controls-uit/HorizontalSpacer.qml new file mode 100644 index 0000000000..545154ab44 --- /dev/null +++ b/interface/resources/qml/controls-uit/HorizontalSpacer.qml @@ -0,0 +1,21 @@ +// +// HorizontalSpacer.qml +// +// Created by Clement on 7/18/16 +// Copyright 2016 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 +// + +import QtQuick 2.5 + +import "../styles-uit" + +Item { + id: root + property alias size: root.width + + width: hifi.dimensions.controlInterlineHeight + height: 1 // Must be non-zero +} diff --git a/interface/resources/qml/controls-uit/VerticalSpacer.qml b/interface/resources/qml/controls-uit/VerticalSpacer.qml index 6fc49605c0..2df65f1002 100644 --- a/interface/resources/qml/controls-uit/VerticalSpacer.qml +++ b/interface/resources/qml/controls-uit/VerticalSpacer.qml @@ -13,6 +13,9 @@ import QtQuick 2.5 import "../styles-uit" Item { + id: root + property alias size: root.height + width: 1 // Must be non-zero height: hifi.dimensions.controlInterlineHeight } diff --git a/interface/resources/qml/dialogs/MessageDialog.qml b/interface/resources/qml/dialogs/MessageDialog.qml index d390ea08bf..40c5a01e15 100644 --- a/interface/resources/qml/dialogs/MessageDialog.qml +++ b/interface/resources/qml/dialogs/MessageDialog.qml @@ -21,8 +21,6 @@ import "messageDialog" ModalWindow { id: root HifiConstants { id: hifi } - implicitWidth: 640 - implicitHeight: 320 destroyOnCloseButton: true destroyOnHidden: true visible: true @@ -70,7 +68,7 @@ ModalWindow { QtObject { id: d readonly property int minWidth: 480 - readonly property int maxWdith: 1280 + readonly property int maxWidth: 1280 readonly property int minHeight: 120 readonly property int maxHeight: 720 @@ -80,7 +78,7 @@ ModalWindow { + (informativeTextContainer.text != "" ? informativeTextContainer.contentHeight + 3 * hifi.dimensions.contentSpacing.y : 0) + buttons.height + (content.state === "expanded" ? details.implicitHeight + hifi.dimensions.contentSpacing.y : 0) - root.width = (targetWidth < d.minWidth) ? d.minWidth : ((targetWidth > d.maxWdith) ? d.maxWidth : targetWidth) + root.width = (targetWidth < d.minWidth) ? d.minWidth : ((targetWidth > d.maxWidth) ? d.maxWidth : targetWidth) root.height = (targetHeight < d.minHeight) ? d.minHeight: ((targetHeight > d.maxHeight) ? d.maxHeight : targetHeight) } } diff --git a/interface/resources/qml/styles-uit/ButtonLabel.qml b/interface/resources/qml/styles-uit/ButtonLabel.qml new file mode 100644 index 0000000000..aade5fb439 --- /dev/null +++ b/interface/resources/qml/styles-uit/ButtonLabel.qml @@ -0,0 +1,18 @@ +// +// ButtonLabel.qml +// +// Created by Clement on 7/18/16 +// Copyright 2016 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 +// + +import QtQuick 2.5 +import QtQuick.Controls 1.4 +import QtQuick.Controls.Styles 1.4 +import "." + +RalewayBold { + font.pixelSize: hifi.fontSizes.buttonLabel +} diff --git a/interface/resources/qml/styles-uit/IconButton.qml b/interface/resources/qml/styles-uit/IconButton.qml new file mode 100644 index 0000000000..84c1ef14c1 --- /dev/null +++ b/interface/resources/qml/styles-uit/IconButton.qml @@ -0,0 +1,20 @@ +// +// IconButton.qml +// +// Created by Clement on 7/18/16 +// Copyright 2016 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 +// + +import QtQuick 2.5 +import QtQuick.Controls 1.4 +import QtQuick.Controls.Styles 1.4 +import "." + +RalewayRegular { + font.pixelSize: hifi.fontSizes.iconButton + font.capitalization: Font.AllUppercase + font.letterSpacing: 1.5 +} diff --git a/interface/resources/qml/styles-uit/InputLabel.qml b/interface/resources/qml/styles-uit/InputLabel.qml new file mode 100644 index 0000000000..59657a554d --- /dev/null +++ b/interface/resources/qml/styles-uit/InputLabel.qml @@ -0,0 +1,18 @@ +// +// InputLabel.qml +// +// Created by Clement on 7/18/16 +// Copyright 2016 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 +// + +import QtQuick 2.5 +import QtQuick.Controls 1.4 +import QtQuick.Controls.Styles 1.4 +import "." + +RalewaySemiBold { + font.pixelSize: hifi.fontSizes.inputLabel +} diff --git a/interface/resources/qml/styles-uit/ListItem.qml b/interface/resources/qml/styles-uit/ListItem.qml new file mode 100644 index 0000000000..f707686edc --- /dev/null +++ b/interface/resources/qml/styles-uit/ListItem.qml @@ -0,0 +1,18 @@ +// +// ListItem.qml +// +// Created by Clement on 7/18/16 +// Copyright 2016 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 +// + +import QtQuick 2.5 +import QtQuick.Controls 1.4 +import QtQuick.Controls.Styles 1.4 +import "." + +RalewayRegular { + font.pixelSize: hifi.fontSizes.listItem +} diff --git a/interface/resources/qml/styles-uit/Logs.qml b/interface/resources/qml/styles-uit/Logs.qml new file mode 100644 index 0000000000..577fe2f8d8 --- /dev/null +++ b/interface/resources/qml/styles-uit/Logs.qml @@ -0,0 +1,18 @@ +// +// Logs.qml +// +// Created by Clement on 7/18/16 +// Copyright 2016 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 +// + +import QtQuick 2.5 +import QtQuick.Controls 1.4 +import QtQuick.Controls.Styles 1.4 +import "." + +AnonymousProRegular { + font.pixelSize: hifi.fontSizes.logs +} diff --git a/interface/resources/qml/styles-uit/MenuItem.qml b/interface/resources/qml/styles-uit/MenuItem.qml new file mode 100644 index 0000000000..4431c357bf --- /dev/null +++ b/interface/resources/qml/styles-uit/MenuItem.qml @@ -0,0 +1,19 @@ +// +// MenuItem.qml +// +// Created by Clement on 7/18/16 +// Copyright 2016 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 +// + +import QtQuick 2.5 +import QtQuick.Controls 1.4 +import QtQuick.Controls.Styles 1.4 +import "." + +RalewaySemiBold { + lineHeight: 2 + font.pixelSize: hifi.fontSizes.menuItem +} diff --git a/interface/resources/qml/styles-uit/OverlayTitle.qml b/interface/resources/qml/styles-uit/OverlayTitle.qml new file mode 100644 index 0000000000..e23b9eca14 --- /dev/null +++ b/interface/resources/qml/styles-uit/OverlayTitle.qml @@ -0,0 +1,18 @@ +// +// OverlayTitle.qml +// +// Created by Clement on 7/18/16 +// Copyright 2016 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 +// + +import QtQuick 2.5 +import QtQuick.Controls 1.4 +import QtQuick.Controls.Styles 1.4 +import "." + +RalewayRegular { + font.pixelSize: hifi.fontSizes.overlayTitle +} diff --git a/interface/resources/qml/styles-uit/SectionName.qml b/interface/resources/qml/styles-uit/SectionName.qml new file mode 100644 index 0000000000..5438fec7bc --- /dev/null +++ b/interface/resources/qml/styles-uit/SectionName.qml @@ -0,0 +1,19 @@ +// +// SectionName.qml +// +// Created by Clement on 7/18/16 +// Copyright 2016 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 +// + +import QtQuick 2.5 +import QtQuick.Controls 1.4 +import QtQuick.Controls.Styles 1.4 +import "." + +RalewayRegular { + font.pixelSize: hifi.fontSizes.sectionName + font.capitalization: Font.AllUppercase +} diff --git a/interface/resources/qml/styles-uit/ShortcutText.qml b/interface/resources/qml/styles-uit/ShortcutText.qml new file mode 100644 index 0000000000..a3ab351870 --- /dev/null +++ b/interface/resources/qml/styles-uit/ShortcutText.qml @@ -0,0 +1,18 @@ +// +// ShortcutText.qml +// +// Created by Clement on 7/18/16 +// Copyright 2016 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 +// + +import QtQuick 2.5 +import QtQuick.Controls 1.4 +import QtQuick.Controls.Styles 1.4 +import "." + +RalewayLight { + font.pixelSize: hifi.fontSizes.shortcutText +} diff --git a/interface/resources/qml/styles-uit/TabName.qml b/interface/resources/qml/styles-uit/TabName.qml new file mode 100644 index 0000000000..eb4e790e7e --- /dev/null +++ b/interface/resources/qml/styles-uit/TabName.qml @@ -0,0 +1,19 @@ +// +// TabName.qml +// +// Created by Clement on 7/18/16 +// Copyright 2016 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 +// + +import QtQuick 2.5 +import QtQuick.Controls 1.4 +import QtQuick.Controls.Styles 1.4 +import "." + +RalewayRegular { + font.pixelSize: hifi.fontSizes.tabName + font.capitalization: Font.AllUppercase +} diff --git a/interface/resources/qml/styles-uit/TextFieldInput.qml b/interface/resources/qml/styles-uit/TextFieldInput.qml new file mode 100644 index 0000000000..010b4d03ad --- /dev/null +++ b/interface/resources/qml/styles-uit/TextFieldInput.qml @@ -0,0 +1,18 @@ +// +// TextFieldInput.qml +// +// Created by Clement on 7/18/16 +// Copyright 2016 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 +// + +import QtQuick 2.5 +import QtQuick.Controls 1.4 +import QtQuick.Controls.Styles 1.4 +import "." + +FiraSansSemiBold { + font.pixelSize: hifi.fontSizes.textFieldInput +} diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 1729a773c6..58284682f1 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2242,11 +2242,12 @@ void Application::keyPressEvent(QKeyEvent* event) { break; case Qt::Key_X: - if (isShifted && isMeta) { + if (isMeta) { auto offscreenUi = DependencyManager::get(); - offscreenUi->togglePinned(); - //offscreenUi->getRootContext()->engine()->clearComponentCache(); - //OffscreenUi::information("Debugging", "Component cache cleared"); +// offscreenUi->togglePinned(); + offscreenUi->getRootContext()->engine()->clearComponentCache(); + qDebug() << "Component cache cleared"; +// OffscreenUi::information("Debugging", "Component cache cleared"); // placeholder for dialogs being converted to QML. } break; diff --git a/interface/src/ui/LoginDialog.cpp b/interface/src/ui/LoginDialog.cpp index 8240340381..15a277f394 100644 --- a/interface/src/ui/LoginDialog.cpp +++ b/interface/src/ui/LoginDialog.cpp @@ -22,9 +22,7 @@ HIFI_QML_DEF(LoginDialog) -LoginDialog::LoginDialog(QQuickItem *parent) : OffscreenQmlDialog(parent), - _rootUrl(NetworkingConstants::METAVERSE_SERVER_URL.toString()) -{ +LoginDialog::LoginDialog(QQuickItem *parent) : OffscreenQmlDialog(parent) { auto accountManager = DependencyManager::get(); connect(accountManager.data(), &AccountManager::loginComplete, this, &LoginDialog::handleLoginCompleted); @@ -54,42 +52,16 @@ void LoginDialog::toggleAction() { } } -void LoginDialog::handleLoginCompleted(const QUrl&) { - hide(); -} - -void LoginDialog::handleLoginFailed() { - setStatusText("Invalid username or password"); -} - -void LoginDialog::setStatusText(const QString& statusText) { - if (statusText != _statusText) { - _statusText = statusText; - emit statusTextChanged(); - } -} - -QString LoginDialog::statusText() const { - return _statusText; -} - -QString LoginDialog::rootUrl() const { - return _rootUrl; -} - void LoginDialog::login(const QString& username, const QString& password) { qDebug() << "Attempting to login " << username; - setStatusText("Logging in..."); DependencyManager::get()->requestAccessToken(username, password); } void LoginDialog::loginThroughSteam() { qDebug() << "Attempting to login through Steam"; - setStatusText("Logging in..."); - SteamClient::requestTicket([this](Ticket ticket) { if (ticket.isNull()) { - setStatusText("Steam client not logged into an account"); + emit handleLoginFailed(); return; } @@ -98,6 +70,5 @@ void LoginDialog::loginThroughSteam() { } void LoginDialog::openUrl(const QString& url) { - qDebug() << url; QDesktopServices::openUrl(url); } diff --git a/interface/src/ui/LoginDialog.h b/interface/src/ui/LoginDialog.h index 0dd4b5e96f..dcd0e04894 100644 --- a/interface/src/ui/LoginDialog.h +++ b/interface/src/ui/LoginDialog.h @@ -20,32 +20,19 @@ class LoginDialog : public OffscreenQmlDialog { Q_OBJECT HIFI_QML_DECL - Q_PROPERTY(QString statusText READ statusText WRITE setStatusText NOTIFY statusTextChanged) - Q_PROPERTY(QString rootUrl READ rootUrl) - public: static void toggleAction(); LoginDialog(QQuickItem* parent = nullptr); - void setStatusText(const QString& statusText); - QString statusText() const; - - QString rootUrl() const; - signals: - void statusTextChanged(); - -protected: - void handleLoginCompleted(const QUrl& authURL); + void handleLoginCompleted(); void handleLoginFailed(); +protected: Q_INVOKABLE void login(const QString& username, const QString& password); Q_INVOKABLE void loginThroughSteam(); Q_INVOKABLE void openUrl(const QString& url); -private: - QString _statusText; - const QString _rootUrl; }; #endif // hifi_LoginDialog_h diff --git a/libraries/networking/src/NetworkingConstants.h b/libraries/networking/src/NetworkingConstants.h index a512ae8887..d1e0a46c71 100644 --- a/libraries/networking/src/NetworkingConstants.h +++ b/libraries/networking/src/NetworkingConstants.h @@ -15,7 +15,7 @@ #include namespace NetworkingConstants { - const QUrl METAVERSE_SERVER_URL = QUrl("https://metaverse.highfidelity.com"); + const QUrl METAVERSE_SERVER_URL = QUrl("http://localhost:3000"); } #endif // hifi_NetworkingConstants_h From f0ff9752480485c9ddb5f8bae1afbb67550fe47c Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Fri, 22 Jul 2016 19:48:52 -0700 Subject: [PATCH 04/22] UI wiring --- interface/resources/qml/LoginDialog.qml | 23 +-- .../qml/LoginDialog/CompleteProfileBody.qml | 37 +++++ .../qml/LoginDialog/EmailSentBody.qml | 6 +- .../qml/LoginDialog/LinkAccountBody.qml | 81 +++++++++- .../qml/LoginDialog/RecoverPasswordBody.qml | 38 ++++- .../resources/qml/LoginDialog/SignInBody.qml | 18 +++ .../qml/LoginDialog/UsernameCollisionBody.qml | 149 ++++++++---------- .../resources/qml/LoginDialog/WelcomeBody.qml | 17 +- .../scripting/AccountScriptingInterface.cpp | 3 + .../src/scripting/AccountScriptingInterface.h | 5 + interface/src/ui/LoginDialog.cpp | 92 +++++++++++ interface/src/ui/LoginDialog.h | 24 ++- libraries/networking/src/AccountManager.cpp | 1 + .../src/steamworks-wrapper/SteamClient.cpp | 23 ++- .../src/steamworks-wrapper/SteamClient.h | 2 + 15 files changed, 394 insertions(+), 125 deletions(-) diff --git a/interface/resources/qml/LoginDialog.qml b/interface/resources/qml/LoginDialog.qml index 3e8747c076..1f84024e15 100644 --- a/interface/resources/qml/LoginDialog.qml +++ b/interface/resources/qml/LoginDialog.qml @@ -33,34 +33,13 @@ ModalWindow { property string title: "" property int titleWidth: 0 - Component { - id: signInBody - SignInBody {} - } - Component { - id: welcomeBody - WelcomeBody {} - } - LoginDialog { id: loginDialog Loader { id: bodyLoader anchors.fill: parent - sourceComponent: signInBody - } - - Connections { - target: loginDialog - onHandleLoginCompleted: { - console.log("Login Succeeded") - bodyLoader.sourceComponent = welcomeBody - bodyLoader.active = true - } - onHandleLoginFailed: { - console.log("Login Failed") - } + source: loginDialog.isSteamRunning() ? "LoginDialog/SignInBody.qml" : "LoginDialog/LinkAccountBody.qml" } } diff --git a/interface/resources/qml/LoginDialog/CompleteProfileBody.qml b/interface/resources/qml/LoginDialog/CompleteProfileBody.qml index b6ef012e2a..12d2cee73e 100644 --- a/interface/resources/qml/LoginDialog/CompleteProfileBody.qml +++ b/interface/resources/qml/LoginDialog/CompleteProfileBody.qml @@ -54,6 +54,8 @@ Item { text: qsTr("Create your profile") color: hifi.buttons.blue + + onClicked: loginDialog.createAccountFromStream() } Button { @@ -83,6 +85,15 @@ Item { lineHeight: 2 lineHeightMode: Text.ProportionalHeight horizontalAlignment: Text.AlignHCenter + + MouseArea { + anchors.fill: parent + onClicked: { + bodyLoader.source = "LinkAccountBody.qml" + bodyLoader.item.width = root.pane.width + bodyLoader.item.height = root.pane.height + } + } } Component.onCompleted: { @@ -90,4 +101,30 @@ Item { root.iconText = "<" d.resize(); } + + Connections { + target: loginDialog + onHandleCreateCompleted: { + console.log("Create Succeeded") + + loginDialog.loginThroughSteam() + } + onHandleCreateFailed: { + console.log("Create Failed: " + error) + + bodyLoader.source = "UsernameCollisionBody.qml" + bodyLoader.item.width = root.pane.width + bodyLoader.item.height = root.pane.height + } + onHandleLoginCompleted: { + console.log("Login Succeeded") + + bodyLoader.setSource("WelcomeBody.qml", { "welcomeBack" : false }) + bodyLoader.item.width = root.pane.width + bodyLoader.item.height = root.pane.height + } + onHandleLoginFailed: { + console.log("Login Failed") + } + } } diff --git a/interface/resources/qml/LoginDialog/EmailSentBody.qml b/interface/resources/qml/LoginDialog/EmailSentBody.qml index eede996412..489385864b 100644 --- a/interface/resources/qml/LoginDialog/EmailSentBody.qml +++ b/interface/resources/qml/LoginDialog/EmailSentBody.qml @@ -17,10 +17,10 @@ import "../styles-uit" Item { id: emailSentBody clip: true - width: pane.width - height: pane.height + width: root.pane.width + height: root.pane.height - property string email: "clement@highfidelity.com" + property string email: "" QtObject { id: d diff --git a/interface/resources/qml/LoginDialog/LinkAccountBody.qml b/interface/resources/qml/LoginDialog/LinkAccountBody.qml index b7ff756fa3..da5f0f1a42 100644 --- a/interface/resources/qml/LoginDialog/LinkAccountBody.qml +++ b/interface/resources/qml/LoginDialog/LinkAccountBody.qml @@ -19,10 +19,14 @@ import "../styles-uit" Item { id: linkAccountBody clip: true - width: pane.width - height: pane.height + width: root.pane.width + height: root.pane.height - property bool existingEmail: true + property bool existingEmail: false + + function login() { + loginDialog.login(usernameField.text, passwordField.text) + } QtObject { id: d @@ -64,7 +68,7 @@ Item { Column { id: form anchors { - top: mainTextContainer.bottom + top: mainTextContainer.visible ? mainTextContainer.bottom : parent.top left: parent.left margins: 0 topMargin: 2 * hifi.dimensions.contentSpacing.y @@ -96,6 +100,15 @@ Item { verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignHCenter + + MouseArea { + anchors.fill: parent + onClicked: { + bodyLoader.source = "RecoverPasswordBody.qml" + bodyLoader.item.width = root.pane.width + bodyLoader.item.height = root.pane.height + } + } } } Row { @@ -124,6 +137,15 @@ Item { verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignHCenter + + MouseArea { + anchors.fill: parent + onClicked: { + bodyLoader.source = "RecoverPasswordBody.qml" + bodyLoader.item.width = root.pane.width + bodyLoader.item.height = root.pane.height + } + } } } @@ -141,11 +163,14 @@ Item { onHeightChanged: d.resize(); onWidthChanged: d.resize(); Button { + id: linkAccountButton anchors.verticalCenter: parent.verticalCenter width: 200 - text: qsTr("Link Account") + text: qsTr(loginDialog.isSteamRunning() ? "Link Account" : "Login") color: hifi.buttons.blue + + onClicked: linkAccountBody.login() } Button { @@ -161,5 +186,51 @@ Item { root.title = qsTr("Sign Into High Fidelity") root.iconText = "<" d.resize(); + + usernameField.forceActiveFocus() + } + + Connections { + target: loginDialog + onHandleLoginCompleted: { + console.log("Login Succeeded, linking steam account") + + if (loginDialog.isSteamRunning()) { + loginDialog.linkSteam() + } else { + bodyLoader.setSource("WelcomeBody.qml", { "welcomeBack" : true }) + bodyLoader.item.width = root.pane.width + bodyLoader.item.height = root.pane.height + } + } + onHandleLoginFailed: { + console.log("Login Failed") + + } + onHandleLinkCompleted: { + console.log("Link Succeeded") + + bodyLoader.setSource("WelcomeBody.qml", { "welcomeBack" : true }) + bodyLoader.item.width = root.pane.width + bodyLoader.item.height = root.pane.height + } + onHandleLinkFailed: { + console.log("Link Failed") + + } + } + + Keys.onPressed: { + if (!visible) { + return + } + + switch (event.key) { + case Qt.Key_Enter: + case Qt.Key_Return: + event.accepted = true + linkAccountBody.login() + break + } } } diff --git a/interface/resources/qml/LoginDialog/RecoverPasswordBody.qml b/interface/resources/qml/LoginDialog/RecoverPasswordBody.qml index 74dcb18054..3c6e101e2a 100644 --- a/interface/resources/qml/LoginDialog/RecoverPasswordBody.qml +++ b/interface/resources/qml/LoginDialog/RecoverPasswordBody.qml @@ -19,8 +19,16 @@ import "../styles-uit" Item { id: recoverPasswordBody clip: true - width: pane.width - height: pane.height + width: root.pane.width + height: root.pane.height + + function send() { + loginDialog.sendRecoveryEmail(emailField.text) + + bodyLoader.setSource("EmailSentBody.qml", { "email": emailField.text }) + bodyLoader.item.width = root.pane.width + bodyLoader.item.height = root.pane.height + } QtObject { id: d @@ -70,6 +78,10 @@ Item { width: 350 label: "Email address" + + Component.onCompleted: { + emailField.forceActiveFocus() + } } Row { @@ -89,12 +101,20 @@ Item { text: qsTr("Send recovery email") color: hifi.buttons.blue + + onClicked: recoverPasswordBody.send() } Button { anchors.verticalCenter: parent.verticalCenter text: qsTr("Back") + + onClicked: { + bodyLoader.source = "LinkAccountBody.qml" + bodyLoader.item.width = root.pane.width + bodyLoader.item.height = root.pane.height + } } } @@ -103,4 +123,18 @@ Item { root.iconText = "<" d.resize(); } + + Keys.onPressed: { + if (!visible) { + return + } + + switch (event.key) { + case Qt.Key_Enter: + case Qt.Key_Return: + event.accepted = true + recoverPasswordBody.send() + break + } + } } diff --git a/interface/resources/qml/LoginDialog/SignInBody.qml b/interface/resources/qml/LoginDialog/SignInBody.qml index d3f6926bd2..2da0ea856d 100644 --- a/interface/resources/qml/LoginDialog/SignInBody.qml +++ b/interface/resources/qml/LoginDialog/SignInBody.qml @@ -107,4 +107,22 @@ Item { root.iconText = "" d.resize(); } + + Connections { + target: loginDialog + onHandleLoginCompleted: { + console.log("Login Succeeded") + + bodyLoader.setSource("WelcomeBody.qml", { "welcomeBack" : true }) + bodyLoader.item.width = root.pane.width + bodyLoader.item.height = root.pane.height + } + onHandleLoginFailed: { + console.log("Login Failed") + + bodyLoader.source = "CompleteProfileBody.qml" + bodyLoader.item.width = root.pane.width + bodyLoader.item.height = root.pane.height + } + } } diff --git a/interface/resources/qml/LoginDialog/UsernameCollisionBody.qml b/interface/resources/qml/LoginDialog/UsernameCollisionBody.qml index ea5a9bb614..f0663631a8 100644 --- a/interface/resources/qml/LoginDialog/UsernameCollisionBody.qml +++ b/interface/resources/qml/LoginDialog/UsernameCollisionBody.qml @@ -19,8 +19,8 @@ import "../styles-uit" Item { id: usernameCollisionBody clip: true - width: pane.width - height: pane.height + width: root.pane.width + height: root.pane.height QtObject { id: d @@ -30,26 +30,59 @@ Item { readonly property int maxHeight: 720 function resize() { - var targetWidth = Math.max(titleWidth, mainTextContainer.visible ? mainTextContainer.contentWidth : 0) - var targetHeight = (mainTextContainer.visible ? mainTextContainer.height : 0) + - 4 * hifi.dimensions.contentSpacing.y + form.height + - 4 * hifi.dimensions.contentSpacing.y + buttons.height + var targetWidth = Math.max(titleWidth, Math.max(mainTextContainer.contentWidth, + termsContainer.contentWidth)) + var targetHeight = mainTextContainer.height + + 2 * hifi.dimensions.contentSpacing.y + textField.height + + 5 * hifi.dimensions.contentSpacing.y + termsContainer.height + + 1 * hifi.dimensions.contentSpacing.y + buttons.height root.width = Math.max(d.minWidth, Math.min(d.maxWidth, targetWidth)) root.height = Math.max(d.minHeight, Math.min(d.maxHeight, targetHeight)) } } - MenuItem { + ShortcutText { id: mainTextContainer anchors { top: parent.top - horizontalCenter: parent.horizontalCenter + left: parent.left margins: 0 topMargin: hifi.dimensions.contentSpacing.y } - text: qsTr("Choose your High Fidelity user name:") + text: qsTr("Your Steam username is not available.") + wrapMode: Text.WordWrap + color: hifi.colors.redAccent + lineHeight: 1 + lineHeightMode: Text.ProportionalHeight + horizontalAlignment: Text.AlignHCenter + } + + + TextField { + id: textField + anchors { + top: mainTextContainer.bottom + left: parent.left + margins: 0 + topMargin: 2 * hifi.dimensions.contentSpacing.y + } + width: 250 + + placeholderText: "Choose your own" + } + + MenuItem { + id: termsContainer + anchors { + top: textField.bottom + left: parent.left + margins: 0 + topMargin: 3 * hifi.dimensions.contentSpacing.y + } + + text: qsTr("By creating this user profile, you agree to High Fidelity's Terms of Service") wrapMode: Text.WordWrap color: hifi.colors.baseGrayHighlight lineHeight: 1 @@ -57,82 +90,13 @@ Item { horizontalAlignment: Text.AlignHCenter } - - Column { - id: form - anchors { - top: mainTextContainer.bottom - left: parent.left - margins: 0 - topMargin: 2 * hifi.dimensions.contentSpacing.y - } - spacing: 2 * hifi.dimensions.contentSpacing.y - - Row { - spacing: hifi.dimensions.contentSpacing.x - - TextField { - id: usernameField - anchors { - verticalCenter: parent.verticalCenter - } - width: 350 - - label: "User Name or Email" - } - - ShortcutText { - anchors { - verticalCenter: parent.verticalCenter - } - - text: "Need help?" - - color: hifi.colors.blueAccent - font.underline: true - - verticalAlignment: Text.AlignVCenter - horizontalAlignment: Text.AlignHCenter - } - } - Row { - spacing: hifi.dimensions.contentSpacing.x - - TextField { - id: passwordField - anchors { - verticalCenter: parent.verticalCenter - } - width: 350 - - label: "Password" - echoMode: TextInput.Password - } - - ShortcutText { - anchors { - verticalCenter: parent.verticalCenter - } - - text: "Need help?" - - color: hifi.colors.blueAccent - font.underline: true - - verticalAlignment: Text.AlignVCenter - horizontalAlignment: Text.AlignHCenter - } - } - - } - Row { id: buttons anchors { - top: form.bottom + top: termsContainer.bottom right: parent.right margins: 0 - topMargin: 3 * hifi.dimensions.contentSpacing.y + topMargin: 1 * hifi.dimensions.contentSpacing.y } spacing: hifi.dimensions.contentSpacing.x onHeightChanged: d.resize(); onWidthChanged: d.resize(); @@ -143,6 +107,10 @@ Item { text: qsTr("Create your profile") color: hifi.buttons.blue + + onClicked: { + loginDialog.createAccountFromStream(textField.text) + } } Button { @@ -159,4 +127,25 @@ Item { root.iconText = "<" d.resize(); } + Connections { + target: loginDialog + onHandleCreateCompleted: { + console.log("Create Succeeded") + + loginDialog.loginThroughSteam() + } + onHandleCreateFailed: { + console.log("Create Failed: " + error) + } + onHandleLoginCompleted: { + console.log("Login Succeeded") + + bodyLoader.setSource("WelcomeBody.qml", { "welcomeBack" : false }) + bodyLoader.item.width = root.pane.width + bodyLoader.item.height = root.pane.height + } + onHandleLoginFailed: { + console.log("Login Failed") + } + } } diff --git a/interface/resources/qml/LoginDialog/WelcomeBody.qml b/interface/resources/qml/LoginDialog/WelcomeBody.qml index 8b771eac1f..ecc848cdc0 100644 --- a/interface/resources/qml/LoginDialog/WelcomeBody.qml +++ b/interface/resources/qml/LoginDialog/WelcomeBody.qml @@ -20,7 +20,13 @@ Item { width: pane.width height: pane.height - property bool welcomeBack: true + property bool welcomeBack: false + + function setTitle() { + root.title = (welcomeBack ? qsTr("Welcome back ") : qsTr("Welcome ")) + Account.username + qsTr("!") + root.iconText = "" + d.resize(); + } QtObject { id: d @@ -75,9 +81,10 @@ Item { } } - Component.onCompleted: { - root.title = (welcomeBack ? qsTr("Welcome back ") : qsTr("Welcome ")) + Account.getUsername() + qsTr("!") - root.iconText = "" - d.resize(); + Component.onCompleted: welcomeBody.setTitle() + + Connections { + target: Account + onUsernameChanged: welcomeBody.setTitle() } } diff --git a/interface/src/scripting/AccountScriptingInterface.cpp b/interface/src/scripting/AccountScriptingInterface.cpp index 1328197195..4090c99ac8 100644 --- a/interface/src/scripting/AccountScriptingInterface.cpp +++ b/interface/src/scripting/AccountScriptingInterface.cpp @@ -15,6 +15,9 @@ AccountScriptingInterface* AccountScriptingInterface::getInstance() { static AccountScriptingInterface sharedInstance; + auto accountManager = DependencyManager::get(); + QObject::connect(accountManager.data(), &AccountManager::profileChanged, + &sharedInstance, &AccountScriptingInterface::usernameChanged); return &sharedInstance; } diff --git a/interface/src/scripting/AccountScriptingInterface.h b/interface/src/scripting/AccountScriptingInterface.h index 888149b836..49648781ce 100644 --- a/interface/src/scripting/AccountScriptingInterface.h +++ b/interface/src/scripting/AccountScriptingInterface.h @@ -17,6 +17,11 @@ class AccountScriptingInterface : public QObject { Q_OBJECT + Q_PROPERTY(QString username READ getUsername NOTIFY usernameChanged) + +signals: + void usernameChanged(); + public slots: static AccountScriptingInterface* getInstance(); QString getUsername(); diff --git a/interface/src/ui/LoginDialog.cpp b/interface/src/ui/LoginDialog.cpp index 15a277f394..b65e111b16 100644 --- a/interface/src/ui/LoginDialog.cpp +++ b/interface/src/ui/LoginDialog.cpp @@ -12,6 +12,8 @@ #include "LoginDialog.h" #include +#include +#include #include #include @@ -52,6 +54,10 @@ void LoginDialog::toggleAction() { } } +bool LoginDialog::isSteamRunning() { + return SteamClient::isRunning(); +} + void LoginDialog::login(const QString& username, const QString& password) { qDebug() << "Attempting to login " << username; DependencyManager::get()->requestAccessToken(username, password); @@ -69,6 +75,92 @@ void LoginDialog::loginThroughSteam() { }); } +void LoginDialog::linkSteam() { + qDebug() << "Attempting to link Steam account"; + SteamClient::requestTicket([this](Ticket ticket) { + if (ticket.isNull()) { + emit handleLoginFailed(); + return; + } + + JSONCallbackParameters callbackParams; + callbackParams.jsonCallbackReceiver = this; + callbackParams.jsonCallbackMethod = "linkCompleted"; + callbackParams.errorCallbackReceiver = this; + callbackParams.errorCallbackMethod = "linkFailed"; + + const QString LINK_STEAM_PATH = "api/v1/user/link_steam"; + + QJsonObject payload; + payload.insert("ticket", QJsonValue::fromVariant(QVariant(ticket))); + + auto accountManager = DependencyManager::get(); + accountManager->sendRequest(LINK_STEAM_PATH, AccountManagerAuth::Required, + QNetworkAccessManager::PostOperation, callbackParams, + QJsonDocument(payload).toJson()); + }); +} + +void LoginDialog::createAccountFromStream(QString username) { + qDebug() << "Attempting to create account from Steam info"; + SteamClient::requestTicket([this, username](Ticket ticket) { + if (ticket.isNull()) { + emit handleLoginFailed(); + return; + } + + JSONCallbackParameters callbackParams; + callbackParams.jsonCallbackReceiver = this; + callbackParams.jsonCallbackMethod = "createCompleted"; + callbackParams.errorCallbackReceiver = this; + callbackParams.errorCallbackMethod = "createFailed"; + + const QString CREATE_ACCOUNT_FROM_STEAM_PATH = "api/v1/user/create_from_steam"; + + QJsonObject payload; + payload.insert("ticket", QJsonValue::fromVariant(QVariant(ticket))); + if (!username.isEmpty()) { + payload.insert("username", QJsonValue::fromVariant(QVariant(username))); + } + + auto accountManager = DependencyManager::get(); + accountManager->sendRequest(CREATE_ACCOUNT_FROM_STEAM_PATH, AccountManagerAuth::None, + QNetworkAccessManager::PostOperation, callbackParams, + QJsonDocument(payload).toJson()); + }); + +} + void LoginDialog::openUrl(const QString& url) { QDesktopServices::openUrl(url); } + +void LoginDialog::sendRecoveryEmail(const QString& email) { + const QString PASSWORD_RESET_PATH = "/users/password"; + + QJsonObject payload; + payload.insert("user_email", QJsonValue::fromVariant(QVariant(email))); + + + auto accountManager = DependencyManager::get(); + accountManager->sendRequest(PASSWORD_RESET_PATH, AccountManagerAuth::None, + QNetworkAccessManager::PostOperation, JSONCallbackParameters(), + QJsonDocument(payload).toJson()); +} + +void LoginDialog::linkCompleted(QNetworkReply& reply) { + emit handleLinkCompleted(); +} + +void LoginDialog::linkFailed(QNetworkReply& reply) { + emit handleLinkFailed(reply.errorString()); +} + +void LoginDialog::createCompleted(QNetworkReply& reply) { + emit handleCreateCompleted(); +} + +void LoginDialog::createFailed(QNetworkReply& reply) { + emit handleCreateFailed(reply.errorString()); +} + diff --git a/interface/src/ui/LoginDialog.h b/interface/src/ui/LoginDialog.h index dcd0e04894..ef2c937201 100644 --- a/interface/src/ui/LoginDialog.h +++ b/interface/src/ui/LoginDialog.h @@ -16,6 +16,8 @@ #include +class QNetworkReply; + class LoginDialog : public OffscreenQmlDialog { Q_OBJECT HIFI_QML_DECL @@ -29,10 +31,30 @@ signals: void handleLoginCompleted(); void handleLoginFailed(); -protected: + void handleLinkCompleted(); + void handleLinkFailed(QString error); + + void handleCreateCompleted(); + void handleCreateFailed(QString error); + +public slots: + void linkCompleted(QNetworkReply& reply); + void linkFailed(QNetworkReply& reply); + + void createCompleted(QNetworkReply& reply); + void createFailed(QNetworkReply& reply); + +protected slots: + Q_INVOKABLE bool isSteamRunning(); + Q_INVOKABLE void login(const QString& username, const QString& password); Q_INVOKABLE void loginThroughSteam(); + Q_INVOKABLE void linkSteam(); + Q_INVOKABLE void createAccountFromStream(QString username = QString()); + Q_INVOKABLE void openUrl(const QString& url); + Q_INVOKABLE void sendRecoveryEmail(const QString& email); + }; #endif // hifi_LoginDialog_h diff --git a/libraries/networking/src/AccountManager.cpp b/libraries/networking/src/AccountManager.cpp index 8c0fa5ed92..52d9e87636 100644 --- a/libraries/networking/src/AccountManager.cpp +++ b/libraries/networking/src/AccountManager.cpp @@ -568,6 +568,7 @@ void AccountManager::requestAccessTokenFinished() { void AccountManager::requestAccessTokenError(QNetworkReply::NetworkError error) { // TODO: error handling qCDebug(networking) << "AccountManager requestError - " << error; + emit loginFailed(); } void AccountManager::requestProfile() { diff --git a/libraries/steamworks-wrapper/src/steamworks-wrapper/SteamClient.cpp b/libraries/steamworks-wrapper/src/steamworks-wrapper/SteamClient.cpp index 1dbfc0ce00..a8a57064de 100644 --- a/libraries/steamworks-wrapper/src/steamworks-wrapper/SteamClient.cpp +++ b/libraries/steamworks-wrapper/src/steamworks-wrapper/SteamClient.cpp @@ -133,8 +133,16 @@ void SteamTicketRequests::onGetAuthSessionTicketResponse(GetAuthSessionTicketRes static std::atomic_bool initialized { false }; static std::unique_ptr steamTicketRequests; -bool SteamClient::init() { + +bool SteamClient::isRunning() { if (!initialized) { + init(); + } + return initialized; +} + +bool SteamClient::init() { + if (SteamAPI_IsSteamRunning() && !initialized) { initialized = SteamAPI_Init(); } @@ -157,11 +165,6 @@ void SteamClient::shutdown() { void SteamClient::runCallbacks() { if (!initialized) { - init(); - } - - if (!initialized) { - qDebug() << "Steam not initialized"; return; } @@ -176,7 +179,13 @@ void SteamClient::runCallbacks() { void SteamClient::requestTicket(TicketRequestCallback callback) { if (!initialized) { - init(); + if (SteamAPI_IsSteamRunning()) { + init(); + } else { + qWarning() << "Steam is not running"; + callback(INVALID_TICKET); + return; + } } if (!initialized) { diff --git a/libraries/steamworks-wrapper/src/steamworks-wrapper/SteamClient.h b/libraries/steamworks-wrapper/src/steamworks-wrapper/SteamClient.h index ac5c648ead..f7ca775829 100644 --- a/libraries/steamworks-wrapper/src/steamworks-wrapper/SteamClient.h +++ b/libraries/steamworks-wrapper/src/steamworks-wrapper/SteamClient.h @@ -22,6 +22,8 @@ using TicketRequestCallback = std::function; class SteamClient { public: + static bool isRunning(); + static bool init(); static void shutdown(); From 0663766074da67ea4377002d9fdaeca2edca655d Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 25 Jul 2016 14:52:02 -0700 Subject: [PATCH 05/22] Replace metaverse server with testing URL --- libraries/networking/src/NetworkingConstants.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/networking/src/NetworkingConstants.h b/libraries/networking/src/NetworkingConstants.h index d1e0a46c71..154470201f 100644 --- a/libraries/networking/src/NetworkingConstants.h +++ b/libraries/networking/src/NetworkingConstants.h @@ -15,7 +15,7 @@ #include namespace NetworkingConstants { - const QUrl METAVERSE_SERVER_URL = QUrl("http://localhost:3000"); + const QUrl METAVERSE_SERVER_URL = QUrl("https://hifi.ngrok.io"); } #endif // hifi_NetworkingConstants_h From e5290076be650d63e1a97af0fefe4556c6ab2386 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 26 Jul 2016 17:25:52 -0700 Subject: [PATCH 06/22] First draft for Steam friends --- .../src/steamworks-wrapper/SteamClient.cpp | 51 ++++++++++++++----- 1 file changed, 38 insertions(+), 13 deletions(-) diff --git a/libraries/steamworks-wrapper/src/steamworks-wrapper/SteamClient.cpp b/libraries/steamworks-wrapper/src/steamworks-wrapper/SteamClient.cpp index a8a57064de..de95269d1a 100644 --- a/libraries/steamworks-wrapper/src/steamworks-wrapper/SteamClient.cpp +++ b/libraries/steamworks-wrapper/src/steamworks-wrapper/SteamClient.cpp @@ -12,7 +12,6 @@ #include "SteamClient.h" #include -#include #include @@ -37,13 +36,15 @@ public: HAuthTicket startRequest(TicketRequestCallback callback); void stopRequest(HAuthTicket authTicket); + void stopAll(); STEAM_CALLBACK(SteamTicketRequests, onGetAuthSessionTicketResponse, GetAuthSessionTicketResponse_t, _getAuthSessionTicketResponse); -private: - void stopAll(); + STEAM_CALLBACK(SteamTicketRequests, onGameRichPresenceJoinRequested, + GameRichPresenceJoinRequested_t, _gameRichPresenceJoinRequestedResponse); +private: struct PendingTicket { HAuthTicket authTicket; Ticket ticket; @@ -54,7 +55,8 @@ private: }; SteamTicketRequests::SteamTicketRequests() : - _getAuthSessionTicketResponse(this, &SteamTicketRequests::onGetAuthSessionTicketResponse) + _getAuthSessionTicketResponse(this, &SteamTicketRequests::onGetAuthSessionTicketResponse), + _gameRichPresenceJoinRequestedResponse(this, &SteamTicketRequests::onGameRichPresenceJoinRequested) { } @@ -128,10 +130,35 @@ void SteamTicketRequests::onGetAuthSessionTicketResponse(GetAuthSessionTicketRes } } +#include +#include +#include +#include +#include +const QString PREFIX = "--url \""; +const QString SUFFIX = "\""; + + +void SteamTicketRequests::onGameRichPresenceJoinRequested(GameRichPresenceJoinRequested_t* pCallback) { + auto url = QString::fromLocal8Bit(pCallback->m_rgchConnect); + + if (url.startsWith(PREFIX) && url.endsWith(SUFFIX)) { + url.remove(0, PREFIX.size()); + url.remove(-SUFFIX.size(), SUFFIX.size()); + } + + qDebug() << "Joining:" << url; + auto mimeData = new QMimeData(); + mimeData->setUrls(QList() << QUrl(url)); + auto event = new QDropEvent(QPointF(0,0), Qt::MoveAction, mimeData, Qt::LeftButton, Qt::NoModifier); + + QCoreApplication::postEvent(qApp, event); +} + static std::atomic_bool initialized { false }; -static std::unique_ptr steamTicketRequests; +static SteamTicketRequests steamTicketRequests; bool SteamClient::isRunning() { @@ -144,12 +171,12 @@ bool SteamClient::isRunning() { bool SteamClient::init() { if (SteamAPI_IsSteamRunning() && !initialized) { initialized = SteamAPI_Init(); - } - if (!steamTicketRequests && initialized) { - steamTicketRequests.reset(new SteamTicketRequests()); + if (initialized) { + SteamFriends()->SetRichPresence("status", "Localhost"); + SteamFriends()->SetRichPresence("connect", "--url \"hifi://10.0.0.185:40117/10,10,10\""); + } } - return initialized; } @@ -158,9 +185,7 @@ void SteamClient::shutdown() { SteamAPI_Shutdown(); } - if (steamTicketRequests) { - steamTicketRequests.reset(); - } + steamTicketRequests.stopAll(); } void SteamClient::runCallbacks() { @@ -193,7 +218,7 @@ void SteamClient::requestTicket(TicketRequestCallback callback) { return; } - steamTicketRequests->startRequest(callback); + steamTicketRequests.startRequest(callback); } From a13950752bd12e01e7780186ad266b9ac0bd8f95 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 27 Jul 2016 13:32:31 -0700 Subject: [PATCH 07/22] Update steam location with discoverability --- interface/src/DiscoverabilityManager.cpp | 15 ++-- .../src/steamworks-wrapper/SteamClient.cpp | 69 ++++++++++++------- .../src/steamworks-wrapper/SteamClient.h | 3 + 3 files changed, 55 insertions(+), 32 deletions(-) diff --git a/interface/src/DiscoverabilityManager.cpp b/interface/src/DiscoverabilityManager.cpp index 4051bd8a1e..3b7d544394 100644 --- a/interface/src/DiscoverabilityManager.cpp +++ b/interface/src/DiscoverabilityManager.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -36,11 +37,11 @@ const QString SESSION_ID_KEY = "session_id"; void DiscoverabilityManager::updateLocation() { auto accountManager = DependencyManager::get(); - - if (_mode.get() != Discoverability::None && accountManager->isLoggedIn()) { - auto addressManager = DependencyManager::get(); - DomainHandler& domainHandler = DependencyManager::get()->getDomainHandler(); + auto addressManager = DependencyManager::get(); + auto& domainHandler = DependencyManager::get()->getDomainHandler(); + + if (_mode.get() != Discoverability::None && accountManager->isLoggedIn()) { // construct a QJsonObject given the user's current address information QJsonObject rootObject; @@ -48,8 +49,6 @@ void DiscoverabilityManager::updateLocation() { QString pathString = addressManager->currentPath(); - const QString LOCATION_KEY_IN_ROOT = "location"; - const QString PATH_KEY_IN_LOCATION = "path"; locationObject.insert(PATH_KEY_IN_LOCATION, pathString); @@ -90,6 +89,7 @@ void DiscoverabilityManager::updateLocation() { // we have a changed location, send it now _lastLocationObject = locationObject; + const QString LOCATION_KEY_IN_ROOT = "location"; rootObject.insert(LOCATION_KEY_IN_ROOT, locationObject); apiPath = API_USER_LOCATION_PATH; @@ -109,6 +109,9 @@ void DiscoverabilityManager::updateLocation() { accountManager->sendRequest(API_USER_HEARTBEAT_PATH, AccountManagerAuth::Optional, QNetworkAccessManager::PutOperation, callbackParameters); } + + // Update Steam + SteamClient::updateLocation(domainHandler.getHostname(), addressManager->currentAddress()); } void DiscoverabilityManager::handleHeartbeatResponse(QNetworkReply& requestReply) { diff --git a/libraries/steamworks-wrapper/src/steamworks-wrapper/SteamClient.cpp b/libraries/steamworks-wrapper/src/steamworks-wrapper/SteamClient.cpp index de95269d1a..f775efe2f6 100644 --- a/libraries/steamworks-wrapper/src/steamworks-wrapper/SteamClient.cpp +++ b/libraries/steamworks-wrapper/src/steamworks-wrapper/SteamClient.cpp @@ -13,7 +13,12 @@ #include +#include #include +#include +#include +#include +#include #if defined(__GNUC__) && !defined(__clang__) #pragma GCC diagnostic push @@ -41,9 +46,6 @@ public: STEAM_CALLBACK(SteamTicketRequests, onGetAuthSessionTicketResponse, GetAuthSessionTicketResponse_t, _getAuthSessionTicketResponse); - STEAM_CALLBACK(SteamTicketRequests, onGameRichPresenceJoinRequested, - GameRichPresenceJoinRequested_t, _gameRichPresenceJoinRequestedResponse); - private: struct PendingTicket { HAuthTicket authTicket; @@ -55,8 +57,7 @@ private: }; SteamTicketRequests::SteamTicketRequests() : - _getAuthSessionTicketResponse(this, &SteamTicketRequests::onGetAuthSessionTicketResponse), - _gameRichPresenceJoinRequestedResponse(this, &SteamTicketRequests::onGameRichPresenceJoinRequested) + _getAuthSessionTicketResponse(this, &SteamTicketRequests::onGetAuthSessionTicketResponse) { } @@ -130,24 +131,37 @@ void SteamTicketRequests::onGetAuthSessionTicketResponse(GetAuthSessionTicketRes } } -#include -#include -#include -#include -#include -const QString PREFIX = "--url \""; -const QString SUFFIX = "\""; +const QString CONNECT_PREFIX = "--url \""; +const QString CONNECT_SUFFIX = "\""; -void SteamTicketRequests::onGameRichPresenceJoinRequested(GameRichPresenceJoinRequested_t* pCallback) { +class SteamCallbackManager { +public: + SteamCallbackManager(); + + STEAM_CALLBACK(SteamCallbackManager, onGameRichPresenceJoinRequested, + GameRichPresenceJoinRequested_t, _gameRichPresenceJoinRequestedResponse); + + SteamTicketRequests& getTicketRequests() { return _steamTicketRequests; } + +private: + SteamTicketRequests _steamTicketRequests; +}; + +SteamCallbackManager::SteamCallbackManager() : +_gameRichPresenceJoinRequestedResponse(this, &SteamCallbackManager::onGameRichPresenceJoinRequested) +{ +} + +void SteamCallbackManager::onGameRichPresenceJoinRequested(GameRichPresenceJoinRequested_t* pCallback) { auto url = QString::fromLocal8Bit(pCallback->m_rgchConnect); - if (url.startsWith(PREFIX) && url.endsWith(SUFFIX)) { - url.remove(0, PREFIX.size()); - url.remove(-SUFFIX.size(), SUFFIX.size()); + if (url.startsWith(CONNECT_PREFIX) && url.endsWith(CONNECT_SUFFIX)) { + url.remove(0, CONNECT_PREFIX.size()); + url.remove(-CONNECT_SUFFIX.size(), CONNECT_SUFFIX.size()); } - qDebug() << "Joining:" << url; + qDebug() << "Joining Steam Friends at:" << url; auto mimeData = new QMimeData(); mimeData->setUrls(QList() << QUrl(url)); auto event = new QDropEvent(QPointF(0,0), Qt::MoveAction, mimeData, Qt::LeftButton, Qt::NoModifier); @@ -156,9 +170,8 @@ void SteamTicketRequests::onGameRichPresenceJoinRequested(GameRichPresenceJoinRe } - static std::atomic_bool initialized { false }; -static SteamTicketRequests steamTicketRequests; +static SteamCallbackManager steamCallbackManager; bool SteamClient::isRunning() { @@ -171,11 +184,6 @@ bool SteamClient::isRunning() { bool SteamClient::init() { if (SteamAPI_IsSteamRunning() && !initialized) { initialized = SteamAPI_Init(); - - if (initialized) { - SteamFriends()->SetRichPresence("status", "Localhost"); - SteamFriends()->SetRichPresence("connect", "--url \"hifi://10.0.0.185:40117/10,10,10\""); - } } return initialized; } @@ -185,7 +193,7 @@ void SteamClient::shutdown() { SteamAPI_Shutdown(); } - steamTicketRequests.stopAll(); + steamCallbackManager.getTicketRequests().stopAll(); } void SteamClient::runCallbacks() { @@ -218,7 +226,16 @@ void SteamClient::requestTicket(TicketRequestCallback callback) { return; } - steamTicketRequests.startRequest(callback); + steamCallbackManager.getTicketRequests().startRequest(callback); } +void SteamClient::updateLocation(QString status, QUrl locationUrl) { + if (!initialized) { + return; + } + auto connectStr = locationUrl.isEmpty() ? "" : CONNECT_PREFIX + locationUrl.toString() + CONNECT_SUFFIX; + + SteamFriends()->SetRichPresence("status", status.toLocal8Bit().data()); + SteamFriends()->SetRichPresence("connect", connectStr.toLocal8Bit().data()); +} diff --git a/libraries/steamworks-wrapper/src/steamworks-wrapper/SteamClient.h b/libraries/steamworks-wrapper/src/steamworks-wrapper/SteamClient.h index f7ca775829..9ce127f3cb 100644 --- a/libraries/steamworks-wrapper/src/steamworks-wrapper/SteamClient.h +++ b/libraries/steamworks-wrapper/src/steamworks-wrapper/SteamClient.h @@ -20,6 +20,8 @@ using Ticket = QByteArray; using TicketRequestCallback = std::function; +class QUrl; + class SteamClient { public: static bool isRunning(); @@ -30,6 +32,7 @@ public: static void runCallbacks(); static void requestTicket(TicketRequestCallback callback); + static void updateLocation(QString status, QUrl locationUrl); }; From 42c9a695ff5edd327329fa096879abb17765119e Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 27 Jul 2016 17:45:45 -0700 Subject: [PATCH 08/22] Invite friends in HMD --- interface/src/Application.cpp | 4 +++ .../src/steamworks-wrapper/SteamClient.cpp | 14 +++++++-- .../src/steamworks-wrapper/SteamClient.h | 16 +++++++++++ scripts/system/assets/images/tools/steam.jpeg | Bin 0 -> 979 bytes scripts/system/steam.js | 27 ++++++++++++++++++ 5 files changed, 58 insertions(+), 3 deletions(-) create mode 100644 scripts/system/assets/images/tools/steam.jpeg create mode 100644 scripts/system/steam.js diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 58284682f1..a1016d90fb 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1599,6 +1599,8 @@ void Application::initializeUi() { rootContext->setContextProperty("Reticle", getApplicationCompositor().getReticleInterface()); rootContext->setContextProperty("ApplicationCompositor", &getApplicationCompositor()); + + rootContext->setContextProperty("Steam", new SteamScriptingInterface(engine)); _glWidget->installEventFilter(offscreenUi.data()); @@ -4799,6 +4801,8 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri scriptEngine->registerGlobalObject("UserActivityLogger", DependencyManager::get().data()); scriptEngine->registerGlobalObject("Users", DependencyManager::get().data()); + + scriptEngine->registerGlobalObject("Steam", new SteamScriptingInterface(scriptEngine)); } bool Application::canAcceptURL(const QString& urlString) const { diff --git a/libraries/steamworks-wrapper/src/steamworks-wrapper/SteamClient.cpp b/libraries/steamworks-wrapper/src/steamworks-wrapper/SteamClient.cpp index f775efe2f6..ee6711e6f6 100644 --- a/libraries/steamworks-wrapper/src/steamworks-wrapper/SteamClient.cpp +++ b/libraries/steamworks-wrapper/src/steamworks-wrapper/SteamClient.cpp @@ -149,7 +149,7 @@ private: }; SteamCallbackManager::SteamCallbackManager() : -_gameRichPresenceJoinRequestedResponse(this, &SteamCallbackManager::onGameRichPresenceJoinRequested) + _gameRichPresenceJoinRequestedResponse(this, &SteamCallbackManager::onGameRichPresenceJoinRequested) { } @@ -161,7 +161,7 @@ void SteamCallbackManager::onGameRichPresenceJoinRequested(GameRichPresenceJoinR url.remove(-CONNECT_SUFFIX.size(), CONNECT_SUFFIX.size()); } - qDebug() << "Joining Steam Friends at:" << url; + qDebug() << "Joining Steam Friend at:" << url; auto mimeData = new QMimeData(); mimeData->setUrls(QList() << QUrl(url)); auto event = new QDropEvent(QPointF(0,0), Qt::MoveAction, mimeData, Qt::LeftButton, Qt::NoModifier); @@ -169,7 +169,6 @@ void SteamCallbackManager::onGameRichPresenceJoinRequested(GameRichPresenceJoinR QCoreApplication::postEvent(qApp, event); } - static std::atomic_bool initialized { false }; static SteamCallbackManager steamCallbackManager; @@ -239,3 +238,12 @@ void SteamClient::updateLocation(QString status, QUrl locationUrl) { SteamFriends()->SetRichPresence("status", status.toLocal8Bit().data()); SteamFriends()->SetRichPresence("connect", connectStr.toLocal8Bit().data()); } + +void SteamClient::openInviteOverlay() { + if (!initialized) { + return; + } + + qDebug() << "Inviting steam friends"; + SteamFriends()->ActivateGameOverlayInviteDialog(CSteamID()); +} diff --git a/libraries/steamworks-wrapper/src/steamworks-wrapper/SteamClient.h b/libraries/steamworks-wrapper/src/steamworks-wrapper/SteamClient.h index 9ce127f3cb..7c958c4b39 100644 --- a/libraries/steamworks-wrapper/src/steamworks-wrapper/SteamClient.h +++ b/libraries/steamworks-wrapper/src/steamworks-wrapper/SteamClient.h @@ -15,6 +15,7 @@ #include +#include #include using Ticket = QByteArray; @@ -33,6 +34,21 @@ public: static void requestTicket(TicketRequestCallback callback); static void updateLocation(QString status, QUrl locationUrl); + static void openInviteOverlay(); + +}; + +class SteamScriptingInterface : public QObject { + Q_OBJECT + + Q_PROPERTY(bool isRunning READ isRunning) + +public: + SteamScriptingInterface(QObject* parent) : QObject(parent) {} + +public slots: + bool isRunning() const { return SteamClient::isRunning(); } + void openInviteOverlay() const { SteamClient::openInviteOverlay(); } }; diff --git a/scripts/system/assets/images/tools/steam.jpeg b/scripts/system/assets/images/tools/steam.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..a39fdf9bc62c72467460026d639f13fc6910831c GIT binary patch literal 979 zcmex=o^zf-vy^0D~Y0gAs!fGoum%lOQ9rAmjfd4AKk?Ow5cRr@{dn3oAP_Bh&vQ z45k7MjLgi8EF3JXtPp8NCT11}RzV>)MZ-XLVG$+A#KK0S;7K1uohDv}biWfTeoY%~70>``pjeUEy0>($=!2;Y-a92A1ZY`BK`}T9%8N`dqFn?})C| zI`GWEwaDj~jO}#>yXw`>llf#%N#~yJYj>N#sLWC&XR@^DhSPGVwVMt&S|5H~JfR7`#um9y16f5)x(ibvX>(Na?nZq-m{`SqZ`D(I$!z#IMj z@>{-czVmqHrsf6peHA?)mH!1>f0lT2u591>6$h_g`(yF>+?!A_YwyCYt24jFMv1*y zGHtelWpH=EfdgMHmi{;e!m(3JJ0Q;4S>^Dg6ej(@dgylp#sORliY+bUGOf}6KR z<(KSpxkFP^@2bYWFc?i_THY?YUSd|p; z>^l@I+q!h6hL@cvLxD);@ZFFMj=1GxlF(C-BPYm>(a Date: Thu, 28 Jul 2016 16:54:17 -0700 Subject: [PATCH 09/22] Add steam.js to default scripts --- scripts/defaultScripts.js | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/defaultScripts.js b/scripts/defaultScripts.js index 0efcd0c140..46439541f1 100644 --- a/scripts/defaultScripts.js +++ b/scripts/defaultScripts.js @@ -9,6 +9,7 @@ // +Script.load("system/steam.js"); Script.load("system/progress.js"); Script.load("system/away.js"); Script.load("system/users.js"); From af76e47629751638fe9abfece4c1a1889c11cf02 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 28 Jul 2016 16:59:25 -0700 Subject: [PATCH 10/22] Fix linux build --- .../steamworks-wrapper/src/steamworks-wrapper/SteamClient.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/steamworks-wrapper/src/steamworks-wrapper/SteamClient.cpp b/libraries/steamworks-wrapper/src/steamworks-wrapper/SteamClient.cpp index ee6711e6f6..544868b2f7 100644 --- a/libraries/steamworks-wrapper/src/steamworks-wrapper/SteamClient.cpp +++ b/libraries/steamworks-wrapper/src/steamworks-wrapper/SteamClient.cpp @@ -18,7 +18,7 @@ #include #include #include -#include +#include #if defined(__GNUC__) && !defined(__clang__) #pragma GCC diagnostic push From 6b861e680f46f5bddae958b67b55045f1360660c Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Fri, 29 Jul 2016 11:46:21 -0700 Subject: [PATCH 11/22] More work on lobby creation/invites --- .../src/steamworks-wrapper/SteamClient.cpp | 51 +++++++++++++++++-- 1 file changed, 48 insertions(+), 3 deletions(-) diff --git a/libraries/steamworks-wrapper/src/steamworks-wrapper/SteamClient.cpp b/libraries/steamworks-wrapper/src/steamworks-wrapper/SteamClient.cpp index 544868b2f7..c28be7f344 100644 --- a/libraries/steamworks-wrapper/src/steamworks-wrapper/SteamClient.cpp +++ b/libraries/steamworks-wrapper/src/steamworks-wrapper/SteamClient.cpp @@ -142,6 +142,15 @@ public: STEAM_CALLBACK(SteamCallbackManager, onGameRichPresenceJoinRequested, GameRichPresenceJoinRequested_t, _gameRichPresenceJoinRequestedResponse); + STEAM_CALLBACK(SteamCallbackManager, onLobbyCreated, + LobbyCreated_t, _lobbyCreatedResponse); + + STEAM_CALLBACK(SteamCallbackManager, onGameLobbyJoinRequested, + GameLobbyJoinRequested_t, _gameLobbyJoinRequestedResponse); + + STEAM_CALLBACK(SteamCallbackManager, onLobbyEnter, + LobbyEnter_t, _lobbyEnterResponse); + SteamTicketRequests& getTicketRequests() { return _steamTicketRequests; } private: @@ -149,7 +158,10 @@ private: }; SteamCallbackManager::SteamCallbackManager() : - _gameRichPresenceJoinRequestedResponse(this, &SteamCallbackManager::onGameRichPresenceJoinRequested) + _gameRichPresenceJoinRequestedResponse(this, &SteamCallbackManager::onGameRichPresenceJoinRequested), + _lobbyCreatedResponse(this, &SteamCallbackManager::onLobbyCreated), + _gameLobbyJoinRequestedResponse(this, &SteamCallbackManager::onGameLobbyJoinRequested), + _lobbyEnterResponse(this, &SteamCallbackManager::onLobbyEnter) { } @@ -169,6 +181,38 @@ void SteamCallbackManager::onGameRichPresenceJoinRequested(GameRichPresenceJoinR QCoreApplication::postEvent(qApp, event); } +void SteamCallbackManager::onLobbyCreated(LobbyCreated_t* pCallback) { + qDebug() << pCallback->m_eResult << pCallback->m_ulSteamIDLobby; + if (pCallback->m_eResult == k_EResultOK) { + qDebug() << "Inviting steam friends"; + + SteamMatchmaking()->SetLobbyData(pCallback->m_ulSteamIDLobby, "connect", + SteamFriends()->GetFriendRichPresence(SteamUser()->GetSteamID(), "connect")); + SteamMatchmaking()->SetLobbyMemberData(pCallback->m_ulSteamIDLobby, + "Creator", "true"); + SteamFriends()->ActivateGameOverlayInviteDialog(pCallback->m_ulSteamIDLobby); + } +} + +void SteamCallbackManager::onGameLobbyJoinRequested(GameLobbyJoinRequested_t* pCallback) { + qDebug() << "onGameLobbyJoinRequested"; + SteamMatchmaking()->JoinLobby(pCallback->m_steamIDLobby); +} + +void SteamCallbackManager::onLobbyEnter(LobbyEnter_t* pCallback) { + qDebug() << "onLobbyEnter"; + auto creator = SteamMatchmaking()->GetLobbyMemberData(pCallback->m_ulSteamIDLobby, SteamUser()->GetSteamID(), "creator"); + if (strcmp(creator, "true") == 0) { + qDebug() << "Created lobby"; + SteamMatchmaking()->LeaveLobby(pCallback->m_ulSteamIDLobby); + } else if (pCallback->m_EChatRoomEnterResponse == k_EChatRoomEnterResponseSuccess) { + qDebug() << "Success"; + auto connectValue = SteamMatchmaking()->GetLobbyData(pCallback->m_ulSteamIDLobby, "connect"); + qDebug() << connectValue; + } +} + + static std::atomic_bool initialized { false }; static SteamCallbackManager steamCallbackManager; @@ -244,6 +288,7 @@ void SteamClient::openInviteOverlay() { return; } - qDebug() << "Inviting steam friends"; - SteamFriends()->ActivateGameOverlayInviteDialog(CSteamID()); + qDebug() << "Creating steam lobby"; + static const int MAX_LOBBY_SIZE = 20; + SteamMatchmaking()->CreateLobby(k_ELobbyTypePrivate, MAX_LOBBY_SIZE); } From 7ec2f98cf2a081e8073ca5d682c34d82d90e3997 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Fri, 29 Jul 2016 13:34:10 -0700 Subject: [PATCH 12/22] Join lobby on startup --- interface/src/Application.cpp | 8 +++ .../src/steamworks-wrapper/SteamClient.cpp | 54 +++++++++++-------- .../src/steamworks-wrapper/SteamClient.h | 1 + 3 files changed, 42 insertions(+), 21 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index a1016d90fb..00a092f8c7 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3224,6 +3224,14 @@ void Application::init() { addressLookupString = arguments().value(urlIndex + 1); } + // when +connect_lobby in command line, join steam lobby + const QString STEAM_LOBBY_COMMAND_LINE_KEY = "+connect_lobby"; + int lobbyIndex = arguments().indexOf(STEAM_LOBBY_COMMAND_LINE_KEY); + if (lobbyIndex != -1) { + QString lobbyId = arguments().value(lobbyIndex + 1); + SteamClient::joinLobby(lobbyId); + } + Setting::Handle firstRun { Settings::firstRun, true }; if (addressLookupString.isEmpty() && firstRun.get()) { qDebug() << "First run and no URL passed... attempting to go to Home or Entry..."; diff --git a/libraries/steamworks-wrapper/src/steamworks-wrapper/SteamClient.cpp b/libraries/steamworks-wrapper/src/steamworks-wrapper/SteamClient.cpp index c28be7f344..3efeba956a 100644 --- a/libraries/steamworks-wrapper/src/steamworks-wrapper/SteamClient.cpp +++ b/libraries/steamworks-wrapper/src/steamworks-wrapper/SteamClient.cpp @@ -165,9 +165,7 @@ SteamCallbackManager::SteamCallbackManager() : { } -void SteamCallbackManager::onGameRichPresenceJoinRequested(GameRichPresenceJoinRequested_t* pCallback) { - auto url = QString::fromLocal8Bit(pCallback->m_rgchConnect); - +void parseUrlAndGo(QString url) { if (url.startsWith(CONNECT_PREFIX) && url.endsWith(CONNECT_SUFFIX)) { url.remove(0, CONNECT_PREFIX.size()); url.remove(-CONNECT_SUFFIX.size(), CONNECT_SUFFIX.size()); @@ -176,40 +174,50 @@ void SteamCallbackManager::onGameRichPresenceJoinRequested(GameRichPresenceJoinR qDebug() << "Joining Steam Friend at:" << url; auto mimeData = new QMimeData(); mimeData->setUrls(QList() << QUrl(url)); - auto event = new QDropEvent(QPointF(0,0), Qt::MoveAction, mimeData, Qt::LeftButton, Qt::NoModifier); + auto event = new QDropEvent(QPointF(0, 0), Qt::MoveAction, mimeData, Qt::LeftButton, Qt::NoModifier); QCoreApplication::postEvent(qApp, event); } +void SteamCallbackManager::onGameRichPresenceJoinRequested(GameRichPresenceJoinRequested_t* pCallback) { + auto url = QString::fromLocal8Bit(pCallback->m_rgchConnect); + + parseUrlAndGo(url); +} + + + void SteamCallbackManager::onLobbyCreated(LobbyCreated_t* pCallback) { qDebug() << pCallback->m_eResult << pCallback->m_ulSteamIDLobby; if (pCallback->m_eResult == k_EResultOK) { qDebug() << "Inviting steam friends"; - SteamMatchmaking()->SetLobbyData(pCallback->m_ulSteamIDLobby, "connect", - SteamFriends()->GetFriendRichPresence(SteamUser()->GetSteamID(), "connect")); - SteamMatchmaking()->SetLobbyMemberData(pCallback->m_ulSteamIDLobby, - "Creator", "true"); + auto url = SteamFriends()->GetFriendRichPresence(SteamUser()->GetSteamID(), "connect"); + SteamMatchmaking()->SetLobbyData(pCallback->m_ulSteamIDLobby, "connect", url); + SteamMatchmaking()->SetLobbyMemberData(pCallback->m_ulSteamIDLobby, "creator", "true"); SteamFriends()->ActivateGameOverlayInviteDialog(pCallback->m_ulSteamIDLobby); } } void SteamCallbackManager::onGameLobbyJoinRequested(GameLobbyJoinRequested_t* pCallback) { - qDebug() << "onGameLobbyJoinRequested"; + qDebug() << "Joining Steam lobby"; SteamMatchmaking()->JoinLobby(pCallback->m_steamIDLobby); } void SteamCallbackManager::onLobbyEnter(LobbyEnter_t* pCallback) { - qDebug() << "onLobbyEnter"; - auto creator = SteamMatchmaking()->GetLobbyMemberData(pCallback->m_ulSteamIDLobby, SteamUser()->GetSteamID(), "creator"); - if (strcmp(creator, "true") == 0) { - qDebug() << "Created lobby"; - SteamMatchmaking()->LeaveLobby(pCallback->m_ulSteamIDLobby); - } else if (pCallback->m_EChatRoomEnterResponse == k_EChatRoomEnterResponseSuccess) { - qDebug() << "Success"; - auto connectValue = SteamMatchmaking()->GetLobbyData(pCallback->m_ulSteamIDLobby, "connect"); - qDebug() << connectValue; + if (pCallback->m_EChatRoomEnterResponse != k_EChatRoomEnterResponseSuccess) { + qWarning() << "An error occured while joing the Steam lobby:" << pCallback->m_EChatRoomEnterResponse; + return; } + + auto creator = SteamMatchmaking()->GetLobbyMemberData(pCallback->m_ulSteamIDLobby, + SteamUser()->GetSteamID(), "creator"); + if (strcmp(creator, "true") != 0) { + auto url = SteamMatchmaking()->GetLobbyData(pCallback->m_ulSteamIDLobby, "connect"); + parseUrlAndGo(url); + } + + SteamMatchmaking()->LeaveLobby(pCallback->m_ulSteamIDLobby); } @@ -218,9 +226,6 @@ static SteamCallbackManager steamCallbackManager; bool SteamClient::isRunning() { - if (!initialized) { - init(); - } return initialized; } @@ -292,3 +297,10 @@ void SteamClient::openInviteOverlay() { static const int MAX_LOBBY_SIZE = 20; SteamMatchmaking()->CreateLobby(k_ELobbyTypePrivate, MAX_LOBBY_SIZE); } + + +void SteamClient::joinLobby(QString lobbyIdStr) { + qDebug() << "Trying to join Steam lobby:" << lobbyIdStr; + CSteamID lobbyId(lobbyIdStr.toULongLong()); + SteamMatchmaking()->JoinLobby(lobbyId); +} \ No newline at end of file diff --git a/libraries/steamworks-wrapper/src/steamworks-wrapper/SteamClient.h b/libraries/steamworks-wrapper/src/steamworks-wrapper/SteamClient.h index 7c958c4b39..5bf0d4db56 100644 --- a/libraries/steamworks-wrapper/src/steamworks-wrapper/SteamClient.h +++ b/libraries/steamworks-wrapper/src/steamworks-wrapper/SteamClient.h @@ -35,6 +35,7 @@ public: static void requestTicket(TicketRequestCallback callback); static void updateLocation(QString status, QUrl locationUrl); static void openInviteOverlay(); + static void joinLobby(QString lobbyId); }; From 2af32ca60ed54c78df0771aeeb15d9f7c6cdb077 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Fri, 29 Jul 2016 13:55:39 -0700 Subject: [PATCH 13/22] Only leave lobby if you were invited --- .../src/steamworks-wrapper/SteamClient.cpp | 32 ++++++++++++------- 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/libraries/steamworks-wrapper/src/steamworks-wrapper/SteamClient.cpp b/libraries/steamworks-wrapper/src/steamworks-wrapper/SteamClient.cpp index 3efeba956a..f6cf13effd 100644 --- a/libraries/steamworks-wrapper/src/steamworks-wrapper/SteamClient.cpp +++ b/libraries/steamworks-wrapper/src/steamworks-wrapper/SteamClient.cpp @@ -188,19 +188,17 @@ void SteamCallbackManager::onGameRichPresenceJoinRequested(GameRichPresenceJoinR void SteamCallbackManager::onLobbyCreated(LobbyCreated_t* pCallback) { - qDebug() << pCallback->m_eResult << pCallback->m_ulSteamIDLobby; if (pCallback->m_eResult == k_EResultOK) { - qDebug() << "Inviting steam friends"; + qDebug() << "Inviting steam friends" << pCallback->m_ulSteamIDLobby; auto url = SteamFriends()->GetFriendRichPresence(SteamUser()->GetSteamID(), "connect"); SteamMatchmaking()->SetLobbyData(pCallback->m_ulSteamIDLobby, "connect", url); - SteamMatchmaking()->SetLobbyMemberData(pCallback->m_ulSteamIDLobby, "creator", "true"); SteamFriends()->ActivateGameOverlayInviteDialog(pCallback->m_ulSteamIDLobby); } } void SteamCallbackManager::onGameLobbyJoinRequested(GameLobbyJoinRequested_t* pCallback) { - qDebug() << "Joining Steam lobby"; + qDebug() << "Joining Steam lobby" << pCallback->m_steamIDLobby.ConvertToUint64(); SteamMatchmaking()->JoinLobby(pCallback->m_steamIDLobby); } @@ -210,14 +208,14 @@ void SteamCallbackManager::onLobbyEnter(LobbyEnter_t* pCallback) { return; } - auto creator = SteamMatchmaking()->GetLobbyMemberData(pCallback->m_ulSteamIDLobby, - SteamUser()->GetSteamID(), "creator"); - if (strcmp(creator, "true") != 0) { - auto url = SteamMatchmaking()->GetLobbyData(pCallback->m_ulSteamIDLobby, "connect"); - parseUrlAndGo(url); - } + qDebug() << "Entered Steam lobby" << pCallback->m_ulSteamIDLobby; - SteamMatchmaking()->LeaveLobby(pCallback->m_ulSteamIDLobby); + if (SteamMatchmaking()->GetLobbyOwner(pCallback->m_ulSteamIDLobby) != SteamUser()->GetSteamID()) { + auto url = SteamMatchmaking()->GetLobbyData(pCallback->m_ulSteamIDLobby, "connect"); + qDebug() << "Jumping to" << url; + parseUrlAndGo(url); + SteamMatchmaking()->LeaveLobby(pCallback->m_ulSteamIDLobby); + } } @@ -293,13 +291,23 @@ void SteamClient::openInviteOverlay() { return; } - qDebug() << "Creating steam lobby"; + qDebug() << "Creating Steam lobby"; static const int MAX_LOBBY_SIZE = 20; SteamMatchmaking()->CreateLobby(k_ELobbyTypePrivate, MAX_LOBBY_SIZE); } void SteamClient::joinLobby(QString lobbyIdStr) { + if (!initialized) { + if (SteamAPI_IsSteamRunning()) { + init(); + } + else { + qWarning() << "Steam is not running"; + return; + } + } + qDebug() << "Trying to join Steam lobby:" << lobbyIdStr; CSteamID lobbyId(lobbyIdStr.toULongLong()); SteamMatchmaking()->JoinLobby(lobbyId); From aa2ae31aab3b5b9b6fe4b9359f40ee5e3efa9600 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Fri, 29 Jul 2016 19:30:20 -0700 Subject: [PATCH 14/22] CR UI fixes --- .../qml/LoginDialog/CompleteProfileBody.qml | 15 +- .../qml/LoginDialog/EmailSentBody.qml | 83 ----------- .../qml/LoginDialog/LinkAccountBody.qml | 51 ++----- .../qml/LoginDialog/RecoverPasswordBody.qml | 140 ------------------ .../qml/LoginDialog/UsernameCollisionBody.qml | 30 +++- interface/src/ui/LoginDialog.cpp | 4 +- .../networking/src/NetworkingConstants.h | 2 +- 7 files changed, 50 insertions(+), 275 deletions(-) delete mode 100644 interface/resources/qml/LoginDialog/EmailSentBody.qml delete mode 100644 interface/resources/qml/LoginDialog/RecoverPasswordBody.qml diff --git a/interface/resources/qml/LoginDialog/CompleteProfileBody.qml b/interface/resources/qml/LoginDialog/CompleteProfileBody.qml index 12d2cee73e..fc7eac3d00 100644 --- a/interface/resources/qml/LoginDialog/CompleteProfileBody.qml +++ b/interface/resources/qml/LoginDialog/CompleteProfileBody.qml @@ -77,22 +77,17 @@ Item { topMargin: hifi.dimensions.contentSpacing.y } - text: "Already have a High Fidelity profile? Link to an existing profile here." + text: "Already have a High Fidelity profile? Link to an existing profile here." - font.underline: true wrapMode: Text.WordWrap - color: hifi.colors.blueAccent lineHeight: 2 lineHeightMode: Text.ProportionalHeight horizontalAlignment: Text.AlignHCenter - MouseArea { - anchors.fill: parent - onClicked: { - bodyLoader.source = "LinkAccountBody.qml" - bodyLoader.item.width = root.pane.width - bodyLoader.item.height = root.pane.height - } + onLinkActivated: { + bodyLoader.source = "LinkAccountBody.qml" + bodyLoader.item.width = root.pane.width + bodyLoader.item.height = root.pane.height } } diff --git a/interface/resources/qml/LoginDialog/EmailSentBody.qml b/interface/resources/qml/LoginDialog/EmailSentBody.qml deleted file mode 100644 index 489385864b..0000000000 --- a/interface/resources/qml/LoginDialog/EmailSentBody.qml +++ /dev/null @@ -1,83 +0,0 @@ -// -// EmailSentBody.qml -// -// Created by Clement on 7/18/16 -// Copyright 2015 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 -// - -import Hifi 1.0 -import QtQuick 2.4 - -import "../controls-uit" -import "../styles-uit" - -Item { - id: emailSentBody - clip: true - width: root.pane.width - height: root.pane.height - - property string email: "" - - QtObject { - id: d - readonly property int minWidth: 480 - readonly property int maxWidth: 1280 - readonly property int minHeight: 120 - readonly property int maxHeight: 720 - - function resize() { - var targetWidth = Math.max(titleWidth, mainTextContainer.contentWidth) - var targetHeight = mainTextContainer.height + 3 * hifi.dimensions.contentSpacing.y + buttons.height - - root.width = Math.max(d.minWidth, Math.min(d.maxWidth, targetWidth)) - root.height = Math.max(d.minHeight, Math.min(d.maxHeight, targetHeight)) - } - } - - MenuItem { - id: mainTextContainer - anchors { - top: parent.top - horizontalCenter: parent.horizontalCenter - margins: 0 - topMargin: hifi.dimensions.contentSpacing.y - } - - text: qsTr("An email with instructions on reseting your password was sent to
") + email + "" - wrapMode: Text.WordWrap - color: hifi.colors.baseGrayHighlight - lineHeight: 2 - lineHeightMode: Text.ProportionalHeight - horizontalAlignment: Text.AlignHCenter - } - - Row { - id: buttons - anchors { - top: mainTextContainer.bottom - horizontalCenter: parent.horizontalCenter - margins: 0 - topMargin: 2 * hifi.dimensions.contentSpacing.y - } - spacing: hifi.dimensions.contentSpacing.x - onHeightChanged: d.resize(); onWidthChanged: d.resize(); - - Button { - anchors.verticalCenter: parent.verticalCenter - - text: qsTr("Close"); - - onClicked: root.destroy() - } - } - - Component.onCompleted: { - root.title = qsTr("Email Sent") - root.iconText = "" - d.resize(); - } -} diff --git a/interface/resources/qml/LoginDialog/LinkAccountBody.qml b/interface/resources/qml/LoginDialog/LinkAccountBody.qml index da5f0f1a42..137556964f 100644 --- a/interface/resources/qml/LoginDialog/LinkAccountBody.qml +++ b/interface/resources/qml/LoginDialog/LinkAccountBody.qml @@ -22,9 +22,8 @@ Item { width: root.pane.width height: root.pane.height - property bool existingEmail: false - function login() { + mainTextContainer.visible = false loginDialog.login(usernameField.text, passwordField.text) } @@ -36,8 +35,8 @@ Item { readonly property int maxHeight: 720 function resize() { - var targetWidth = Math.max(titleWidth, mainTextContainer.visible ? mainTextContainer.contentWidth : 0) - var targetHeight = (mainTextContainer.visible ? mainTextContainer.height : 0) + + var targetWidth = Math.max(titleWidth, form.contentWidth) + var targetHeight = hifi.dimensions.contentSpacing.y + mainTextContainer.height + 4 * hifi.dimensions.contentSpacing.y + form.height + 4 * hifi.dimensions.contentSpacing.y + buttons.height @@ -46,29 +45,29 @@ Item { } } - MenuItem { + ShortcutText { id: mainTextContainer anchors { top: parent.top - horizontalCenter: parent.horizontalCenter + left: parent.left margins: 0 topMargin: hifi.dimensions.contentSpacing.y } - visible: existingEmail - text: qsTr("Your Steam account's email matches an existing High Fidelity Profile") + visible: false + + text: qsTr("Username or password incorrect.") wrapMode: Text.WordWrap color: hifi.colors.redAccent - lineHeight: 2 + lineHeight: 1 lineHeightMode: Text.ProportionalHeight horizontalAlignment: Text.AlignHCenter } - Column { id: form anchors { - top: mainTextContainer.visible ? mainTextContainer.bottom : parent.top + top: mainTextContainer.bottom left: parent.left margins: 0 topMargin: 2 * hifi.dimensions.contentSpacing.y @@ -93,22 +92,12 @@ Item { verticalCenter: parent.verticalCenter } - text: "Need help?" - - color: hifi.colors.blueAccent - font.underline: true + text: "Forgot Username?" verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignHCenter - MouseArea { - anchors.fill: parent - onClicked: { - bodyLoader.source = "RecoverPasswordBody.qml" - bodyLoader.item.width = root.pane.width - bodyLoader.item.height = root.pane.height - } - } + onLinkActivated: loginDialog.openUrl(link) } } Row { @@ -130,22 +119,12 @@ Item { verticalCenter: parent.verticalCenter } - text: "Need help?" - - color: hifi.colors.blueAccent - font.underline: true + text: "Forgot Password?" verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignHCenter - MouseArea { - anchors.fill: parent - onClicked: { - bodyLoader.source = "RecoverPasswordBody.qml" - bodyLoader.item.width = root.pane.width - bodyLoader.item.height = root.pane.height - } - } + onLinkActivated: loginDialog.openUrl(link) } } @@ -205,7 +184,7 @@ Item { } onHandleLoginFailed: { console.log("Login Failed") - + mainTextContainer.visible = true } onHandleLinkCompleted: { console.log("Link Succeeded") diff --git a/interface/resources/qml/LoginDialog/RecoverPasswordBody.qml b/interface/resources/qml/LoginDialog/RecoverPasswordBody.qml deleted file mode 100644 index 3c6e101e2a..0000000000 --- a/interface/resources/qml/LoginDialog/RecoverPasswordBody.qml +++ /dev/null @@ -1,140 +0,0 @@ -// -// RecoverPasswordBody.qml -// -// Created by Clement on 7/18/16 -// Copyright 2015 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 -// - -import Hifi 1.0 -import QtQuick 2.4 -import QtQuick.Controls 1.4 -import QtQuick.Controls.Styles 1.4 as OriginalStyles - -import "../controls-uit" -import "../styles-uit" - -Item { - id: recoverPasswordBody - clip: true - width: root.pane.width - height: root.pane.height - - function send() { - loginDialog.sendRecoveryEmail(emailField.text) - - bodyLoader.setSource("EmailSentBody.qml", { "email": emailField.text }) - bodyLoader.item.width = root.pane.width - bodyLoader.item.height = root.pane.height - } - - QtObject { - id: d - readonly property int minWidth: 480 - readonly property int maxWidth: 1280 - readonly property int minHeight: 120 - readonly property int maxHeight: 720 - - function resize() { - var targetWidth = Math.max(titleWidth, mainTextContainer.contentWidth) - var targetHeight = mainTextContainer.height + - 3 * hifi.dimensions.contentSpacing.y + emailField.height + - 4 * hifi.dimensions.contentSpacing.y + buttons.height - - root.width = Math.max(d.minWidth, Math.min(d.maxWidth, targetWidth)) - root.height = Math.max(d.minHeight, Math.min(d.maxHeight, targetHeight)) - } - } - - MenuItem { - id: mainTextContainer - anchors { - top: parent.top - left: parent.left - right: parent.right - margins: 0 - topMargin: hifi.dimensions.contentSpacing.y - } - - text: qsTr("In order to help you reset your password, we will send an
email with instructions to your email address.") - wrapMode: Text.WordWrap - color: hifi.colors.baseGrayHighlight - lineHeight: 1 - horizontalAlignment: Text.AlignHLeft - } - - - TextField { - id: emailField - anchors { - top: mainTextContainer.bottom - left: parent.left - margins: 0 - topMargin: 2 * hifi.dimensions.contentSpacing.y - } - - width: 350 - - label: "Email address" - - Component.onCompleted: { - emailField.forceActiveFocus() - } - } - - Row { - id: buttons - anchors { - top: emailField.bottom - right: parent.right - margins: 0 - topMargin: 3 * hifi.dimensions.contentSpacing.y - } - spacing: hifi.dimensions.contentSpacing.x - onHeightChanged: d.resize(); onWidthChanged: d.resize(); - - Button { - anchors.verticalCenter: parent.verticalCenter - width: 200 - - text: qsTr("Send recovery email") - color: hifi.buttons.blue - - onClicked: recoverPasswordBody.send() - } - - Button { - anchors.verticalCenter: parent.verticalCenter - - text: qsTr("Back") - - onClicked: { - bodyLoader.source = "LinkAccountBody.qml" - bodyLoader.item.width = root.pane.width - bodyLoader.item.height = root.pane.height - } - } - } - - Component.onCompleted: { - root.title = qsTr("Recover Password") - root.iconText = "<" - d.resize(); - } - - Keys.onPressed: { - if (!visible) { - return - } - - switch (event.key) { - case Qt.Key_Enter: - case Qt.Key_Return: - event.accepted = true - recoverPasswordBody.send() - break - } - } -} diff --git a/interface/resources/qml/LoginDialog/UsernameCollisionBody.qml b/interface/resources/qml/LoginDialog/UsernameCollisionBody.qml index f0663631a8..7e22b11f8b 100644 --- a/interface/resources/qml/LoginDialog/UsernameCollisionBody.qml +++ b/interface/resources/qml/LoginDialog/UsernameCollisionBody.qml @@ -22,6 +22,11 @@ Item { width: root.pane.width height: root.pane.height + function create() { + mainTextContainer.visible = false + loginDialog.createAccountFromStream(textField.text) + } + QtObject { id: d readonly property int minWidth: 480 @@ -82,12 +87,14 @@ Item { topMargin: 3 * hifi.dimensions.contentSpacing.y } - text: qsTr("By creating this user profile, you agree to High Fidelity's Terms of Service") + text: qsTr("By creating this user profile, you agree to High Fidelity's Terms of Service") wrapMode: Text.WordWrap color: hifi.colors.baseGrayHighlight lineHeight: 1 lineHeightMode: Text.ProportionalHeight horizontalAlignment: Text.AlignHCenter + + onLinkActivated: loginDialog.openUrl(link) } Row { @@ -108,9 +115,7 @@ Item { text: qsTr("Create your profile") color: hifi.buttons.blue - onClicked: { - loginDialog.createAccountFromStream(textField.text) - } + onClicked: usernameCollisionBody.create() } Button { @@ -136,6 +141,9 @@ Item { } onHandleCreateFailed: { console.log("Create Failed: " + error) + + mainTextContainer.visible = true + mainTextContainer.text = "\"" + textField.text + qsTr("\" is invalid or already taken.") } onHandleLoginCompleted: { console.log("Login Succeeded") @@ -148,4 +156,18 @@ Item { console.log("Login Failed") } } + + Keys.onPressed: { + if (!visible) { + return + } + + switch (event.key) { + case Qt.Key_Enter: + case Qt.Key_Return: + event.accepted = true + usernameCollisionBody.create() + break + } + } } diff --git a/interface/src/ui/LoginDialog.cpp b/interface/src/ui/LoginDialog.cpp index b65e111b16..78aacb1216 100644 --- a/interface/src/ui/LoginDialog.cpp +++ b/interface/src/ui/LoginDialog.cpp @@ -132,7 +132,9 @@ void LoginDialog::createAccountFromStream(QString username) { } void LoginDialog::openUrl(const QString& url) { - QDesktopServices::openUrl(url); + auto offscreenUi = DependencyManager::get(); + auto browser = offscreenUi->load("Browser.qml"); + browser->setProperty("url", url); } void LoginDialog::sendRecoveryEmail(const QString& email) { diff --git a/libraries/networking/src/NetworkingConstants.h b/libraries/networking/src/NetworkingConstants.h index 154470201f..bbbaa5ebbe 100644 --- a/libraries/networking/src/NetworkingConstants.h +++ b/libraries/networking/src/NetworkingConstants.h @@ -15,7 +15,7 @@ #include namespace NetworkingConstants { - const QUrl METAVERSE_SERVER_URL = QUrl("https://hifi.ngrok.io"); + const QUrl METAVERSE_SERVER_URL = QUrl("http://10.0.0.146:8080"); } #endif // hifi_NetworkingConstants_h From 51b45f8f73e58408b78d72ed3cea03016d3bfe6b Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 3 Aug 2016 16:04:48 -0700 Subject: [PATCH 15/22] Steam invite are facing the current position --- interface/src/DiscoverabilityManager.cpp | 2 +- interface/src/avatar/MyAvatar.cpp | 12 ++++--- libraries/networking/src/AddressManager.cpp | 39 +++++++++++++++++++-- libraries/networking/src/AddressManager.h | 6 ++-- 4 files changed, 49 insertions(+), 10 deletions(-) diff --git a/interface/src/DiscoverabilityManager.cpp b/interface/src/DiscoverabilityManager.cpp index 3b7d544394..dd80dadca7 100644 --- a/interface/src/DiscoverabilityManager.cpp +++ b/interface/src/DiscoverabilityManager.cpp @@ -111,7 +111,7 @@ void DiscoverabilityManager::updateLocation() { } // Update Steam - SteamClient::updateLocation(domainHandler.getHostname(), addressManager->currentAddress()); + SteamClient::updateLocation(domainHandler.getHostname(), addressManager->currentFacingAddress()); } void DiscoverabilityManager::handleHeartbeatResponse(QNetworkReply& requestReply) { diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index de5455fc14..57e379a9ac 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -122,11 +122,13 @@ MyAvatar::MyAvatar(RigPointer rig) : _driveKeys[i] = 0.0f; } + + // Necessary to select the correct slot + using SlotType = void(MyAvatar::*)(const glm::vec3&, bool, const glm::quat&, bool); + // connect to AddressManager signal for location jumps - connect(DependencyManager::get().data(), &AddressManager::locationChangeRequired, - [=](const glm::vec3& newPosition, bool hasOrientation, const glm::quat& newOrientation, bool shouldFaceLocation){ - goToLocation(newPosition, hasOrientation, newOrientation, shouldFaceLocation); - }); + connect(DependencyManager::get().data(), &AddressManager::locationChangeRequired, + this, static_cast(&MyAvatar::goToLocation)); _characterController.setEnabled(true); @@ -1859,7 +1861,7 @@ void MyAvatar::goToLocation(const glm::vec3& newPosition, glm::quat quatOrientation = cancelOutRollAndPitch(newOrientation); if (shouldFaceLocation) { - quatOrientation = newOrientation * glm::angleAxis(PI, glm::vec3(0.0f, 1.0f, 0.0f)); + quatOrientation = newOrientation * glm::angleAxis(PI, Vectors::UP); // move the user a couple units away const float DISTANCE_TO_USER = 2.0f; diff --git a/libraries/networking/src/AddressManager.cpp b/libraries/networking/src/AddressManager.cpp index ae6aad3c4f..6760d44244 100644 --- a/libraries/networking/src/AddressManager.cpp +++ b/libraries/networking/src/AddressManager.cpp @@ -17,6 +17,7 @@ #include #include +#include #include #include @@ -46,7 +47,7 @@ bool AddressManager::isConnected() { return DependencyManager::get()->getDomainHandler().isConnected(); } -const QUrl AddressManager::currentAddress() const { +QUrl AddressManager::currentAddress() const { QUrl hifiURL; hifiURL.setScheme(HIFI_URL_SCHEME); @@ -61,6 +62,21 @@ const QUrl AddressManager::currentAddress() const { return hifiURL; } +QUrl AddressManager::currentFacingAddress() const { + QUrl hifiURL; + + hifiURL.setScheme(HIFI_URL_SCHEME); + hifiURL.setHost(_host); + + if (_port != 0 && _port != DEFAULT_DOMAIN_SERVER_PORT) { + hifiURL.setPort(_port); + } + + hifiURL.setPath(currentFacingPath()); + + return hifiURL; +} + void AddressManager::loadSettings(const QString& lookupString) { if (lookupString.isEmpty()) { handleUrl(currentAddressHandle.get().toString(), LookupTrigger::StartupFromSettings); @@ -97,7 +113,7 @@ void AddressManager::storeCurrentAddress() { currentAddressHandle.set(currentAddress()); } -const QString AddressManager::currentPath(bool withOrientation) const { +QString AddressManager::currentPath(bool withOrientation) const { if (_positionGetter) { QString pathString = "/" + createByteArray(_positionGetter()); @@ -121,6 +137,25 @@ const QString AddressManager::currentPath(bool withOrientation) const { } } +QString AddressManager::currentFacingPath() const { + if (_positionGetter && _orientationGetter) { + auto position = _positionGetter(); + auto orientation = _orientationGetter(); + + // move the user a couple units away + const float DISTANCE_TO_USER = 2.0f; + position += orientation * Vectors::FRONT * DISTANCE_TO_USER; + + // rotate the user by 180 degrees + orientation = orientation * glm::angleAxis(PI, Vectors::UP); + + return "/" + createByteArray(position) + "/" + createByteArray(orientation); + } else { + qCDebug(networking) << "Cannot create address path without a getter for position/orientation."; + return QString(); + } +} + const JSONCallbackParameters& AddressManager::apiCallbackParameters() { static bool hasSetupParameters = false; static JSONCallbackParameters callbackParams; diff --git a/libraries/networking/src/AddressManager.h b/libraries/networking/src/AddressManager.h index 2e9f177137..8ccddc5975 100644 --- a/libraries/networking/src/AddressManager.h +++ b/libraries/networking/src/AddressManager.h @@ -57,8 +57,10 @@ public: bool isConnected(); const QString& getProtocol() { return HIFI_URL_SCHEME; }; - const QUrl currentAddress() const; - const QString currentPath(bool withOrientation = true) const; + QUrl currentAddress() const; + QUrl currentFacingAddress() const; + QString currentPath(bool withOrientation = true) const; + QString currentFacingPath() const; const QUuid& getRootPlaceID() const { return _rootPlaceID; } const QString& getPlaceName() const { return _placeName; } From 61d07cf952c1ab2224d68c390825156e0ae1a362 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Fri, 5 Aug 2016 13:08:18 -0700 Subject: [PATCH 16/22] Restore mateverse URL --- libraries/networking/src/NetworkingConstants.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/networking/src/NetworkingConstants.h b/libraries/networking/src/NetworkingConstants.h index bbbaa5ebbe..a512ae8887 100644 --- a/libraries/networking/src/NetworkingConstants.h +++ b/libraries/networking/src/NetworkingConstants.h @@ -15,7 +15,7 @@ #include namespace NetworkingConstants { - const QUrl METAVERSE_SERVER_URL = QUrl("http://10.0.0.146:8080"); + const QUrl METAVERSE_SERVER_URL = QUrl("https://metaverse.highfidelity.com"); } #endif // hifi_NetworkingConstants_h From f08b2f9257f834380ca73c9fcbeacf5882b2cb36 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 8 Aug 2016 15:39:44 -0700 Subject: [PATCH 17/22] Remove temporary override to reload QML --- interface/src/Application.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 00a092f8c7..ac024f89c3 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2244,12 +2244,11 @@ void Application::keyPressEvent(QKeyEvent* event) { break; case Qt::Key_X: - if (isMeta) { + if (isShifted && isMeta) { auto offscreenUi = DependencyManager::get(); -// offscreenUi->togglePinned(); - offscreenUi->getRootContext()->engine()->clearComponentCache(); - qDebug() << "Component cache cleared"; -// OffscreenUi::information("Debugging", "Component cache cleared"); + offscreenUi->togglePinned(); + //offscreenUi->getRootContext()->engine()->clearComponentCache(); + //OffscreenUi::information("Debugging", "Component cache cleared"); // placeholder for dialogs being converted to QML. } break; From 25b60d0c62026d5fcf8f97f33f76ca40aaa7302a Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 9 Aug 2016 09:46:58 -0700 Subject: [PATCH 18/22] CR feedback --- interface/resources/qml/LoginDialogSave.qml | 197 ------------------ interface/src/ui/LoginDialog.cpp | 19 +- interface/src/ui/LoginDialog.h | 7 +- .../src/steamworks-wrapper/SteamClient.cpp | 3 +- 4 files changed, 7 insertions(+), 219 deletions(-) delete mode 100644 interface/resources/qml/LoginDialogSave.qml diff --git a/interface/resources/qml/LoginDialogSave.qml b/interface/resources/qml/LoginDialogSave.qml deleted file mode 100644 index 46246fc1a5..0000000000 --- a/interface/resources/qml/LoginDialogSave.qml +++ /dev/null @@ -1,197 +0,0 @@ -Window { - id: root - HifiConstants { id: hifi } - - width: 550 - height: 200 - - anchors.centerIn: parent - resizable: true - - property bool required: false - - Component { - id: welcomeBody - - Column { - anchors.centerIn: parent - - OverlayTitle { - anchors.horizontalCenter: parent.horizontalCenter - - text: "Welcomeback Atlante45!" - color: hifi.colors.baseGrayHighlight - verticalAlignment: Text.AlignVCenter - horizontalAlignment: Text.AlignHCenter - } - - VerticalSpacer {} - - HorizontalRule {} - - MenuItem { - id: details - anchors.horizontalCenter: parent.horizontalCenter - - text: "You are now signed into High Fidelity" - color: hifi.colors.baseGrayHighlight - verticalAlignment: Text.AlignVCenter - horizontalAlignment: Text.AlignHCenter - } - - VerticalSpacer {} - - Button { - anchors.horizontalCenter: parent.horizontalCenter - - text: "Close" - } - } - } - - Component { - id: signInBody - - Column { - anchors.centerIn: parent - - OverlayTitle { - anchors.horizontalCenter: parent.horizontalCenter - - text: required ? "Sign In Required" : "Sign In" - color: hifi.colors.baseGrayHighlight - verticalAlignment: Text.AlignVCenter - horizontalAlignment: Text.AlignHCenter - } - - VerticalSpacer {} - - HorizontalRule {} - - MenuItem { - id: details - anchors.horizontalCenter: parent.horizontalCenter - - text: required ? "This domain's owner requires that you sign in:" - : "Sign in to access your user account:" - color: hifi.colors.baseGrayHighlight - verticalAlignment: Text.AlignVCenter - horizontalAlignment: Text.AlignHCenter - } - - VerticalSpacer {} - - Row { - anchors.horizontalCenter: parent.horizontalCenter - - Button { - anchors.verticalCenter: parent.verticalCenter - width: undefined // invalidate so that the image's size sets the width - height: undefined // invalidate so that the image's size sets the height - - style: Original.ButtonStyle { - background: Image { - id: buttonImage - source: "../images/steam-sign-in.png" - } - } - - onClicked: body.sourceComponent = completeProfileBody - } - - HorizontalSpacer {} - - Button { - anchors.verticalCenter: parent.verticalCenter - - text: "Cancel" - - onClicked: required = !required - } - } - } - } - - Component { - id: completeProfileBody - - Column { - anchors.centerIn: parent - - Row { - anchors.horizontalCenter: parent.horizontalCenter - - HiFiGlyphs { - anchors.verticalCenter: parent.verticalCenter - - text: hifi.glyphs.avatar - } - - OverlayTitle { - anchors.verticalCenter: parent.verticalCenter - - text: "Complete Your Profile" - color: hifi.colors.baseGrayHighlight - verticalAlignment: Text.AlignVCenter - horizontalAlignment: Text.AlignHCenter - } - } - - VerticalSpacer {} - - HorizontalRule {} - - VerticalSpacer {} - - Row { - anchors.horizontalCenter: parent.horizontalCenter - - Button { - anchors.verticalCenter: parent.verticalCenter - - width: 200 - - text: "Create your profile" - color: hifi.buttons.blue - - onClicked: body.sourceComponent = welcomeBody - } - - HorizontalSpacer {} - - Button { - anchors.verticalCenter: parent.verticalCenter - - text: "Cancel" - - onClicked: body.sourceComponent = signInBody - - } - } - - VerticalSpacer {} - - ShortcutText { - text: "Already have a High Fidelity profile? Link to an existing profile here." - - color: hifi.colors.blueAccent - font.underline: true - - verticalAlignment: Text.AlignVCenter - horizontalAlignment: Text.AlignHCenter - } - } - } - - Rectangle { - anchors.fill: root - color: hifi.colors.faintGray - radius: hifi.dimensions.borderRadius - - Loader { - id: body - anchors.centerIn: parent - sourceComponent: signInBody - } - } -} diff --git a/interface/src/ui/LoginDialog.cpp b/interface/src/ui/LoginDialog.cpp index 78aacb1216..08e2b6479d 100644 --- a/interface/src/ui/LoginDialog.cpp +++ b/interface/src/ui/LoginDialog.cpp @@ -54,11 +54,11 @@ void LoginDialog::toggleAction() { } } -bool LoginDialog::isSteamRunning() { +bool LoginDialog::isSteamRunning() const { return SteamClient::isRunning(); } -void LoginDialog::login(const QString& username, const QString& password) { +void LoginDialog::login(const QString& username, const QString& password) const { qDebug() << "Attempting to login " << username; DependencyManager::get()->requestAccessToken(username, password); } @@ -131,25 +131,12 @@ void LoginDialog::createAccountFromStream(QString username) { } -void LoginDialog::openUrl(const QString& url) { +void LoginDialog::openUrl(const QString& url) const { auto offscreenUi = DependencyManager::get(); auto browser = offscreenUi->load("Browser.qml"); browser->setProperty("url", url); } -void LoginDialog::sendRecoveryEmail(const QString& email) { - const QString PASSWORD_RESET_PATH = "/users/password"; - - QJsonObject payload; - payload.insert("user_email", QJsonValue::fromVariant(QVariant(email))); - - - auto accountManager = DependencyManager::get(); - accountManager->sendRequest(PASSWORD_RESET_PATH, AccountManagerAuth::None, - QNetworkAccessManager::PostOperation, JSONCallbackParameters(), - QJsonDocument(payload).toJson()); -} - void LoginDialog::linkCompleted(QNetworkReply& reply) { emit handleLinkCompleted(); } diff --git a/interface/src/ui/LoginDialog.h b/interface/src/ui/LoginDialog.h index ef2c937201..8b6dc40302 100644 --- a/interface/src/ui/LoginDialog.h +++ b/interface/src/ui/LoginDialog.h @@ -45,15 +45,14 @@ public slots: void createFailed(QNetworkReply& reply); protected slots: - Q_INVOKABLE bool isSteamRunning(); + Q_INVOKABLE bool isSteamRunning() const; - Q_INVOKABLE void login(const QString& username, const QString& password); + Q_INVOKABLE void login(const QString& username, const QString& password) const; Q_INVOKABLE void loginThroughSteam(); Q_INVOKABLE void linkSteam(); Q_INVOKABLE void createAccountFromStream(QString username = QString()); - Q_INVOKABLE void openUrl(const QString& url); - Q_INVOKABLE void sendRecoveryEmail(const QString& email); + Q_INVOKABLE void openUrl(const QString& url) const; }; diff --git a/libraries/steamworks-wrapper/src/steamworks-wrapper/SteamClient.cpp b/libraries/steamworks-wrapper/src/steamworks-wrapper/SteamClient.cpp index f6cf13effd..2e8f6bd7b3 100644 --- a/libraries/steamworks-wrapper/src/steamworks-wrapper/SteamClient.cpp +++ b/libraries/steamworks-wrapper/src/steamworks-wrapper/SteamClient.cpp @@ -301,8 +301,7 @@ void SteamClient::joinLobby(QString lobbyIdStr) { if (!initialized) { if (SteamAPI_IsSteamRunning()) { init(); - } - else { + } else { qWarning() << "Steam is not running"; return; } From c34153b67b090d41b1198aa0ca67b1568e298ea6 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 11 Aug 2016 11:57:43 -0700 Subject: [PATCH 19/22] Change Web API arg name to be more descriptif --- interface/src/ui/LoginDialog.cpp | 4 ++-- libraries/networking/src/AccountManager.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/interface/src/ui/LoginDialog.cpp b/interface/src/ui/LoginDialog.cpp index 08e2b6479d..5d1d83d9e3 100644 --- a/interface/src/ui/LoginDialog.cpp +++ b/interface/src/ui/LoginDialog.cpp @@ -92,7 +92,7 @@ void LoginDialog::linkSteam() { const QString LINK_STEAM_PATH = "api/v1/user/link_steam"; QJsonObject payload; - payload.insert("ticket", QJsonValue::fromVariant(QVariant(ticket))); + payload.insert("steam_auth_ticket", QJsonValue::fromVariant(QVariant(ticket))); auto accountManager = DependencyManager::get(); accountManager->sendRequest(LINK_STEAM_PATH, AccountManagerAuth::Required, @@ -118,7 +118,7 @@ void LoginDialog::createAccountFromStream(QString username) { const QString CREATE_ACCOUNT_FROM_STEAM_PATH = "api/v1/user/create_from_steam"; QJsonObject payload; - payload.insert("ticket", QJsonValue::fromVariant(QVariant(ticket))); + payload.insert("steam_auth_ticket", QJsonValue::fromVariant(QVariant(ticket))); if (!username.isEmpty()) { payload.insert("username", QJsonValue::fromVariant(QVariant(username))); } diff --git a/libraries/networking/src/AccountManager.cpp b/libraries/networking/src/AccountManager.cpp index 52d9e87636..d89514b7cd 100644 --- a/libraries/networking/src/AccountManager.cpp +++ b/libraries/networking/src/AccountManager.cpp @@ -518,7 +518,7 @@ void AccountManager::requestAccessTokenWithSteam(QByteArray authSessionTicket) { QByteArray postData; postData.append("grant_type=password&"); - postData.append("ticket=" + QUrl::toPercentEncoding(authSessionTicket) + "&"); + postData.append("steam_auth_ticket=" + QUrl::toPercentEncoding(authSessionTicket) + "&"); postData.append("scope=" + ACCOUNT_MANAGER_REQUESTED_SCOPE); request.setUrl(grantURL); From 19b3aa9c89ce4a35024ce229c4be8e645692be2c Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Fri, 12 Aug 2016 10:42:32 -0700 Subject: [PATCH 20/22] New metaverse web API --- interface/src/ui/LoginDialog.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/ui/LoginDialog.cpp b/interface/src/ui/LoginDialog.cpp index 08e2b6479d..1cc8dfb49a 100644 --- a/interface/src/ui/LoginDialog.cpp +++ b/interface/src/ui/LoginDialog.cpp @@ -89,7 +89,7 @@ void LoginDialog::linkSteam() { callbackParams.errorCallbackReceiver = this; callbackParams.errorCallbackMethod = "linkFailed"; - const QString LINK_STEAM_PATH = "api/v1/user/link_steam"; + const QString LINK_STEAM_PATH = "api/v1/user/steam/link"; QJsonObject payload; payload.insert("ticket", QJsonValue::fromVariant(QVariant(ticket))); @@ -115,7 +115,7 @@ void LoginDialog::createAccountFromStream(QString username) { callbackParams.errorCallbackReceiver = this; callbackParams.errorCallbackMethod = "createFailed"; - const QString CREATE_ACCOUNT_FROM_STEAM_PATH = "api/v1/user/create_from_steam"; + const QString CREATE_ACCOUNT_FROM_STEAM_PATH = "api/v1/user/steam/create"; QJsonObject payload; payload.insert("ticket", QJsonValue::fromVariant(QVariant(ticket))); From 6c5acf448114a95196c857722d6c73e67593d5e8 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Fri, 12 Aug 2016 14:53:03 -0700 Subject: [PATCH 21/22] Change location of the Steam invite icon --- scripts/defaultScripts.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/defaultScripts.js b/scripts/defaultScripts.js index 46439541f1..cf707c4d19 100644 --- a/scripts/defaultScripts.js +++ b/scripts/defaultScripts.js @@ -9,13 +9,13 @@ // -Script.load("system/steam.js"); Script.load("system/progress.js"); Script.load("system/away.js"); Script.load("system/users.js"); Script.load("system/mute.js"); Script.load("system/goto.js"); Script.load("system/hmd.js"); +Script.load("system/steam.js"); Script.load("system/marketplace.js"); Script.load("system/edit.js"); Script.load("system/mod.js"); From 121890235c75a271c2411b177dd5c3fb718713ef Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Fri, 12 Aug 2016 15:24:28 -0700 Subject: [PATCH 22/22] New steam invite icon --- .../assets/images/tools/steam-invite.svg | 112 ++++++++++++++++++ scripts/system/assets/images/tools/steam.jpeg | Bin 979 -> 0 bytes scripts/system/steam.js | 6 +- 3 files changed, 117 insertions(+), 1 deletion(-) create mode 100644 scripts/system/assets/images/tools/steam-invite.svg delete mode 100644 scripts/system/assets/images/tools/steam.jpeg diff --git a/scripts/system/assets/images/tools/steam-invite.svg b/scripts/system/assets/images/tools/steam-invite.svg new file mode 100644 index 0000000000..ce225cca68 --- /dev/null +++ b/scripts/system/assets/images/tools/steam-invite.svg @@ -0,0 +1,112 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/scripts/system/assets/images/tools/steam.jpeg b/scripts/system/assets/images/tools/steam.jpeg deleted file mode 100644 index a39fdf9bc62c72467460026d639f13fc6910831c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 979 zcmex=o^zf-vy^0D~Y0gAs!fGoum%lOQ9rAmjfd4AKk?Ow5cRr@{dn3oAP_Bh&vQ z45k7MjLgi8EF3JXtPp8NCT11}RzV>)MZ-XLVG$+A#KK0S;7K1uohDv}biWfTeoY%~70>``pjeUEy0>($=!2;Y-a92A1ZY`BK`}T9%8N`dqFn?})C| zI`GWEwaDj~jO}#>yXw`>llf#%N#~yJYj>N#sLWC&XR@^DhSPGVwVMt&S|5H~JfR7`#um9y16f5)x(ibvX>(Na?nZq-m{`SqZ`D(I$!z#IMj z@>{-czVmqHrsf6peHA?)mH!1>f0lT2u591>6$h_g`(yF>+?!A_YwyCYt24jFMv1*y zGHtelWpH=EfdgMHmi{;e!m(3JJ0Q;4S>^Dg6ej(@dgylp#sORliY+bUGOf}6KR z<(KSpxkFP^@2bYWFc?i_THY?YUSd|p; z>^l@I+q!h6hL@cvLxD);@ZFFMj=1GxlF(C-BPYm>(a