Merge pull request #13961 from wayne-chen/loginOnLaunch

Pop up login dialog on launch
This commit is contained in:
Wayne Chen 2018-09-11 17:43:29 -07:00 committed by GitHub
commit cb0aa8055f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 230 additions and 93 deletions

View file

@ -0,0 +1,5 @@
<svg width="31" height="23" viewBox="0 0 31 23" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M3.59534 11.0156C6.16042 13.4128 9.65987 15.5898 13.6042 16.1774C17.686 16.7856 22.4164 15.7196 27.3057 11.0659C22.0721 6.07309 17.0642 5.14115 12.9153 5.90073C8.99427 6.61859 5.69298 8.87688 3.59534 11.0156ZM12.455 3.27591C17.7727 2.30235 23.9836 3.74895 30.1053 10.1333L31 11.0664L30.1053 11.9994C24.3636 17.9875 18.4774 19.5983 13.2276 18.8161C8.06048 18.0463 3.70384 14.9892 0.837069 11.9994L0 11.1265L0.778477 10.1986C3.05338 7.48717 7.2318 4.23217 12.455 3.27591Z" fill="#3D3D3D"/>
<ellipse cx="15.6539" cy="10.9218" rx="3.65386" ry="3.81061" fill="#3D3D3D"/>
<line x1="25" y1="2.12132" x2="7.12132" y2="20" stroke="#3D3D3D" stroke-width="3" stroke-linecap="round"/>
</svg>

After

Width:  |  Height:  |  Size: 825 B

View file

@ -0,0 +1,4 @@
<svg width="31" height="16" viewBox="0 0 31 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M3.59534 8.01564C6.16042 10.4128 9.65987 12.5898 13.6042 13.1774C17.686 13.7856 22.4164 12.7196 27.3057 8.06585C22.0721 3.07309 17.0642 2.14115 12.9153 2.90073C8.99427 3.61859 5.69298 5.87688 3.59534 8.01564ZM12.455 0.275915C17.7727 -0.697651 23.9836 0.748949 30.1053 7.13329L31 8.06636L30.1053 8.99944C24.3636 14.9875 18.4774 16.5983 13.2276 15.8161C8.06048 15.0463 3.70384 11.9892 0.837069 8.99944L0 8.12646L0.778477 7.1986C3.05338 4.48717 7.2318 1.23217 12.455 0.275915Z" fill="#3D3D3D"/>
<ellipse cx="15.644" cy="7.92179" rx="3.65386" ry="3.81061" fill="#3D3D3D"/>
</svg>

After

Width:  |  Height:  |  Size: 721 B

View file

@ -23,6 +23,7 @@ ModalWindow {
objectName: "LoginDialog" objectName: "LoginDialog"
implicitWidth: 520 implicitWidth: 520
implicitHeight: 320 implicitHeight: 320
closeButtonVisible: true
destroyOnCloseButton: true destroyOnCloseButton: true
destroyOnHidden: true destroyOnHidden: true
visible: true visible: true

View file

@ -15,7 +15,6 @@ import QtQuick.Controls.Styles 1.4 as OriginalStyles
import "../controls-uit" import "../controls-uit"
import "../styles-uit" import "../styles-uit"
Item { Item {
id: linkAccountBody id: linkAccountBody
clip: true clip: true
@ -87,6 +86,23 @@ Item {
height: 48 height: 48
} }
ShortcutText {
id: flavorText
anchors {
top: parent.top
left: parent.left
margins: 0
topMargin: hifi.dimensions.contentSpacing.y
}
text: qsTr("Sign in to High Fidelity to make friends, get HFC, and buy interesting things on the Marketplace!")
width: parent.width
wrapMode: Text.WordWrap
lineHeight: 1
lineHeightMode: Text.ProportionalHeight
horizontalAlignment: Text.AlignHCenter
}
ShortcutText { ShortcutText {
id: mainTextContainer id: mainTextContainer
anchors { anchors {
@ -97,7 +113,6 @@ Item {
} }
visible: false visible: false
text: qsTr("Username or password incorrect.") text: qsTr("Username or password incorrect.")
wrapMode: Text.WordWrap wrapMode: Text.WordWrap
color: hifi.colors.redAccent color: hifi.colors.redAccent
@ -117,22 +132,21 @@ Item {
} }
spacing: 2 * hifi.dimensions.contentSpacing.y spacing: 2 * hifi.dimensions.contentSpacing.y
TextField { TextField {
id: usernameField id: usernameField
text: Settings.getValue("wallet/savedUsername", ""); text: Settings.getValue("wallet/savedUsername", "");
width: parent.width width: parent.width
focus: true focus: true
label: "Username or Email" placeholderText: "Username or Email"
activeFocusOnPress: true activeFocusOnPress: true
ShortcutText { ShortcutText {
z: 10 z: 10
y: usernameField.height
anchors { anchors {
left: usernameField.left right: usernameField.right
top: usernameField.top top: usernameField.bottom
leftMargin: usernameField.textFieldLabel.contentWidth + 10 topMargin: 4
topMargin: -19
} }
text: "<a href='https://highfidelity.com/users/password/new'>Forgot Username?</a>" text: "<a href='https://highfidelity.com/users/password/new'>Forgot Username?</a>"
@ -143,26 +157,32 @@ Item {
onLinkActivated: loginDialog.openUrl(link) onLinkActivated: loginDialog.openUrl(link)
} }
onFocusChanged: { onFocusChanged: {
root.text = ""; root.text = "";
} }
Component.onCompleted: {
var savedUsername = Settings.getValue("wallet/savedUsername", "");
usernameField.text = savedUsername === "Unknown user" ? "" : savedUsername;
}
} }
TextField { TextField {
id: passwordField id: passwordField
width: parent.width width: parent.width
placeholderText: "Password"
label: "Password"
echoMode: showPassword.checked ? TextInput.Normal : TextInput.Password
activeFocusOnPress: true activeFocusOnPress: true
echoMode: TextInput.Password
onHeightChanged: d.resize(); onWidthChanged: d.resize();
ShortcutText { ShortcutText {
id: forgotPasswordShortcut
y: passwordField.height
z: 10 z: 10
anchors { anchors {
left: passwordField.left right: passwordField.right
top: passwordField.top top: passwordField.bottom
leftMargin: passwordField.textFieldLabel.contentWidth + 10 topMargin: 4
topMargin: -19
} }
text: "<a href='https://highfidelity.com/users/password/new'>Forgot Password?</a>" text: "<a href='https://highfidelity.com/users/password/new'>Forgot Password?</a>"
@ -179,12 +199,45 @@ Item {
root.isPassword = true; root.isPassword = true;
} }
Keys.onReturnPressed: linkAccountBody.login() Rectangle {
id: showPasswordHitbox
z: 10
x: passwordField.width - ((passwordField.height) * 31 / 23)
width: parent.width - (parent.width - (parent.height * 31/16))
height: parent.height
anchors {
right: parent.right
}
color: "transparent"
Image {
id: showPasswordImage
y: (passwordField.height - (passwordField.height * 16 / 23)) / 2
width: passwordField.width - (passwordField.width - (((passwordField.height) * 31/23)))
height: passwordField.height * 16 / 23
anchors {
right: parent.right
rightMargin: 3
}
source: "../../images/eyeOpen.svg"
} }
CheckBox { MouseArea {
id: showPassword id: passwordFieldMouseArea
text: "Show password" anchors.fill: parent
acceptedButtons: Qt.LeftButton
property bool showPassword: false
onClicked: {
showPassword = !showPassword;
passwordField.echoMode = showPassword ? TextInput.Normal : TextInput.Password;
showPasswordImage.source = showPassword ? "../../images/eyeClosed.svg" : "../../images/eyeOpen.svg";
showPasswordImage.height = showPassword ? passwordField.height : passwordField.height * 16 / 23;
showPasswordImage.y = showPassword ? 0 : (passwordField.height - showPasswordImage.height) / 2;
}
}
}
Keys.onReturnPressed: linkAccountBody.login()
} }
InfoItem { InfoItem {
@ -206,6 +259,26 @@ Item {
onHeightChanged: d.resize(); onWidthChanged: d.resize(); onHeightChanged: d.resize(); onWidthChanged: d.resize();
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
CheckBox {
id: autoLogoutCheckbox
checked: !Settings.getValue("wallet/autoLogout", true)
text: "Keep me signed in"
boxSize: 20;
labelFontSize: 15
color: hifi.colors.black
onCheckedChanged: {
Settings.setValue("wallet/autoLogout", !checked);
if (checked) {
Settings.setValue("wallet/savedUsername", Account.username);
} else {
Settings.setValue("wallet/savedUsername", "");
}
}
Component.onDestruction: {
Settings.setValue("wallet/autoLogout", !checked);
}
}
Button { Button {
id: linkAccountButton id: linkAccountButton
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
@ -216,12 +289,6 @@ Item {
onClicked: linkAccountBody.login() onClicked: linkAccountBody.login()
} }
Button {
anchors.verticalCenter: parent.verticalCenter
text: qsTr("Cancel")
onClicked: root.tryDestroy()
}
} }
Row { Row {
@ -234,7 +301,7 @@ Item {
RalewaySemiBold { RalewaySemiBold {
size: hifi.fontSizes.inputLabel size: hifi.fontSizes.inputLabel
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
text: qsTr("Don't have an account?") text: qsTr("New to High Fidelity?")
} }
Button { Button {
@ -287,11 +354,23 @@ Item {
bodyLoader.item.width = root.pane.width bodyLoader.item.width = root.pane.width
bodyLoader.item.height = root.pane.height bodyLoader.item.height = root.pane.height
} }
if (Settings.getValue("loginDialogPoppedUp", false)) {
var data = {
"action": "user logged in"
};
UserActivityLogger.logAction("encourageLoginDialog", data);
}
} }
onHandleLoginFailed: { onHandleLoginFailed: {
console.log("Login Failed") console.log("Login Failed")
mainTextContainer.visible = true mainTextContainer.visible = true
toggleLoading(false) toggleLoading(false)
if (Settings.getValue("loginDialogPoppedUp", false)) {
var data = {
"action": "user failed logging in"
};
UserActivityLogger.logAction("encourageLoginDialog", data);
}
} }
onHandleLinkCompleted: { onHandleLinkCompleted: {
console.log("Link Succeeded") console.log("Link Succeeded")

View file

@ -94,5 +94,25 @@ Frame {
color: hifi.colors.lightGray color: hifi.colors.lightGray
} }
} }
GlyphButton {
id: closeButton
visible: window.closeButtonVisible
width: 30
y: -hifi.dimensions.modalDialogTitleHeight
anchors {
top: parent.top
right: parent.right
topMargin: 10
rightMargin: 10
}
glyph: hifi.glyphs.close
size: 23
onClicked: {
window.clickedCloseButton = true;
window.destroy();
}
}
} }
} }

View file

@ -19,6 +19,9 @@ ScrollingWindow {
destroyOnHidden: true destroyOnHidden: true
frame: ModalFrame { } frame: ModalFrame { }
property bool closeButtonVisible: false
// only applicable for if close button is visible.
property bool clickedCloseButton: false
property int colorScheme: hifi.colorSchemes.light property int colorScheme: hifi.colorSchemes.light
property bool draggable: false property bool draggable: false

View file

@ -2299,6 +2299,24 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
connect(&AndroidHelper::instance(), &AndroidHelper::enterForeground, this, &Application::enterForeground); connect(&AndroidHelper::instance(), &AndroidHelper::enterForeground, this, &Application::enterForeground);
AndroidHelper::instance().notifyLoadComplete(); AndroidHelper::instance().notifyLoadComplete();
#endif #endif
static int CHECK_LOGIN_TIMER = 3000;
QTimer* checkLoginTimer = new QTimer(this);
checkLoginTimer->setInterval(CHECK_LOGIN_TIMER);
checkLoginTimer->setSingleShot(true);
connect(checkLoginTimer, &QTimer::timeout, this, [this]() {
auto accountManager = DependencyManager::get<AccountManager>();
auto dialogsManager = DependencyManager::get<DialogsManager>();
if (!accountManager->isLoggedIn()) {
Setting::Handle<bool>{"loginDialogPoppedUp", false}.set(true);
dialogsManager->showLoginDialog();
QJsonObject loginData = {};
loginData["action"] = "login dialog shown";
UserActivityLogger::getInstance().logAction("encourageLoginDialog", loginData);
}
});
Setting::Handle<bool>{"loginDialogPoppedUp", false}.set(false);
checkLoginTimer->start();
} }
void Application::updateVerboseLogging() { void Application::updateVerboseLogging() {
@ -2432,6 +2450,8 @@ void Application::onAboutToQuit() {
// so its persisted explicitly here // so its persisted explicitly here
Setting::Handle<QString>{ ACTIVE_DISPLAY_PLUGIN_SETTING_NAME }.set(getActiveDisplayPlugin()->getName()); Setting::Handle<QString>{ ACTIVE_DISPLAY_PLUGIN_SETTING_NAME }.set(getActiveDisplayPlugin()->getName());
Setting::Handle<bool>{"loginDialogPoppedUp", false}.set(false);
getActiveDisplayPlugin()->deactivate(); getActiveDisplayPlugin()->deactivate();
if (_autoSwitchDisplayModeSupportedHMDPlugin if (_autoSwitchDisplayModeSupportedHMDPlugin
&& _autoSwitchDisplayModeSupportedHMDPlugin->isSessionActive()) { && _autoSwitchDisplayModeSupportedHMDPlugin->isSessionActive()) {

View file

@ -331,6 +331,8 @@ signals:
void uploadRequest(QString path); void uploadRequest(QString path);
void loginDialogPoppedUp();
public slots: public slots:
QVector<EntityItemID> pasteEntities(float x, float y, float z); QVector<EntityItemID> pasteEntities(float x, float y, float z);
bool exportEntities(const QString& filename, const QVector<EntityItemID>& entityIDs, const glm::vec3* givenOffset = nullptr); bool exportEntities(const QString& filename, const QVector<EntityItemID>& entityIDs, const glm::vec3* givenOffset = nullptr);

View file

@ -19,6 +19,7 @@
#include <plugins/PluginManager.h> #include <plugins/PluginManager.h>
#include <plugins/SteamClientPlugin.h> #include <plugins/SteamClientPlugin.h>
#include <ui/TabletScriptingInterface.h> #include <ui/TabletScriptingInterface.h>
#include <UserActivityLogger.h>
#include "AccountManager.h" #include "AccountManager.h"
#include "DependencyManager.h" #include "DependencyManager.h"
@ -37,11 +38,19 @@ LoginDialog::LoginDialog(QQuickItem *parent) : OffscreenQmlDialog(parent) {
connect(accountManager.data(), &AccountManager::loginFailed, connect(accountManager.data(), &AccountManager::loginFailed,
this, &LoginDialog::handleLoginFailed); this, &LoginDialog::handleLoginFailed);
#endif #endif
} }
void LoginDialog::showWithSelection() LoginDialog::~LoginDialog() {
{ Setting::Handle<bool> loginDialogPoppedUp{ "loginDialogPoppedUp", false };
if (loginDialogPoppedUp.get()) {
QJsonObject data;
data["action"] = "user opted out";
UserActivityLogger::getInstance().logAction("encourageLoginDialog", data);
}
loginDialogPoppedUp.set(false);
}
void LoginDialog::showWithSelection() {
auto tabletScriptingInterface = DependencyManager::get<TabletScriptingInterface>(); auto tabletScriptingInterface = DependencyManager::get<TabletScriptingInterface>();
auto tablet = dynamic_cast<TabletProxy*>(tabletScriptingInterface->getTablet("com.highfidelity.interface.tablet.system")); auto tablet = dynamic_cast<TabletProxy*>(tabletScriptingInterface->getTablet("com.highfidelity.interface.tablet.system"));
auto hmd = DependencyManager::get<HMDScriptingInterface>(); auto hmd = DependencyManager::get<HMDScriptingInterface>();
@ -73,9 +82,7 @@ void LoginDialog::toggleAction() {
} else { } else {
// change the menu item to login // change the menu item to login
loginAction->setText("Login / Sign Up"); loginAction->setText("Login / Sign Up");
connection = connect(loginAction, &QAction::triggered, [] { connection = connect(loginAction, &QAction::triggered, [] { LoginDialog::showWithSelection(); });
LoginDialog::showWithSelection();
});
} }
} }
@ -158,7 +165,6 @@ void LoginDialog::createAccountFromStream(QString username) {
QJsonDocument(payload).toJson()); QJsonDocument(payload).toJson());
}); });
} }
} }
void LoginDialog::openUrl(const QString& url) const { void LoginDialog::openUrl(const QString& url) const {
@ -200,7 +206,6 @@ void LoginDialog::createFailed(QNetworkReply* reply) {
} }
void LoginDialog::signup(const QString& email, const QString& username, const QString& password) { void LoginDialog::signup(const QString& email, const QString& username, const QString& password) {
JSONCallbackParameters callbackParams; JSONCallbackParameters callbackParams;
callbackParams.callbackReceiver = this; callbackParams.callbackReceiver = this;
callbackParams.jsonCallbackMethod = "signupCompleted"; callbackParams.jsonCallbackMethod = "signupCompleted";
@ -240,7 +245,6 @@ QString errorStringFromAPIObject(const QJsonValue& apiObject) {
} }
void LoginDialog::signupFailed(QNetworkReply* reply) { void LoginDialog::signupFailed(QNetworkReply* reply) {
// parse the returned JSON to see what the problem was // parse the returned JSON to see what the problem was
auto jsonResponse = QJsonDocument::fromJson(reply->readAll()); auto jsonResponse = QJsonDocument::fromJson(reply->readAll());
@ -274,7 +278,4 @@ void LoginDialog::signupFailed(QNetworkReply* reply) {
static const QString DEFAULT_SIGN_UP_FAILURE_MESSAGE = "There was an unknown error while creating your account. Please try again later."; static const QString DEFAULT_SIGN_UP_FAILURE_MESSAGE = "There was an unknown error while creating your account. Please try again later.";
emit handleSignupFailed(DEFAULT_SIGN_UP_FAILURE_MESSAGE); emit handleSignupFailed(DEFAULT_SIGN_UP_FAILURE_MESSAGE);
} }
} }

View file

@ -27,7 +27,10 @@ public:
LoginDialog(QQuickItem* parent = nullptr); LoginDialog(QQuickItem* parent = nullptr);
~LoginDialog();
static void showWithSelection(); static void showWithSelection();
signals: signals:
void handleLoginCompleted(); void handleLoginCompleted();
void handleLoginFailed(); void handleLoginFailed();
@ -62,7 +65,6 @@ protected slots:
Q_INVOKABLE void signup(const QString& email, const QString& username, const QString& password); Q_INVOKABLE void signup(const QString& email, const QString& username, const QString& password);
Q_INVOKABLE void openUrl(const QString& url) const; Q_INVOKABLE void openUrl(const QString& url) const;
}; };
#endif // hifi_LoginDialog_h #endif // hifi_LoginDialog_h