Unified · Split
| @@ -120,6 +120,6 @@ FocusScope { · 119 unmodified lines | ||
| 120 | 120 | } |
| 121 | 121 | |
| 122 | 122 | Component.onCompleted: { |
| 123 | − bodyLoader.setSource("LoginDialog/LinkAccountBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "linkSteam": false }); | |
| 123 | + bodyLoader.setSource("LoginDialog/LinkAccountBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "linkSteam": false, "linkOculus": false }); | |
| 124 | 124 | } |
| 125 | 125 | } |
| @@ -22,11 +22,16 @@ Item { · 21 unmodified lines | ||
| 22 | 22 | width: root.width |
| 23 | 23 | height: root.height |
| 24 | 24 | readonly property string termsContainerText: qsTr("By creating this user profile, you agree to High Fidelity's Terms of Service") |
| 25 | + readonly property string termsContainerOculusText: qsTr("By signing up, you agree to High Fidelity's Terms of Service") | |
| 26 | + readonly property int textFieldHeight: 31 | |
| 25 | 27 | readonly property string fontFamily: "Raleway" |
| 26 | 28 | readonly property int fontSize: 15 |
| 27 | 29 | readonly property bool fontBold: true |
| 30 | + readonly property int textFieldFontSize: 18 | |
| 31 | + readonly property var passwordImageRatio: 16 / 23 | |
| 28 | 32 | |
| 29 | − readonly property bool withSteam: withSteam | |
| 33 | + property bool withOculus: withOculus | |
| 34 | + property bool withSteam: withSteam | |
| 30 | 35 | property string errorString: errorString |
| 31 | 36 | |
| 32 | 37 | readonly property bool loginDialogPoppedUp: loginDialog.getLoginDialogPoppedUp() |
| @@ -61,15 +66,20 @@ Item { · 28 unmodified lines | ||
| 61 | 66 | |
| 62 | 67 | Item { |
| 63 | 68 | id: contentItem |
| 64 | − anchors.fill: parent | |
| 69 | + width: parent.width | |
| 70 | + height: errorContainer.height + fields.height + buttons.height + additionalTextContainer.height + | |
| 71 | + termsContainer.height | |
| 72 | + anchors.top: parent.top | |
| 73 | + anchors.topMargin: root.bannerHeight + 0.25 * parent.height | |
| 74 | + anchors.left: parent.left | |
| 65 | 75 | |
| 66 | 76 | Item { |
| 67 | 77 | id: errorContainer |
| 68 | − width: parent.width | |
| 78 | + width: root.bannerWidth | |
| 69 | 79 | height: loginErrorMessageTextMetrics.height |
| 70 | 80 | anchors { |
| 71 | − bottom: buttons.top; | |
| 72 | − bottomMargin: hifi.dimensions.contentSpacing.y; | |
| 81 | + bottom: completeProfileBody.withOculus ? fields.top : buttons.top; | |
| 82 | + bottomMargin: 1.5 * hifi.dimensions.contentSpacing.y; | |
| 73 | 83 | left: buttons.left; |
| 74 | 84 | } |
| 75 | 85 | TextMetrics { |
| @@ -79,8 +89,8 @@ Item { · 3 unmodified lines | ||
| 79 | 89 | } |
| 80 | 90 | Text { |
| 81 | 91 | id: loginErrorMessage; |
| 82 | − width: root.bannerWidth | |
| 83 | 92 | color: "red"; |
| 93 | + width: root.bannerWidth; | |
| 84 | 94 | font.family: completeProfileBody.fontFamily |
| 85 | 95 | font.pixelSize: 18 |
| 86 | 96 | font.bold: completeProfileBody.fontBold |
| @@ -88,13 +98,196 @@ Item { · 1 unmodified line | ||
| 88 | 98 | horizontalAlignment: Text.AlignHCenter |
| 89 | 99 | text: completeProfileBody.errorString |
| 90 | 100 | visible: true |
| 101 | + onTextChanged: { | |
| 102 | + mainContainer.recalculateErrorMessage(); | |
| 103 | + } | |
| 104 | + Component.onCompleted: { | |
| 105 | + mainContainer.recalculateErrorMessage(); | |
| 106 | + } | |
| 107 | + } | |
| 108 | + } | |
| 109 | + | |
| 110 | + Item { | |
| 111 | + id: fields | |
| 112 | + width: root.bannerWidth | |
| 113 | + height: 3 * completeProfileBody.textFieldHeight + 2 * hifi.dimensions.contentSpacing.y | |
| 114 | + visible: completeProfileBody.withOculus | |
| 115 | + anchors { | |
| 116 | + left: parent.left | |
| 117 | + leftMargin: (parent.width - root.bannerWidth) / 2 | |
| 118 | + bottom: buttons.top | |
| 119 | + bottomMargin: hifi.dimensions.contentSpacing.y | |
| 120 | + } | |
| 121 | + | |
| 122 | + HifiControlsUit.TextField { | |
| 123 | + id: usernameField | |
| 124 | + width: root.bannerWidth | |
| 125 | + height: completeProfileBody.textFieldHeight | |
| 126 | + placeholderText: "Username" | |
| 127 | + font.pixelSize: completeProfileBody.textFieldFontSize | |
| 128 | + styleRenderType: Text.QtRendering | |
| 129 | + anchors { | |
| 130 | + top: parent.top | |
| 131 | + } | |
| 132 | + Keys.onPressed: { | |
| 133 | + if (!usernameField.visible) { | |
| 134 | + return; | |
| 135 | + } | |
| 136 | + switch (event.key) { | |
| 137 | + case Qt.Key_Tab: | |
| 138 | + event.accepted = true; | |
| 139 | + if (event.modifiers === Qt.ShiftModifier) { | |
| 140 | + passwordField.focus = true; | |
| 141 | + } else { | |
| 142 | + emailField.focus = true; | |
| 143 | + } | |
| 144 | + break; | |
| 145 | + case Qt.Key_Backtab: | |
| 146 | + event.accepted = true; | |
| 147 | + passwordField.focus = true; | |
| 148 | + break; | |
| 149 | + case Qt.Key_Enter: | |
| 150 | + case Qt.Key_Return: | |
| 151 | + event.accepted = true; | |
| 152 | + loginDialog.createAccountFromOculus(emailField.text, usernameField.text, passwordField.text); | |
| 153 | + bodyLoader.setSource("LoggingInBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "withSteam": completeProfileBody.withSteam, | |
| 154 | + "linkSteam": false, "withOculus": completeProfileBody.withOculus, "linkOculus": false, "createOculus": true }); | |
| 155 | + break; | |
| 156 | + } | |
| 157 | + } | |
| 158 | + onFocusChanged: { | |
| 159 | + root.text = ""; | |
| 160 | + if (focus) { | |
| 161 | + root.isPassword = false; | |
| 162 | + } | |
| 163 | + } | |
| 164 | + Component.onCompleted: { | |
| 165 | + var userID = ""; | |
| 166 | + if (completeProfileBody.withOculus) { | |
| 167 | + userID = loginDialog.oculusUserID(); | |
| 168 | + } | |
| 169 | + usernameField.text = userID; | |
| 170 | + } | |
| 171 | + } | |
| 172 | + HifiControlsUit.TextField { | |
| 173 | + id: emailField | |
| 174 | + width: root.bannerWidth | |
| 175 | + height: completeProfileBody.textFieldHeight | |
| 176 | + anchors { | |
| 177 | + top: usernameField.bottom | |
| 178 | + topMargin: hifi.dimensions.contentSpacing.y | |
| 179 | + } | |
| 180 | + placeholderText: "Email" | |
| 181 | + font.pixelSize: completeProfileBody.textFieldFontSize | |
| 182 | + styleRenderType: Text.QtRendering | |
| 183 | + activeFocusOnPress: true | |
| 184 | + Keys.onPressed: { | |
| 185 | + switch (event.key) { | |
| 186 | + case Qt.Key_Tab: | |
| 187 | + event.accepted = true; | |
| 188 | + if (event.modifiers === Qt.ShiftModifier) { | |
| 189 | + usernameField.focus = true; | |
| 190 | + } else { | |
| 191 | + passwordField.focus = true; | |
| 192 | + } | |
| 193 | + break; | |
| 194 | + case Qt.Key_Backtab: | |
| 195 | + event.accepted = true; | |
| 196 | + usernameField.focus = true; | |
| 197 | + break; | |
| 198 | + case Qt.Key_Enter: | |
| 199 | + case Qt.Key_Return: | |
| 200 | + event.accepted = true; | |
| 201 | + loginDialog.createAccountFromOculus(emailField.text, usernameField.text, passwordField.text); | |
| 202 | + bodyLoader.setSource("LoggingInBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "withSteam": completeProfileBody.withSteam, | |
| 203 | + "linkSteam": false, "withOculus": completeProfileBody.withOculus, "linkOculus": false, "createOculus": true }); | |
| 204 | + break; | |
| 205 | + } | |
| 206 | + } | |
| 207 | + onFocusChanged: { | |
| 208 | + root.text = ""; | |
| 209 | + if (focus) { | |
| 210 | + root.isPassword = false; | |
| 211 | + } | |
| 212 | + } | |
| 91 | 213 | } |
| 92 | − Component.onCompleted: { | |
| 93 | − if (loginErrorMessageTextMetrics.width > root.bannerWidth && root.isTablet) { | |
| 94 | − loginErrorMessage.wrapMode = Text.WordWrap; | |
| 95 | − loginErrorMessage.verticalAlignment = Text.AlignLeft; | |
| 96 | − loginErrorMessage.horizontalAlignment = Text.AlignLeft; | |
| 97 | − errorContainer.height = 3 * loginErrorMessageTextMetrics.height; | |
| 214 | + HifiControlsUit.TextField { | |
| 215 | + id: passwordField | |
| 216 | + width: root.bannerWidth | |
| 217 | + height: completeProfileBody.textFieldHeight | |
| 218 | + placeholderText: "Password (optional)" | |
| 219 | + font.pixelSize: completeProfileBody.textFieldFontSize | |
| 220 | + styleRenderType: Text.QtRendering | |
| 221 | + activeFocusOnPress: true | |
| 222 | + echoMode: passwordFieldMouseArea.showPassword ? TextInput.Normal : TextInput.Password | |
| 223 | + anchors { | |
| 224 | + top: emailField.bottom | |
| 225 | + topMargin: hifi.dimensions.contentSpacing.y | |
| 226 | + } | |
| 227 | + | |
| 228 | + onFocusChanged: { | |
| 229 | + root.text = ""; | |
| 230 | + root.isPassword = focus; | |
| 231 | + } | |
| 232 | + | |
| 233 | + Item { | |
| 234 | + id: showPasswordContainer | |
| 235 | + z: 10 | |
| 236 | + // width + image's rightMargin | |
| 237 | + width: showPasswordImage.width + 8 | |
| 238 | + height: parent.height | |
| 239 | + anchors { | |
| 240 | + right: parent.right | |
| 241 | + } | |
| 242 | + | |
| 243 | + Image { | |
| 244 | + id: showPasswordImage | |
| 245 | + width: passwordField.height * passwordImageRatio | |
| 246 | + height: passwordField.height * passwordImageRatio | |
| 247 | + anchors { | |
| 248 | + right: parent.right | |
| 249 | + rightMargin: 8 | |
| 250 | + top: parent.top | |
| 251 | + topMargin: passwordFieldMouseArea.showPassword ? 6 : 8 | |
| 252 | + bottom: parent.bottom | |
| 253 | + bottomMargin: passwordFieldMouseArea.showPassword ? 5 : 8 | |
| 254 | + } | |
| 255 | + source: passwordFieldMouseArea.showPassword ? "../../images/eyeClosed.svg" : "../../images/eyeOpen.svg" | |
| 256 | + MouseArea { | |
| 257 | + id: passwordFieldMouseArea | |
| 258 | + anchors.fill: parent | |
| 259 | + acceptedButtons: Qt.LeftButton | |
| 260 | + property bool showPassword: false | |
| 261 | + onClicked: { | |
| 262 | + showPassword = !showPassword; | |
| 263 | + } | |
| 264 | + } | |
| 265 | + } | |
| 266 | + } | |
| 267 | + Keys.onPressed: { | |
| 268 | + switch (event.key) { | |
| 269 | + case Qt.Key_Tab: | |
| 270 | + event.accepted = true; | |
| 271 | + if (event.modifiers === Qt.ShiftModifier) { | |
| 272 | + emailField.focus = true; | |
| 273 | + } else if (usernameField.visible) { | |
| 274 | + usernameField.focus = true; | |
| 275 | + } else { | |
| 276 | + emailField.focus = true; | |
| 277 | + } | |
| 278 | + break; | |
| 279 | + case Qt.Key_Backtab: | |
| 280 | + event.accepted = true; | |
| 281 | + emailField.focus = true; | |
| 282 | + break; | |
| 283 | + case Qt.Key_Enter: | |
| 284 | + case Qt.Key_Return: | |
| 285 | + event.accepted = true; | |
| 286 | + loginDialog.createAccountFromOculus(emailField.text, usernameField.text, passwordField.text); | |
| 287 | + bodyLoader.setSource("LoggingInBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "withSteam": completeProfileBody.withSteam, | |
| 288 | + "linkSteam": false, "withOculus": completeProfileBody.withOculus, "linkOculus": false, "createOculus": true }); | |
| 289 | + break; | |
| 290 | + } | |
| 98 | 291 | } |
| 99 | 292 | } |
| 100 | 293 | } |
| @@ -105,7 +298,7 @@ Item { · 4 unmodified lines | ||
| 105 | 298 | height: d.minHeightButton |
| 106 | 299 | anchors { |
| 107 | 300 | top: parent.top |
| 108 | − topMargin: (parent.height - additionalTextContainer.height) / 2 - hifi.dimensions.contentSpacing.y | |
| 301 | + topMargin: (parent.height - additionalTextContainer.height + fields.height) / 2 - hifi.dimensions.contentSpacing.y | |
| 109 | 302 | left: parent.left |
| 110 | 303 | leftMargin: (parent.width - root.bannerWidth) / 2 |
| 111 | 304 | } |
| @@ -144,7 +337,7 @@ Item { · 32 unmodified lines | ||
| 144 | 337 | width: (parent.width - hifi.dimensions.contentSpacing.x) / 2 |
| 145 | 338 | height: d.minHeightButton |
| 146 | 339 | |
| 147 | − text: qsTr("Create your profile") | |
| 340 | + text: completeProfileBody.withOculus ? qsTr("Sign Up") : qsTr("Create your profile") | |
| 148 | 341 | color: hifi.buttons.blue |
| 149 | 342 | |
| 150 | 343 | fontFamily: completeProfileBody.fontFamily |
| @@ -158,116 +351,149 @@ Item { · 7 unmodified lines | ||
| 158 | 351 | UserActivityLogger.logAction("encourageLoginDialog", data); |
| 159 | 352 | } |
| 160 | 353 | loginErrorMessage.visible = false; |
| 161 | − loginDialog.createAccountFromSteam(); | |
| 354 | + if (completeProfileBody.withOculus) { | |
| 355 | + loginDialog.createAccountFromOculus(emailField.text, usernameField.text, passwordField.text); | |
| 356 | + bodyLoader.setSource("LoggingInBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "withSteam": completeProfileBody.withSteam, | |
| 357 | + "linkSteam": false, "withOculus": completeProfileBody.withOculus, "linkOculus": false, "createOculus": true }); | |
| 358 | + } else if (completeProfileBody.withSteam) { | |
| 359 | + loginDialog.createAccountFromSteam(); | |
| 360 | + } | |
| 162 | 361 | } |
| 163 | 362 | } |
| 164 | 363 | } |
| 165 | 364 | |
| 166 | 365 | Item { |
| 167 | − id: additionalTextContainer | |
| 366 | + id: termsContainer | |
| 168 | 367 | width: parent.width |
| 169 | − height: additionalTextMetrics.height | |
| 368 | + height: termsTextMetrics.height | |
| 170 | 369 | anchors { |
| 171 | 370 | top: buttons.bottom |
| 172 | 371 | horizontalCenter: parent.horizontalCenter |
| 173 | 372 | topMargin: hifi.dimensions.contentSpacing.y |
| 174 | 373 | left: parent.left |
| 175 | 374 | } |
| 176 | − | |
| 177 | 375 | TextMetrics { |
| 178 | − id: additionalTextMetrics | |
| 179 | − font: additionalText.font | |
| 180 | − text: "Already have a High Fidelity profile? Link to an existing profile here." | |
| 376 | + id: termsTextMetrics | |
| 377 | + font: termsText.font | |
| 378 | + text: completeProfileBody.withOculus ? completeProfileBody.termsContainerOculusText : completeProfileBody.termsContainerText | |
| 379 | + Component.onCompleted: { | |
| 380 | + // with the link. | |
| 381 | + if (completeProfileBody.withOculus) { | |
| 382 | + termsText.text = qsTr("By signing up, you agree to <a href='https://highfidelity.com/terms'>High Fidelity's Terms of Service</a>") | |
| 383 | + } else { | |
| 384 | + termsText.text = qsTr("By creating this user profile, you agree to <a href='https://highfidelity.com/terms'>High Fidelity's Terms of Service</a>") | |
| 385 | + } | |
| 386 | + } | |
| 181 | 387 | } |
| 182 | 388 | |
| 183 | − HifiStylesUit.ShortcutText { | |
| 184 | − id: additionalText | |
| 185 | − text: "<a href='https://fake.link'>Already have a High Fidelity profile? Link to an existing profile here.</a>" | |
| 186 | − | |
| 389 | + HifiStylesUit.InfoItem { | |
| 390 | + id: termsText | |
| 391 | + text: completeProfileBody.withOculus ? completeProfileBody.termsContainerOculusText : completeProfileBody.termsContainerText | |
| 187 | 392 | font.family: completeProfileBody.fontFamily |
| 188 | 393 | font.pixelSize: completeProfileBody.fontSize |
| 189 | 394 | font.bold: completeProfileBody.fontBold |
| 190 | − wrapMode: Text.NoWrap | |
| 395 | + wrapMode: Text.WordWrap | |
| 396 | + color: hifi.colors.white | |
| 397 | + linkColor: hifi.colors.blueAccent | |
| 191 | 398 | lineHeight: 1 |
| 192 | 399 | lineHeightMode: Text.ProportionalHeight |
| 193 | − horizontalAlignment: Text.AlignHCenter | |
| 194 | − linkColor: hifi.colors.blueAccent | |
| 195 | 400 | |
| 196 | − onLinkActivated: { | |
| 197 | − loginDialog.isLogIn = true; | |
| 198 | − bodyLoader.setSource("LinkAccountBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "errorString": "", "withSteam": true, "linkSteam": true }); | |
| 199 | − } | |
| 401 | + onLinkActivated: loginDialog.openUrl(link); | |
| 402 | + | |
| 200 | 403 | Component.onCompleted: { |
| 201 | − if (additionalTextMetrics.width > root.bannerWidth && root.isTablet) { | |
| 202 | − additionalText.width = root.bannerWidth; | |
| 203 | − additionalText.wrapMode = Text.WordWrap; | |
| 404 | + if (termsTextMetrics.width > root.bannerWidth) { | |
| 405 | + termsText.width = root.bannerWidth; | |
| 406 | + termsText.wrapMode = Text.WordWrap; | |
| 204 | 407 | additionalText.verticalAlignment = Text.AlignLeft; |
| 205 | 408 | additionalText.horizontalAlignment = Text.AlignLeft; |
| 206 | − additionalTextContainer.height = (additionalTextMetrics.width / root.bannerWidth) * additionalTextMetrics.height; | |
| 207 | − additionalTextContainer.anchors.left = buttons.left; | |
| 409 | + termsContainer.height = (termsTextMetrics.width / root.bannerWidth) * termsTextMetrics.height; | |
| 410 | + termsContainer.anchors.left = buttons.left; | |
| 208 | 411 | } else { |
| 209 | − additionalText.anchors.centerIn = additionalTextContainer; | |
| 412 | + termsText.anchors.centerIn = termsContainer; | |
| 210 | 413 | } |
| 211 | 414 | } |
| 212 | 415 | } |
| 213 | 416 | } |
| 214 | 417 | |
| 215 | 418 | Item { |
| 216 | − id: termsContainer | |
| 419 | + id: additionalTextContainer | |
| 217 | 420 | width: parent.width |
| 218 | − height: termsTextMetrics.height | |
| 421 | + height: additionalTextMetrics.height | |
| 219 | 422 | anchors { |
| 220 | − top: additionalTextContainer.bottom | |
| 423 | + top: termsContainer.bottom | |
| 221 | 424 | horizontalCenter: parent.horizontalCenter |
| 222 | 425 | topMargin: 2 * hifi.dimensions.contentSpacing.y |
| 223 | 426 | left: parent.left |
| 224 | 427 | } |
| 428 | + | |
| 225 | 429 | TextMetrics { |
| 226 | − id: termsTextMetrics | |
| 227 | − font: termsText.font | |
| 228 | − text: completeProfileBody.termsContainerText | |
| 229 | − Component.onCompleted: { | |
| 230 | − // with the link. | |
| 231 | − termsText.text = qsTr("By creating this user profile, you agree to <a href='https://highfidelity.com/terms'>High Fidelity's Terms of Service</a>") | |
| 232 | − } | |
| 430 | + id: additionalTextMetrics | |
| 431 | + font: additionalText.font | |
| 432 | + text: "Already have a High Fidelity profile? Link to an existing profile here." | |
| 233 | 433 | } |
| 234 | 434 | |
| 235 | − HifiStylesUit.InfoItem { | |
| 236 | − id: termsText | |
| 237 | − text: completeProfileBody.termsContainerText | |
| 435 | + HifiStylesUit.ShortcutText { | |
| 436 | + id: additionalText | |
| 437 | + text: "<a href='https://fake.link'>Already have a High Fidelity profile? Link to an existing profile here.</a>" | |
| 438 | + width: root.bannerWidth; | |
| 238 | 439 | font.family: completeProfileBody.fontFamily |
| 239 | 440 | font.pixelSize: completeProfileBody.fontSize |
| 240 | 441 | font.bold: completeProfileBody.fontBold |
| 241 | − wrapMode: Text.WordWrap | |
| 242 | − color: hifi.colors.lightGray | |
| 243 | − linkColor: hifi.colors.blueAccent | |
| 442 | + wrapMode: Text.NoWrap | |
| 244 | 443 | lineHeight: 1 |
| 245 | 444 | lineHeightMode: Text.ProportionalHeight |
| 445 | + horizontalAlignment: Text.AlignHCenter | |
| 446 | + linkColor: hifi.colors.blueAccent | |
| 246 | 447 | |
| 247 | − onLinkActivated: loginDialog.openUrl(link); | |
| 248 | − | |
| 448 | + onLinkActivated: { | |
| 449 | + bodyLoader.setSource("LinkAccountBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "errorString": "", | |
| 450 | + "withSteam": completeProfileBody.withSteam, "linkSteam": completeProfileBody.withSteam, "withOculus": completeProfileBody.withOculus, | |
| 451 | + "linkOculus": completeProfileBody.withOculus }); | |
| 452 | + } | |
| 249 | 453 | Component.onCompleted: { |
| 250 | − if (termsTextMetrics.width > root.bannerWidth && root.isTablet) { | |
| 251 | − termsText.width = root.bannerWidth; | |
| 252 | − termsText.wrapMode = Text.WordWrap; | |
| 454 | + if (additionalTextMetrics.width > root.bannerWidth) { | |
| 455 | + additionalText.wrapMode = Text.WordWrap; | |
| 253 | 456 | additionalText.verticalAlignment = Text.AlignLeft; |
| 254 | 457 | additionalText.horizontalAlignment = Text.AlignLeft; |
| 255 | − termsContainer.height = (termsTextMetrics.width / root.bannerWidth) * termsTextMetrics.height; | |
| 256 | − termsContainer.anchors.left = buttons.left; | |
| 458 | + additionalTextContainer.height = (additionalTextMetrics.width / root.bannerWidth) * additionalTextMetrics.height; | |
| 459 | + additionalTextContainer.anchors.left = buttons.left; | |
| 257 | 460 | } else { |
| 258 | − termsText.anchors.centerIn = termsContainer; | |
| 461 | + additionalText.anchors.centerIn = additionalTextContainer; | |
| 259 | 462 | } |
| 260 | 463 | } |
| 261 | 464 | } |
| 262 | 465 | } |
| 263 | 466 | } |
| 467 | + function recalculateErrorMessage() { | |
| 468 | + if (completeProfileBody.errorString !== "") { | |
| 469 | + loginErrorMessage.visible = true; | |
| 470 | + var errorLength = completeProfileBody.errorString.split(/\r\n|\r|\n/).length; | |
| 471 | + var errorStringEdited = completeProfileBody.errorString.replace(/[\n\r]+/g, "\n"); | |
| 472 | + loginErrorMessage.text = errorStringEdited; | |
| 473 | + if (errorLength > 1.0) { | |
| 474 | + loginErrorMessage.wrapMode = Text.WordWrap; | |
| 475 | + loginErrorMessage.verticalAlignment = Text.AlignLeft; | |
| 476 | + loginErrorMessage.horizontalAlignment = Text.AlignLeft; | |
| 477 | + errorContainer.height = errorLength * loginErrorMessageTextMetrics.height; | |
| 478 | + } else if (loginErrorMessageTextMetrics.width > root.bannerWidth) { | |
| 479 | + loginErrorMessage.wrapMode = Text.WordWrap; | |
| 480 | + loginErrorMessage.verticalAlignment = Text.AlignLeft; | |
| 481 | + loginErrorMessage.horizontalAlignment = Text.AlignLeft; | |
| 482 | + errorContainer.height = (loginErrorMessageTextMetrics.width / root.bannerWidth) * loginErrorMessageTextMetrics.height; | |
| 483 | + } else { | |
| 484 | + loginErrorMessage.wrapMode = Text.NoWrap; | |
| 485 | + loginErrorMessage.verticalAlignment = Text.AlignVCenter; | |
| 486 | + loginErrorMessage.horizontalAlignment = Text.AlignHCenter; | |
| 487 | + errorContainer.height = loginErrorMessageTextMetrics.height; | |
| 488 | + } | |
| 489 | + } | |
| 490 | + } | |
| 264 | 491 | } |
| 265 | 492 | |
| 266 | 493 | Connections { |
| 267 | 494 | target: loginDialog |
| 268 | 495 | onHandleCreateCompleted: { |
| 269 | − console.log("Create Succeeded") | |
| 270 | − | |
| 496 | + console.log("Create Succeeded"); | |
| 271 | 497 | if (completeProfileBody.withSteam) { |
| 272 | 498 | if (completeProfileBody.loginDialogPoppedUp) { |
| 273 | 499 | var data = { |
| @@ -277,20 +503,24 @@ Item { · 3 unmodified lines | ||
| 277 | 503 | } |
| 278 | 504 | loginDialog.loginThroughSteam(); |
| 279 | 505 | } |
| 280 | − bodyLoader.setSource("LoggingInBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "withSteam": completeProfileBody.withSteam, "linkSteam": false }); | |
| 506 | + bodyLoader.setSource("LoggingInBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "withSteam": completeProfileBody.withSteam, "linkSteam": false, | |
| 507 | + "withOculus": completeProfileBody.withOculus, "linkOculus": false }); | |
| 281 | 508 | } |
| 282 | 509 | onHandleCreateFailed: { |
| 283 | 510 | console.log("Create Failed: " + error); |
| 284 | − if (completeProfileBody.withSteam) { | |
| 511 | + if (completeProfileBody.withSteam || completeProfileBody.withOculus) { | |
| 285 | 512 | if (completeProfileBody.loginDialogPoppedUp) { |
| 513 | + action = completeProfileBody.withSteam ? "Steam" : "Oculus"; | |
| 286 | 514 | var data = { |
| 287 | − "action": "user failed to create a profile with Steam from the complete profile screen" | |
| 515 | + "action": "user failed to create a profile with " + action + " from the complete profile screen" | |
| 288 | 516 | } |
| 289 | 517 | UserActivityLogger.logAction("encourageLoginDialog", data); |
| 290 | 518 | } |
| 291 | 519 | } |
| 292 | − | |
| 293 | − bodyLoader.setSource("UsernameCollisionBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "withSteam": completeProfileBody.withSteam }); | |
| 520 | + if (!completeProfileBody.withOculus) { | |
| 521 | + bodyLoader.setSource("UsernameCollisionBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "withSteam": completeProfileBody.withSteam, | |
| 522 | + "withOculus": completeProfileBody.withOculus }); | |
| 523 | + } | |
| 294 | 524 | } |
| 295 | 525 | } |
| 296 | 526 | |
| @@ -302,5 +532,6 @@ Item { · 5 unmodified lines | ||
| 302 | 532 | } |
| 303 | 533 | d.resize(); |
| 304 | 534 | root.text = ""; |
| 535 | + usernameField.forceActiveFocus(); | |
| 305 | 536 | } |
| 306 | 537 | } |
| @@ -36,9 +36,10 @@ Item { · 35 unmodified lines | ||
| 36 | 36 | property bool keyboardRaised: false |
| 37 | 37 | property bool punctuationMode: false |
| 38 | 38 | |
| 39 | − property bool withSteam: false | |
| 39 | + property bool withSteam: withSteam | |
| 40 | 40 | property bool linkSteam: linkSteam |
| 41 | − property bool withOculus: false | |
| 41 | + property bool withOculus: withOculus | |
| 42 | + property bool linkOculus: linkOculus | |
| 42 | 43 | property string errorString: errorString |
| 43 | 44 | property bool lostFocus: false |
| 44 | 45 | |
| @@ -83,23 +84,24 @@ Item { · 38 unmodified lines | ||
| 83 | 84 | } |
| 84 | 85 | UserActivityLogger.logAction("encourageLoginDialog", data); |
| 85 | 86 | } |
| 86 | − | |
| 87 | − bodyLoader.setSource("LoggingInBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "withSteam": linkAccountBody.withSteam, "withOculus": linkAccountBody.withOculus, "linkSteam": linkAccountBody.linkSteam }); | |
| 87 | + bodyLoader.setSource("LoggingInBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "withSteam": linkAccountBody.withSteam, | |
| 88 | + "withOculus": linkAccountBody.withOculus, "linkSteam": linkAccountBody.linkSteam, "linkOculus": linkAccountBody.linkOculus }); | |
| 88 | 89 | } |
| 89 | 90 | |
| 90 | 91 | function init() { |
| 91 | 92 | // going to/from sign in/up dialog. |
| 92 | − loginDialog.isLogIn = true; | |
| 93 | 93 | loginErrorMessage.text = linkAccountBody.errorString; |
| 94 | 94 | loginErrorMessage.visible = (linkAccountBody.errorString !== ""); |
| 95 | − loginButton.text = !linkAccountBody.linkSteam ? "Log In" : "Link Account"; | |
| 95 | + if (loginErrorMessageTextMetrics.width > emailField.width) { | |
| 96 | + loginErrorMessage.wrapMode = Text.WordWrap; | |
| 97 | + errorContainer.height = (loginErrorMessageTextMetrics.width / emailField.width) * loginErrorMessageTextMetrics.height; | |
| 98 | + } | |
| 99 | + loginButton.text = (!linkAccountBody.linkSteam && !linkAccountBody.linkOculus) ? "Log In" : "Link Account"; | |
| 96 | 100 | loginButton.color = hifi.buttons.blue; |
| 97 | 101 | emailField.placeholderText = "Username or Email"; |
| 98 | 102 | var savedUsername = Settings.getValue("keepMeLoggedIn/savedUsername", ""); |
| 99 | 103 | emailField.text = keepMeLoggedInCheckbox.checked ? savedUsername === "Unknown user" ? "" : savedUsername : ""; |
| 100 | − if (linkAccountBody.linkSteam) { | |
| 101 | − steamInfoText.anchors.top = passwordField.bottom; | |
| 102 | − keepMeLoggedInCheckbox.anchors.top = steamInfoText.bottom; | |
| 104 | + if (linkAccountBody.linkSteam || linkAccountBody.linkOculus) { | |
| 103 | 105 | loginButton.width = (passwordField.width - hifi.dimensions.contentSpacing.x) / 2; |
| 104 | 106 | loginButton.anchors.right = emailField.right; |
| 105 | 107 | } else { |
| @@ -125,7 +127,7 @@ Item { · 19 unmodified lines | ||
| 125 | 127 | id: loginContainer |
| 126 | 128 | width: emailField.width |
| 127 | 129 | height: errorContainer.height + emailField.height + passwordField.height + 5.5 * hifi.dimensions.contentSpacing.y + |
| 128 | − keepMeLoggedInCheckbox.height + loginButton.height + cantAccessTextMetrics.height + continueButton.height + steamInfoTextMetrics.height | |
| 130 | + keepMeLoggedInCheckbox.height + loginButton.height + cantAccessTextMetrics.height + continueButton.height | |
| 129 | 131 | anchors { |
| 130 | 132 | top: parent.top |
| 131 | 133 | topMargin: root.bannerHeight + 0.25 * parent.height |
| @@ -135,7 +137,7 @@ Item { · 3 unmodified lines | ||
| 135 | 137 | |
| 136 | 138 | Item { |
| 137 | 139 | id: errorContainer |
| 138 | − width: loginErrorMessageTextMetrics.width | |
| 140 | + width: parent.width | |
| 139 | 141 | height: loginErrorMessageTextMetrics.height |
| 140 | 142 | anchors { |
| 141 | 143 | bottom: emailField.top; |
| @@ -304,7 +306,7 @@ Item { · 162 unmodified lines | ||
| 304 | 306 | fontSize: linkAccountBody.fontSize |
| 305 | 307 | fontBold: linkAccountBody.fontBold |
| 306 | 308 | color: hifi.buttons.noneBorderlessWhite; |
| 307 | − visible: linkAccountBody.linkSteam | |
| 309 | + visible: linkAccountBody.linkSteam || linkAccountBody.linkOculus | |
| 308 | 310 | anchors { |
| 309 | 311 | top: keepMeLoggedInCheckbox.bottom |
| 310 | 312 | topMargin: hifi.dimensions.contentSpacing.y |
| @@ -315,10 +317,9 @@ Item { · 4 unmodified lines | ||
| 315 | 317 | "action": "user clicked cancel at link account screen" |
| 316 | 318 | }; |
| 317 | 319 | UserActivityLogger.logAction("encourageLoginDialog", data); |
| 318 | − loginDialog.dismissLoginDialog(); | |
| 319 | 320 | } |
| 320 | − | |
| 321 | − bodyLoader.setSource("CompleteProfileBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "withSteam": linkAccountBody.withSteam, "errorString": "" }); | |
| 321 | + bodyLoader.setSource("CompleteProfileBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "withSteam": linkAccountBody.withSteam, | |
| 322 | + "withOculus": linkAccountBody.withOculus, "errorString": "" }); | |
| 322 | 323 | } |
| 323 | 324 | } |
| 324 | 325 | HifiControlsUit.Button { |
| @@ -337,33 +338,6 @@ Item { · 12 unmodified lines | ||
| 337 | 338 | linkAccountBody.login(); |
| 338 | 339 | } |
| 339 | 340 | } |
| 340 | − TextMetrics { | |
| 341 | − id: steamInfoTextMetrics | |
| 342 | − font: steamInfoText.font | |
| 343 | − text: steamInfoText.text | |
| 344 | − } | |
| 345 | − Text { | |
| 346 | − id: steamInfoText | |
| 347 | − width: root.bannerWidth | |
| 348 | − visible: linkAccountBody.linkSteam | |
| 349 | − anchors { | |
| 350 | − top: loginButton.bottom | |
| 351 | − topMargin: hifi.dimensions.contentSpacing.y | |
| 352 | − left: emailField.left | |
| 353 | − } | |
| 354 | − | |
| 355 | − font.family: linkAccountBody.fontFamily | |
| 356 | − font.pixelSize: linkAccountBody.textFieldFontSize | |
| 357 | − color: "white" | |
| 358 | − text: qsTr("Your Steam account information will not be exposed to others."); | |
| 359 | − verticalAlignment: Text.AlignVCenter | |
| 360 | − horizontalAlignment: Text.AlignHCenter | |
| 361 | − Component.onCompleted: { | |
| 362 | − if (steamInfoTextMetrics.width > root.bannerWidth) { | |
| 363 | − steamInfoText.wrapMode = Text.WordWrap; | |
| 364 | − } | |
| 365 | − } | |
| 366 | − } | |
| 367 | 341 | TextMetrics { |
| 368 | 342 | id: cantAccessTextMetrics |
| 369 | 343 | font: cantAccessText.font |
| @@ -372,7 +346,7 @@ Item { · 2 unmodified lines | ||
| 372 | 346 | HifiStylesUit.ShortcutText { |
| 373 | 347 | id: cantAccessText |
| 374 | 348 | z: 10 |
| 375 | − visible: !linkAccountBody.linkSteam | |
| 349 | + visible: !linkAccountBody.linkSteam && !linkAccountBody.linkOculus | |
| 376 | 350 | anchors { |
| 377 | 351 | top: loginButton.bottom |
| 378 | 352 | topMargin: hifi.dimensions.contentSpacing.y |
| @@ -423,10 +397,10 @@ Item { · 44 unmodified lines | ||
| 423 | 397 | buttonGlyphSize: 24 |
| 424 | 398 | buttonGlyphRightMargin: 10 |
| 425 | 399 | onClicked: { |
| 426 | − // if (loginDialog.isOculusStoreRunning()) { | |
| 427 | − // linkAccountBody.withOculus = true; | |
| 428 | − // loginDialog.loginThroughSteam(); | |
| 429 | − // } else | |
| 400 | + if (loginDialog.isOculusRunning()) { | |
| 401 | + linkAccountBody.withOculus = true; | |
| 402 | + loginDialog.loginThroughOculus(); | |
| 403 | + } else | |
| 430 | 404 | if (loginDialog.isSteamRunning()) { |
| 431 | 405 | linkAccountBody.withSteam = true; |
| 432 | 406 | loginDialog.loginThroughSteam(); |
| @@ -446,18 +420,17 @@ Item { · 13 unmodified lines | ||
| 446 | 420 | } |
| 447 | 421 | |
| 448 | 422 | bodyLoader.setSource("LoggingInBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, |
| 449 | − "withSteam": linkAccountBody.withSteam, "withOculus": linkAccountBody.withOculus, "linkSteam": linkAccountBody.linkSteam }); | |
| 423 | + "withSteam": linkAccountBody.withSteam, "withOculus": linkAccountBody.withOculus, "linkSteam": linkAccountBody.linkSteam, "linkOculus": linkAccountBody.linkOculus }); | |
| 450 | 424 | } |
| 451 | 425 | Component.onCompleted: { |
| 452 | − if (linkAccountBody.linkSteam) { | |
| 426 | + if (linkAccountBody.linkSteam || linkAccountBody.linkOculus) { | |
| 453 | 427 | continueButton.visible = false; |
| 454 | 428 | return; |
| 455 | 429 | } |
| 456 | − // if (loginDialog.isOculusStoreRunning()) { | |
| 457 | − // continueButton.text = qsTr("CONTINUE WITH OCULUS"); | |
| 458 | − // continueButton.buttonGlyph = hifi.glyphs.oculus; | |
| 459 | − // } else | |
| 460 | − if (loginDialog.isSteamRunning()) { | |
| 430 | + if (loginDialog.isOculusRunning()) { | |
| 431 | + continueButton.text = qsTr("CONTINUE WITH OCULUS"); | |
| 432 | + continueButton.buttonGlyph = hifi.glyphs.oculus; | |
| 433 | + } else if (loginDialog.isSteamRunning()) { | |
| 461 | 434 | continueButton.text = qsTr("CONTINUE WITH STEAM"); |
| 462 | 435 | continueButton.buttonGlyph = hifi.glyphs.steamSquare; |
| 463 | 436 | } else { |
| @@ -470,7 +443,7 @@ Item { · 6 unmodified lines | ||
| 470 | 443 | id: signUpContainer |
| 471 | 444 | width: loginContainer.width |
| 472 | 445 | height: signUpTextMetrics.height |
| 473 | − visible: !linkAccountBody.linkSteam | |
| 446 | + visible: !linkAccountBody.linkSteam && !linkAccountBody.linkOculus | |
| 474 | 447 | anchors { |
| 475 | 448 | left: loginContainer.left |
| 476 | 449 | top: loginContainer.bottom |
| @@ -519,7 +492,7 @@ Item { · 42 unmodified lines | ||
| 519 | 492 | UserActivityLogger.logAction("encourageLoginDialog", data); |
| 520 | 493 | } |
| 521 | 494 | bodyLoader.setSource("SignUpBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, |
| 522 | − "errorString": "", "linkSteam": linkAccountBody.linkSteam }); | |
| 495 | + "errorString": "" }); | |
| 523 | 496 | } |
| 524 | 497 | } |
| 525 | 498 | } |
| @@ -543,7 +516,7 @@ Item { · 17 unmodified lines | ||
| 543 | 516 | fontFamily: linkAccountBody.fontFamily |
| 544 | 517 | fontSize: linkAccountBody.fontSize |
| 545 | 518 | fontBold: linkAccountBody.fontBold |
| 546 | − visible: linkAccountBody.loginDialogPoppedUp && !linkAccountBody.linkSteam; | |
| 519 | + visible: loginDialog.getLoginDialogPoppedUp() && !linkAccountBody.linkSteam && !linkAccountBody.linkOculus; | |
| 547 | 520 | onClicked: { |
| 548 | 521 | if (linkAccountBody.loginDialogPoppedUp) { |
| 549 | 522 | var data = { |
| @@ -29,6 +29,8 @@ Item { · 28 unmodified lines | ||
| 29 | 29 | property bool withSteam: withSteam |
| 30 | 30 | property bool withOculus: withOculus |
| 31 | 31 | property bool linkSteam: linkSteam |
| 32 | + property bool linkOculus: linkOculus | |
| 33 | + property bool createOculus: createOculus | |
| 32 | 34 | |
| 33 | 35 | readonly property bool loginDialogPoppedUp: loginDialog.getLoginDialogPoppedUp() |
| 34 | 36 | |
| @@ -75,15 +77,25 @@ Item { · 40 unmodified lines | ||
| 75 | 77 | } |
| 76 | 78 | } |
| 77 | 79 | |
| 80 | + Timer { | |
| 81 | + id: oculusSuccessTimer | |
| 82 | + interval: 500; | |
| 83 | + running: false; | |
| 84 | + repeat: false; | |
| 85 | + onTriggered: { | |
| 86 | + loginDialog.loginThroughOculus(); | |
| 87 | + init(); | |
| 88 | + } | |
| 89 | + } | |
| 90 | + | |
| 78 | 91 | function init() { |
| 79 | 92 | // For the process of logging in. |
| 80 | 93 | loggingInText.wrapMode = Text.NoWrap; |
| 81 | − | |
| 82 | − if (loggingInBody.linkSteam) { | |
| 94 | + if (loggingInBody.createOculus) { | |
| 95 | + loggingInGlyph.text = hifi.glyphs.oculus; | |
| 83 | 96 | loggingInGlyph.visible = true; |
| 84 | − loggingInText.text = "Linking to Steam"; | |
| 97 | + loggingInText.text = "Creating account with Oculus"; | |
| 85 | 98 | loggingInText.x = loggingInHeader.width/2 - loggingInTextMetrics.width/2 + loggingInGlyphTextMetrics.width/2; |
| 86 | − loginDialog.linkSteam(); | |
| 87 | 99 | } else if (loggingInBody.withSteam) { |
| 88 | 100 | loggingInGlyph.visible = true; |
| 89 | 101 | loggingInText.text = "Logging in to Steam"; |
| @@ -100,12 +112,18 @@ Item { · 10 unmodified lines | ||
| 100 | 112 | loggingInSpinner.visible = true; |
| 101 | 113 | } |
| 102 | 114 | function loadingSuccess() { |
| 103 | − loggingInSpinner.visible = false; | |
| 104 | 115 | if (loggingInBody.linkSteam) { |
| 105 | 116 | loggingInText.text = "Linking to Steam"; |
| 117 | + loggingInText.x = loggingInHeader.width/2 - loggingInTextMetrics.width/2 + loggingInGlyphTextMetrics.width/2; | |
| 106 | 118 | loginDialog.linkSteam(); |
| 107 | 119 | return; |
| 120 | + } else if (loggingInBody.linkOculus) { | |
| 121 | + loggingInText.text = "Linking to Oculus"; | |
| 122 | + loggingInText.x = loggingInHeader.width/2 - loggingInTextMetrics.width/2 + loggingInGlyphTextMetrics.width/2; | |
| 123 | + loginDialog.linkOculus(); | |
| 124 | + return; | |
| 108 | 125 | } |
| 126 | + loggingInSpinner.visible = false; | |
| 109 | 127 | if (loggingInBody.withSteam) { |
| 110 | 128 | // reset the flag. |
| 111 | 129 | loggingInGlyph.visible = false; |
| @@ -246,6 +264,26 @@ Item { · 134 unmodified lines | ||
| 246 | 264 | verticalAlignment: Text.AlignVCenter; |
| 247 | 265 | visible: false; |
| 248 | 266 | } |
| 267 | + HifiControlsUit.Button { | |
| 268 | + id: okButton; | |
| 269 | + width: d.minWidthButton | |
| 270 | + height: d.minHeightButton | |
| 271 | + text: qsTr("OK") | |
| 272 | + color: hifi.buttons.white | |
| 273 | + anchors { | |
| 274 | + top: loggedInGlyph.bottom | |
| 275 | + topMargin: 3 * hifi.dimensions.contentSpacing.y | |
| 276 | + left: parent.left | |
| 277 | + leftMargin: (parent.width - width) / 2; | |
| 278 | + } | |
| 279 | + onClicked: { | |
| 280 | + root.tryDestroy(); | |
| 281 | + if (loginDialog.getLoginDialogPoppedUp()) { | |
| 282 | + loginDialog.dismissLoginDialog(); | |
| 283 | + } | |
| 284 | + } | |
| 285 | + visible: false | |
| 286 | + } | |
| 249 | 287 | } |
| 250 | 288 | } |
| 251 | 289 | } |
| @@ -257,6 +295,34 @@ Item { · 5 unmodified lines | ||
| 257 | 295 | |
| 258 | 296 | Connections { |
| 259 | 297 | target: loginDialog |
| 298 | + onHandleCreateCompleted: { | |
| 299 | + console.log("Create Succeeded") | |
| 300 | + if (loggingInBody.withOculus) { | |
| 301 | + if (loggingInBody.loginDialogPoppedUp) { | |
| 302 | + var data = { | |
| 303 | + "action": "user created Oculus account successfully" | |
| 304 | + }; | |
| 305 | + UserActivityLogger.logAction("encourageLoginDialog", data); | |
| 306 | + } | |
| 307 | + loggingInBody.createOculus = false; | |
| 308 | + loggingInText.text = "Account created!"; | |
| 309 | + loggingInText.x = loggingInHeader.width/2 - loggingInTextMetrics.width/2 + loggingInGlyphTextMetrics.width/2; | |
| 310 | + oculusSuccessTimer.start(); | |
| 311 | + } | |
| 312 | + } | |
| 313 | + onHandleCreateFailed: { | |
| 314 | + console.log("Create Failed: " + error); | |
| 315 | + if (loggingInBody.withOculus) { | |
| 316 | + if (loggingInBody.loginDialogPoppedUp) { | |
| 317 | + var data = { | |
| 318 | + "action": "user created Oculus account unsuccessfully" | |
| 319 | + }; | |
| 320 | + UserActivityLogger.logAction("encourageLoginDialog", data); | |
| 321 | + } | |
| 322 | + bodyLoader.setSource("CompleteProfileBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "withSteam": loggingInBody.withSteam, | |
| 323 | + "withOculus": loggingInBody.withOculus, "errorString": error }); | |
| 324 | + } | |
| 325 | + } | |
| 260 | 326 | onHandleLinkCompleted: { |
| 261 | 327 | console.log("Link Succeeded"); |
| 262 | 328 | if (loggingInBody.linkSteam) { |
| @@ -267,21 +333,40 @@ Item { · 4 unmodified lines | ||
| 267 | 333 | }; |
| 268 | 334 | UserActivityLogger.logAction("encourageLoginDialog", data); |
| 269 | 335 | } |
| 270 | − | |
| 271 | − loggingInBody.loadingSuccess(); | |
| 336 | + } else if (loggingInBody.linkOculus) { | |
| 337 | + loggingInBody.linkOculus = false; | |
| 338 | + if (loggingInBody.loginDialogPoppedUp) { | |
| 339 | + var data = { | |
| 340 | + "action": "user linked Oculus with their hifi account credentials successfully" | |
| 341 | + }; | |
| 342 | + UserActivityLogger.logAction("encourageLoginDialog", data); | |
| 343 | + } | |
| 272 | 344 | } |
| 345 | + loggingInBody.loadingSuccess(); | |
| 273 | 346 | } |
| 274 | 347 | onHandleLinkFailed: { |
| 275 | 348 | console.log("Link Failed: " + error); |
| 276 | − if (loggingInBody.linkSteam) { | |
| 349 | + loggingInSpinner.visible = false; | |
| 350 | + if (loggingInBody.linkOculus) { | |
| 351 | + loggingInText.text = "Oculus failed to link"; | |
| 352 | + if (loggingInBody.loginDialogPoppedUp) { | |
| 353 | + var data = { | |
| 354 | + "action": "user linked Oculus unsuccessfully" | |
| 355 | + }; | |
| 356 | + UserActivityLogger.logAction("encourageLoginDialog", data); | |
| 357 | + } | |
| 358 | + okButton.visible = true; | |
| 359 | + } else if (loggingInBody.linkSteam){ | |
| 277 | 360 | if (loggingInBody.loginDialogPoppedUp) { |
| 278 | 361 | var data = { |
| 279 | 362 | "action": "user linked Steam unsuccessfully" |
| 280 | 363 | }; |
| 281 | 364 | UserActivityLogger.logAction("encourageLoginDialog", data); |
| 282 | 365 | } |
| 366 | + } else { | |
| 367 | + bodyLoader.setSource("LinkAccountBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "linkSteam": loggingInBody.linkSteam, | |
| 368 | + "linkOculus": loggingInBody.linkOculus, "errorString": error }); | |
| 283 | 369 | } |
| 284 | − bodyLoader.setSource("LinkAccountBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "linkSteam": true, "errorString": error }); | |
| 285 | 370 | } |
| 286 | 371 | |
| 287 | 372 | onHandleLoginCompleted: { |
| @@ -292,8 +377,19 @@ Item { · 4 unmodified lines | ||
| 292 | 377 | onHandleLoginFailed: { |
| 293 | 378 | console.log("Login Failed") |
| 294 | 379 | loggingInSpinner.visible = false; |
| 380 | + loggingInGlyph.visible = false; | |
| 295 | 381 | var errorString = ""; |
| 296 | − if (loggingInBody.linkSteam && loggingInBody.withSteam) { | |
| 382 | + if (loggingInBody.linkOculus && loggingInBody.withOculus) { | |
| 383 | + errorString = "Username or password is incorrect."; | |
| 384 | + if (loggingInBody.loginDialogPoppedUp) { | |
| 385 | + var data = { | |
| 386 | + "action": "user failed to link Oculus with their hifi account credentials" | |
| 387 | + }; | |
| 388 | + UserActivityLogger.logAction("encourageLoginDialog", data); | |
| 389 | + } | |
| 390 | + bodyLoader.setSource("LinkAccountBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "withSteam": loggingInBody.withSteam, | |
| 391 | + "withOculus": loggingInBody.withOculus, "linkSteam": loggingInBody.linkSteam, "linkOculus": loggingInBody.linkOculus, "errorString": errorString }); | |
| 392 | + } else if (loggingInBody.linkSteam && loggingInBody.withSteam) { | |
| 297 | 393 | errorString = "Username or password is incorrect."; |
| 298 | 394 | if (loggingInBody.loginDialogPoppedUp) { |
| 299 | 395 | var data = { |
| @@ -301,9 +397,9 @@ Item { · 1 unmodified line | ||
| 301 | 397 | }; |
| 302 | 398 | UserActivityLogger.logAction("encourageLoginDialog", data); |
| 303 | 399 | } |
| 304 | − bodyLoader.setSource("LinkAccountBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "withSteam": loggingInBody.withSteam, "linkSteam": loggingInBody.linkSteam, "errorString": errorString }); | |
| 400 | + bodyLoader.setSource("LinkAccountBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "withSteam": loggingInBody.withSteam, | |
| 401 | + "withOculus": loggingInBody.withOculus, "linkSteam": loggingInBody.linkSteam, "linkOculus": loggingInBody.linkOculus, "errorString": errorString }); | |
| 305 | 402 | } else if (loggingInBody.withSteam) { |
| 306 | − loggingInGlyph.visible = false; | |
| 307 | 403 | errorString = "Your Steam authentication has failed. Please make sure you are logged into Steam and try again."; |
| 308 | 404 | if (loggingInBody.loginDialogPoppedUp) { |
| 309 | 405 | var data = { |
| @@ -311,19 +407,19 @@ Item { · 1 unmodified line | ||
| 311 | 407 | }; |
| 312 | 408 | UserActivityLogger.logAction("encourageLoginDialog", data); |
| 313 | 409 | } |
| 314 | − bodyLoader.setSource("CompleteProfileBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "withSteam": loggingInBody.withSteam, "errorString": errorString }); | |
| 410 | + bodyLoader.setSource("CompleteProfileBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "withSteam": loggingInBody.withSteam, | |
| 411 | + "withOculus": loggingInBody.withOculus, "linkSteam": loggingInBody.linkSteam, "linkOculus": loggingInBody.linkOculus, "errorString": errorString }); | |
| 315 | 412 | } else if (loggingInBody.withOculus) { |
| 316 | − loggingInGlyph.visible = false; | |
| 317 | − errorString = "Your Oculus authentication has failed. Please make sure you are logged into Oculus and try again." | |
| 413 | + errorString = "Your Oculus account is not connected to an existing High Fidelity account. Please create a new one." | |
| 318 | 414 | if (loggingInBody.loginDialogPoppedUp) { |
| 319 | 415 | var data = { |
| 320 | 416 | "action": "user failed to authenticate with Oculus to log in" |
| 321 | 417 | }; |
| 322 | 418 | UserActivityLogger.logAction("encourageLoginDialog", data); |
| 323 | 419 | } |
| 324 | − bodyLoader.setSource("LinkAccountBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "errorString": errorString }); | |
| 325 | − } | |
| 326 | − else { | |
| 420 | + bodyLoader.setSource("CompleteProfileBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "withSteam": loggingInBody.withSteam, | |
| 421 | + "withOculus": loggingInBody.withOculus, "linkSteam": loggingInBody.linkSteam, "linkOculus": loggingInBody.linkOculus, "errorString": errorString }); | |
| 422 | + } else { | |
| 327 | 423 | errorString = "Username or password is incorrect."; |
| 328 | 424 | if (loggingInBody.loginDialogPoppedUp) { |
| 329 | 425 | var data = { |
| @@ -23,6 +23,7 @@ Item { · 22 unmodified lines | ||
| 23 | 23 | clip: true |
| 24 | 24 | height: root.height |
| 25 | 25 | width: root.width |
| 26 | + readonly property string termsContainerText: qsTr("By signing up, you agree to High Fidelity's Terms of Service") | |
| 26 | 27 | property int textFieldHeight: 31 |
| 27 | 28 | property string fontFamily: "Raleway" |
| 28 | 29 | property int fontSize: 15 |
| @@ -37,7 +38,6 @@ Item { · 8 unmodified lines | ||
| 37 | 38 | onKeyboardRaisedChanged: d.resize(); |
| 38 | 39 | |
| 39 | 40 | property string errorString: errorString |
| 40 | − property bool linkSteam: linkSteam | |
| 41 | 41 | property bool lostFocus: false |
| 42 | 42 | |
| 43 | 43 | readonly property bool loginDialogPoppedUp: loginDialog.getLoginDialogPoppedUp() |
| @@ -73,7 +73,6 @@ Item { · 29 unmodified lines | ||
| 73 | 73 | |
| 74 | 74 | function init() { |
| 75 | 75 | // going to/from sign in/up dialog. |
| 76 | − loginDialog.isLogIn = false; | |
| 77 | 76 | emailField.placeholderText = "Email"; |
| 78 | 77 | emailField.text = ""; |
| 79 | 78 | emailField.anchors.top = usernameField.bottom; |
| @@ -353,7 +352,7 @@ Item { · 273 unmodified lines | ||
| 353 | 352 | } |
| 354 | 353 | UserActivityLogger.logAction("encourageLoginDialog", data); |
| 355 | 354 | } |
| 356 | − bodyLoader.setSource("LinkAccountBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "linkSteam": signUpBody.linkSteam }); | |
| 355 | + bodyLoader.setSource("LinkAccountBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "linkSteam": false }); | |
| 357 | 356 | } |
| 358 | 357 | } |
| 359 | 358 | HifiControlsUit.Button { |
| @@ -380,6 +379,54 @@ Item { · 20 unmodified lines | ||
| 380 | 379 | signUpBody.signup(); |
| 381 | 380 | } |
| 382 | 381 | } |
| 382 | + Item { | |
| 383 | + id: termsContainer | |
| 384 | + width: parent.width | |
| 385 | + height: termsTextMetrics.height | |
| 386 | + anchors { | |
| 387 | + top: signUpButton.bottom | |
| 388 | + horizontalCenter: parent.horizontalCenter | |
| 389 | + topMargin: 2 * hifi.dimensions.contentSpacing.y | |
| 390 | + left: parent.left | |
| 391 | + } | |
| 392 | + TextMetrics { | |
| 393 | + id: termsTextMetrics | |
| 394 | + font: termsText.font | |
| 395 | + text: signUpBody.termsContainerText | |
| 396 | + Component.onCompleted: { | |
| 397 | + // with the link. | |
| 398 | + termsText.text = qsTr("By signing up, you agree to <a href='https://highfidelity.com/terms'>High Fidelity's Terms of Service</a>") | |
| 399 | + } | |
| 400 | + } | |
| 401 | + | |
| 402 | + HifiStylesUit.InfoItem { | |
| 403 | + id: termsText | |
| 404 | + text: signUpBody.termsContainerText | |
| 405 | + font.family: signUpBody.fontFamily | |
| 406 | + font.pixelSize: signUpBody.fontSize | |
| 407 | + font.bold: signUpBody.fontBold | |
| 408 | + wrapMode: Text.WordWrap | |
| 409 | + color: hifi.colors.white | |
| 410 | + linkColor: hifi.colors.blueAccent | |
| 411 | + lineHeight: 1 | |
| 412 | + lineHeightMode: Text.ProportionalHeight | |
| 413 | + | |
| 414 | + onLinkActivated: loginDialog.openUrl(link); | |
| 415 | + | |
| 416 | + Component.onCompleted: { | |
| 417 | + if (termsTextMetrics.width > root.bannerWidth) { | |
| 418 | + termsText.width = root.bannerWidth; | |
| 419 | + termsText.wrapMode = Text.WordWrap; | |
| 420 | + additionalText.verticalAlignment = Text.AlignLeft; | |
| 421 | + additionalText.horizontalAlignment = Text.AlignLeft; | |
| 422 | + termsContainer.height = (termsTextMetrics.width / root.bannerWidth) * termsTextMetrics.height; | |
| 423 | + termsContainer.anchors.left = buttons.left; | |
| 424 | + } else { | |
| 425 | + termsText.anchors.centerIn = termsContainer; | |
| 426 | + } | |
| 427 | + } | |
| 428 | + } | |
| 429 | + } | |
| 383 | 430 | } |
| 384 | 431 | } |
| 385 | 432 | |
| @@ -433,14 +480,15 @@ Item { · 47 unmodified lines | ||
| 433 | 480 | |
| 434 | 481 | if (errorString !== "") { |
| 435 | 482 | loginErrorMessage.visible = true; |
| 483 | + var errorLength = errorString.split(/\r\n|\r|\n/).length; | |
| 436 | 484 | var errorStringEdited = errorString.replace(/[\n\r]+/g, "\n"); |
| 437 | 485 | loginErrorMessage.text = errorStringEdited; |
| 438 | − loginErrorMessageTextMetrics.text = errorString; | |
| 439 | − if (loginErrorMessageTextMetrics.width > usernameField.width) { | |
| 486 | + if (errorLength > 1.0) { | |
| 487 | + loginErrorMessage.width = root.bannerWidth; | |
| 440 | 488 | loginErrorMessage.wrapMode = Text.WordWrap; |
| 441 | 489 | loginErrorMessage.verticalAlignment = Text.AlignLeft; |
| 442 | 490 | loginErrorMessage.horizontalAlignment = Text.AlignLeft; |
| 443 | − errorContainer.height = (loginErrorMessageTextMetrics.width / usernameField.width) * loginErrorMessageTextMetrics.height; | |
| 491 | + errorContainer.height = errorLength * loginErrorMessageTextMetrics.height; | |
| 444 | 492 | } |
| 445 | 493 | errorContainer.anchors.bottom = usernameField.top; |
| 446 | 494 | errorContainer.anchors.bottomMargin = hifi.dimensions.contentSpacing.y; |
| @@ -19,6 +19,7 @@ import TabletScriptingInterface 1.0 · 18 unmodified lines | ||
| 19 | 19 | Item { |
| 20 | 20 | id: usernameCollisionBody |
| 21 | 21 | clip: true |
| 22 | + readonly property string termsContainerText: qsTr("By creating this user profile, you agree to High Fidelity's Terms of Service") | |
| 22 | 23 | width: root.width |
| 23 | 24 | height: root.height |
| 24 | 25 | readonly property string fontFamily: "Raleway" |
| @@ -26,13 +27,18 @@ Item { · 1 unmodified line | ||
| 26 | 27 | readonly property int textFieldFontSize: 18 |
| 27 | 28 | readonly property bool fontBold: true |
| 28 | 29 | |
| 29 | − readonly property bool withSteam: withSteam | |
| 30 | + property bool withSteam: withSteam | |
| 31 | + property bool withOculus: withOculus | |
| 30 | 32 | |
| 31 | 33 | readonly property bool loginDialogPoppedUp: loginDialog.getLoginDialogPoppedUp() |
| 32 | 34 | |
| 33 | 35 | function create() { |
| 34 | 36 | mainTextContainer.visible = false |
| 35 | − loginDialog.createAccountFromSteam(textField.text); | |
| 37 | + if (usernameCollisionBody.withOculus) { | |
| 38 | + loginDialog.createAccountFromOculus(textField.text); | |
| 39 | + } else if (usernameCollisionBody.withSteam) { | |
| 40 | + loginDialog.createAccountFromSteam(textField.text); | |
| 41 | + } | |
| 36 | 42 | } |
| 37 | 43 | |
| 38 | 44 | property bool keyboardEnabled: false |
| @@ -90,12 +96,19 @@ Item { · 51 unmodified lines | ||
| 90 | 96 | font.family: usernameCollisionBody.fontFamily |
| 91 | 97 | font.pixelSize: usernameCollisionBody.fontSize |
| 92 | 98 | font.bold: usernameCollisionBody.fontBold |
| 93 | − text: qsTr("Your Steam username is not available."); | |
| 99 | + text: qsTr(""); | |
| 94 | 100 | wrapMode: Text.WordWrap |
| 95 | 101 | color: hifi.colors.redAccent |
| 96 | 102 | lineHeight: 1 |
| 97 | 103 | lineHeightMode: Text.ProportionalHeight |
| 98 | 104 | horizontalAlignment: Text.AlignHCenter |
| 105 | + Component.onCompleted: { | |
| 106 | + if (usernameCollisionBody.withOculus) { | |
| 107 | + text = qsTr("Your Oculus username is not available."); | |
| 108 | + } else if (usernameCollisionBody.withSteam) { | |
| 109 | + text = qsTr("Your Steam username is not available."); | |
| 110 | + } | |
| 111 | + } | |
| 99 | 112 | } |
| 100 | 113 | |
| 101 | 114 | |
| @@ -164,7 +177,8 @@ Item { · 62 unmodified lines | ||
| 164 | 177 | fontSize: usernameCollisionBody.fontSize |
| 165 | 178 | fontBold: usernameCollisionBody.fontBold |
| 166 | 179 | onClicked: { |
| 167 | − bodyLoader.setSource("CompleteProfileBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "errorString": "" }); | |
| 180 | + bodyLoader.setSource("CompleteProfileBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "withSteam": usernameCollisionBody.withSteam, | |
| 181 | + "withOculus": usernameCollisionBody.withOculus, "errorString": "" }); | |
| 168 | 182 | } |
| 169 | 183 | } |
| 170 | 184 | HifiControlsUit.Button { |
| @@ -187,6 +201,55 @@ Item { · 16 unmodified lines | ||
| 187 | 201 | } |
| 188 | 202 | } |
| 189 | 203 | } |
| 204 | + Item { | |
| 205 | + id: termsContainer | |
| 206 | + width: parent.width | |
| 207 | + height: termsTextMetrics.height | |
| 208 | + anchors { | |
| 209 | + top: buttons.bottom | |
| 210 | + horizontalCenter: parent.horizontalCenter | |
| 211 | + topMargin: 2 * hifi.dimensions.contentSpacing.y | |
| 212 | + left: parent.left | |
| 213 | + leftMargin: (parent.width - buttons.width) / 2 | |
| 214 | + } | |
| 215 | + TextMetrics { | |
| 216 | + id: termsTextMetrics | |
| 217 | + font: termsText.font | |
| 218 | + text: usernameCollisionBody.termsContainerText | |
| 219 | + Component.onCompleted: { | |
| 220 | + // with the link. | |
| 221 | + termsText.text = qsTr("By creating this user profile, you agree to <a href='https://highfidelity.com/terms'>High Fidelity's Terms of Service</a>") | |
| 222 | + } | |
| 223 | + } | |
| 224 | + | |
| 225 | + HifiStylesUit.InfoItem { | |
| 226 | + id: termsText | |
| 227 | + text: usernameCollisionBody.termsContainerText | |
| 228 | + font.family: usernameCollisionBody.fontFamily | |
| 229 | + font.pixelSize: usernameCollisionBody.fontSize | |
| 230 | + font.bold: usernameCollisionBody.fontBold | |
| 231 | + wrapMode: Text.WordWrap | |
| 232 | + color: hifi.colors.white | |
| 233 | + linkColor: hifi.colors.blueAccent | |
| 234 | + lineHeight: 1 | |
| 235 | + lineHeightMode: Text.ProportionalHeight | |
| 236 | + | |
| 237 | + onLinkActivated: loginDialog.openUrl(link); | |
| 238 | + | |
| 239 | + Component.onCompleted: { | |
| 240 | + if (termsTextMetrics.width > root.bannerWidth) { | |
| 241 | + termsText.width = root.bannerWidth; | |
| 242 | + termsText.wrapMode = Text.WordWrap; | |
| 243 | + additionalText.verticalAlignment = Text.AlignLeft; | |
| 244 | + additionalText.horizontalAlignment = Text.AlignLeft; | |
| 245 | + termsContainer.height = (termsTextMetrics.width / root.bannerWidth) * termsTextMetrics.height; | |
| 246 | + termsContainer.anchors.left = buttons.left; | |
| 247 | + } else { | |
| 248 | + termsText.anchors.centerIn = termsContainer; | |
| 249 | + } | |
| 250 | + } | |
| 251 | + } | |
| 252 | + } | |
| 190 | 253 | } |
| 191 | 254 | |
| 192 | 255 | Component.onCompleted: { |
| @@ -201,18 +264,25 @@ Item { · 8 unmodified lines | ||
| 201 | 264 | target: loginDialog |
| 202 | 265 | onHandleCreateCompleted: { |
| 203 | 266 | console.log("Create Succeeded"); |
| 204 | − if (usernameCollisionBody.withSteam) { | |
| 267 | + if (usernameCollisionBody.withOculus) { | |
| 268 | + if (usernameCollisionBody.loginDialogPoppedUp) { | |
| 269 | + var data = { | |
| 270 | + "action": "user created a profile with Oculus successfully in the username collision screen" | |
| 271 | + } | |
| 272 | + UserActivityLogger.logAction("encourageLoginDialog", data); | |
| 273 | + } | |
| 274 | + loginDialog.loginThroughOculus(); | |
| 275 | + } else if (usernameCollisionBody.withSteam) { | |
| 205 | 276 | if (usernameCollisionBody.loginDialogPoppedUp) { |
| 206 | 277 | var data = { |
| 207 | 278 | "action": "user created a profile with Steam successfully in the username collision screen" |
| 208 | 279 | } |
| 209 | 280 | UserActivityLogger.logAction("encourageLoginDialog", data); |
| 210 | 281 | } |
| 211 | − | |
| 212 | 282 | loginDialog.loginThroughSteam(); |
| 213 | 283 | } |
| 214 | − | |
| 215 | − bodyLoader.setSource("LoggingInBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "withSteam": usernameCollisionBody.withSteam, "linkSteam": false }) | |
| 284 | + bodyLoader.setSource("LoggingInBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "withSteam": usernameCollisionBody.withSteam, | |
| 285 | + "withOculus": usernameCollisionBody.withOculus, "linkSteam": false, "linkOculus": false }) | |
| 216 | 286 | } |
| 217 | 287 | onHandleCreateFailed: { |
| 218 | 288 | console.log("Create Failed: " + error) |
| @@ -150,6 +150,6 @@ FocusScope { · 149 unmodified lines | ||
| 150 | 150 | |
| 151 | 151 | Component.onCompleted: { |
| 152 | 152 | keyboardTimer.start(); |
| 153 | − bodyLoader.setSource("LoginDialog/LinkAccountBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "linkSteam": false }); | |
| 153 | + bodyLoader.setSource("LoginDialog/LinkAccountBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "linkSteam": false, "linkOculus": false }); | |
| 154 | 154 | } |
| 155 | 155 | } |
| @@ -14,6 +14,8 @@ import QtQuick 2.5 · 13 unmodified lines | ||
| 14 | 14 | import controlsUit 1.0 as HifiControlsUit |
| 15 | 15 | import stylesUit 1.0 as HifiStylesUit |
| 16 | 16 | |
| 17 | +import TabletScriptingInterface 1.0 | |
| 18 | + | |
| 17 | 19 | import "../LoginDialog" |
| 18 | 20 | |
| 19 | 21 | FocusScope { |
| @@ -25,10 +27,9 @@ FocusScope { · 5 unmodified lines | ||
| 25 | 27 | width: parent.width |
| 26 | 28 | height: parent.height |
| 27 | 29 | |
| 28 | − signal sendToScript(var message); | |
| 29 | − signal canceled(); | |
| 30 | + property var tabletProxy: Tablet.getTablet("com.highfidelity.interface.tablet.system"); | |
| 30 | 31 | |
| 31 | − property bool isHMD: false | |
| 32 | + property bool isHMD: HMD.active | |
| 32 | 33 | property bool gotoPreviousApp: false; |
| 33 | 34 | |
| 34 | 35 | property bool keyboardEnabled: false |
| @@ -52,6 +53,7 @@ FocusScope { · 17 unmodified lines | ||
| 52 | 53 | } |
| 53 | 54 | |
| 54 | 55 | function tryDestroy() { |
| 56 | + tabletProxy.gotoHomeScreen(); | |
| 55 | 57 | } |
| 56 | 58 | |
| 57 | 59 | MouseArea { |
| @@ -76,7 +78,7 @@ FocusScope { · 18 unmodified lines | ||
| 76 | 78 | interval: 200 |
| 77 | 79 | |
| 78 | 80 | onTriggered: { |
| 79 | − if (MenuInterface.isOptionChecked("Use 3D Keyboard")) { | |
| 81 | + if (MenuInterface.isOptionChecked("Use 3D Keyboard") && root.isHMD) { | |
| 80 | 82 | KeyboardScriptingInterface.raised = true; |
| 81 | 83 | } |
| 82 | 84 | } |
| @@ -169,11 +171,13 @@ FocusScope { · 86 unmodified lines | ||
| 169 | 171 | |
| 170 | 172 | Component.onDestruction: { |
| 171 | 173 | loginKeyboard.raised = false; |
| 172 | − KeyboardScriptingInterface.raised = false; | |
| 174 | + if (root.isHMD) { | |
| 175 | + KeyboardScriptingInterface.raised = false; | |
| 176 | + } | |
| 173 | 177 | } |
| 174 | 178 | |
| 175 | 179 | Component.onCompleted: { |
| 176 | 180 | keyboardTimer.start(); |
| 177 | − bodyLoader.setSource("../LoginDialog/LinkAccountBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "linkSteam": false }); | |
| 181 | + bodyLoader.setSource("../LoginDialog/LinkAccountBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "linkSteam": false, "linkOculus": false }); | |
| 178 | 182 | } |
| 179 | 183 | } |
| @@ -120,6 +120,7 @@ · 119 unmodified lines | ||
| 120 | 120 | #include <plugins/PluginManager.h> |
| 121 | 121 | #include <plugins/PluginUtils.h> |
| 122 | 122 | #include <plugins/SteamClientPlugin.h> |
| 123 | +#include <plugins/OculusPlatformPlugin.h> | |
| 123 | 124 | #include <plugins/InputConfiguration.h> |
| 124 | 125 | #include <RecordingScriptingInterface.h> |
| 125 | 126 | #include <render/EngineStats.h> |
| @@ -800,7 +801,6 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) { · 674 unmodified lines | ||
| 800 | 801 | if (auto steamClient = pluginManager->getSteamClientPlugin()) { |
| 801 | 802 | steamClient->init(); |
| 802 | 803 | } |
| 803 | − | |
| 804 | 804 | PROFILE_SET_THREAD_NAME("Main Thread"); |
| 805 | 805 | |
| 806 | 806 | #if defined(Q_OS_WIN) |
| @@ -2737,6 +2737,7 @@ Application::~Application() { · 1930 unmodified lines | ||
| 2737 | 2737 | if (auto steamClient = PluginManager::getInstance()->getSteamClientPlugin()) { |
| 2738 | 2738 | steamClient->shutdown(); |
| 2739 | 2739 | } |
| 2740 | + | |
| 2740 | 2741 | DependencyManager::destroy<PluginManager>(); |
| 2741 | 2742 | |
| 2742 | 2743 | DependencyManager::destroy<CompositorHelper>(); // must be destroyed before the FramebufferCache |
| @@ -4873,6 +4874,10 @@ void Application::idle() { · 2130 unmodified lines | ||
| 4873 | 4874 | steamClient->runCallbacks(); |
| 4874 | 4875 | } |
| 4875 | 4876 | |
| 4877 | + if (auto oculusPlugin = PluginManager::getInstance()->getOculusPlatformPlugin()) { | |
| 4878 | + oculusPlugin->handleOVREvents(); | |
| 4879 | + } | |
| 4880 | + | |
| 4876 | 4881 | float secondsSinceLastUpdate = (float)_lastTimeUpdated.nsecsElapsed() / NSECS_PER_MSEC / MSECS_PER_SECOND; |
| 4877 | 4882 | _lastTimeUpdated.start(); |
| 4878 | 4883 | |
| @@ -18,6 +18,7 @@ · 17 unmodified lines | ||
| 18 | 18 | |
| 19 | 19 | #include <plugins/PluginManager.h> |
| 20 | 20 | #include <plugins/SteamClientPlugin.h> |
| 21 | +#include <plugins/OculusPlatformPlugin.h> | |
| 21 | 22 | #include <shared/GlobalAppProperties.h> |
| 22 | 23 | #include <ui/TabletScriptingInterface.h> |
| 23 | 24 | #include <UserActivityLogger.h> |
| @@ -109,8 +110,16 @@ bool LoginDialog::isSteamRunning() const { · 85 unmodified lines | ||
| 109 | 110 | return steamClient && steamClient->isRunning(); |
| 110 | 111 | } |
| 111 | 112 | |
| 112 | −bool LoginDialog::isOculusStoreRunning() const { | |
| 113 | − return qApp->property(hifi::properties::OCULUS_STORE).toBool(); | |
| 113 | +bool LoginDialog::isOculusRunning() const { | |
| 114 | + auto oculusPlatformPlugin = PluginManager::getInstance()->getOculusPlatformPlugin(); | |
| 115 | + return (oculusPlatformPlugin && oculusPlatformPlugin->isRunning()); | |
| 116 | +} | |
| 117 | + | |
| 118 | +QString LoginDialog::oculusUserID() const { | |
| 119 | + if (auto oculusPlatformPlugin = PluginManager::getInstance()->getOculusPlatformPlugin()) { | |
| 120 | + return oculusPlatformPlugin->getOculusUserID(); | |
| 121 | + } | |
| 122 | + return ""; | |
| 114 | 123 | } |
| 115 | 124 | |
| 116 | 125 | void LoginDialog::dismissLoginDialog() { |
| @@ -126,6 +135,79 @@ void LoginDialog::login(const QString& username, const QString& password) const · 9 unmodified lines | ||
| 126 | 135 | DependencyManager::get<AccountManager>()->requestAccessToken(username, password); |
| 127 | 136 | } |
| 128 | 137 | |
| 138 | +void LoginDialog::loginThroughOculus() { | |
| 139 | + qDebug() << "Attempting to login through Oculus"; | |
| 140 | + if (auto oculusPlatformPlugin = PluginManager::getInstance()->getOculusPlatformPlugin()) { | |
| 141 | + oculusPlatformPlugin->requestNonceAndUserID([this] (QString nonce, QString oculusID) { | |
| 142 | + DependencyManager::get<AccountManager>()->requestAccessTokenWithOculus(nonce, oculusID); | |
| 143 | + }); | |
| 144 | + } | |
| 145 | +} | |
| 146 | + | |
| 147 | +void LoginDialog::linkOculus() { | |
| 148 | + qDebug() << "Attempting to link Oculus account"; | |
| 149 | + if (auto oculusPlatformPlugin = PluginManager::getInstance()->getOculusPlatformPlugin()) { | |
| 150 | + oculusPlatformPlugin->requestNonceAndUserID([this] (QString nonce, QString oculusID) { | |
| 151 | + if (nonce.isEmpty() || oculusID.isEmpty()) { | |
| 152 | + emit handleLoginFailed(); | |
| 153 | + return; | |
| 154 | + } | |
| 155 | + | |
| 156 | + JSONCallbackParameters callbackParams; | |
| 157 | + callbackParams.callbackReceiver = this; | |
| 158 | + callbackParams.jsonCallbackMethod = "linkCompleted"; | |
| 159 | + callbackParams.errorCallbackMethod = "linkFailed"; | |
| 160 | + const QString LINK_OCULUS_PATH = "api/v1/user/oculus/link"; | |
| 161 | + | |
| 162 | + QJsonObject payload; | |
| 163 | + payload["oculus_nonce"] = nonce; | |
| 164 | + payload["oculus_id"] = oculusID; | |
| 165 | + | |
| 166 | + auto accountManager = DependencyManager::get<AccountManager>(); | |
| 167 | + accountManager->sendRequest(LINK_OCULUS_PATH, AccountManagerAuth::Required, | |
| 168 | + QNetworkAccessManager::PostOperation, callbackParams, | |
| 169 | + QJsonDocument(payload).toJson()); | |
| 170 | + }); | |
| 171 | + } | |
| 172 | +} | |
| 173 | + | |
| 174 | +void LoginDialog::createAccountFromOculus(QString email, QString username, QString password) { | |
| 175 | + qDebug() << "Attempting to create account from Oculus info"; | |
| 176 | + if (auto oculusPlatformPlugin = PluginManager::getInstance()->getOculusPlatformPlugin()) { | |
| 177 | + oculusPlatformPlugin->requestNonceAndUserID([this, email, username, password] (QString nonce, QString oculusID) { | |
| 178 | + if (nonce.isEmpty() || oculusID.isEmpty()) { | |
| 179 | + emit handleLoginFailed(); | |
| 180 | + return; | |
| 181 | + } | |
| 182 | + | |
| 183 | + JSONCallbackParameters callbackParams; | |
| 184 | + callbackParams.callbackReceiver = this; | |
| 185 | + callbackParams.jsonCallbackMethod = "createCompleted"; | |
| 186 | + callbackParams.errorCallbackMethod = "createFailed"; | |
| 187 | + | |
| 188 | + const QString CREATE_ACCOUNT_FROM_OCULUS_PATH = "api/v1/user/oculus/create"; | |
| 189 | + | |
| 190 | + QJsonObject payload; | |
| 191 | + payload["oculus_nonce"] = nonce; | |
| 192 | + payload["oculus_id"] = oculusID; | |
| 193 | + if (!email.isEmpty()) { | |
| 194 | + payload["email"] = email; | |
| 195 | + } | |
| 196 | + if (!username.isEmpty()) { | |
| 197 | + payload["username"] = username; | |
| 198 | + } | |
| 199 | + if (!password.isEmpty()) { | |
| 200 | + payload["password"] = password; | |
| 201 | + } | |
| 202 | + | |
| 203 | + auto accountManager = DependencyManager::get<AccountManager>(); | |
| 204 | + accountManager->sendRequest(CREATE_ACCOUNT_FROM_OCULUS_PATH, AccountManagerAuth::None, | |
| 205 | + QNetworkAccessManager::PostOperation, callbackParams, | |
| 206 | + QJsonDocument(payload).toJson()); | |
| 207 | + }); | |
| 208 | + } | |
| 209 | +} | |
| 210 | + | |
| 129 | 211 | void LoginDialog::loginThroughSteam() { |
| 130 | 212 | qDebug() << "Attempting to login through Steam"; |
| 131 | 213 | if (auto steamClient = PluginManager::getInstance()->getSteamClientPlugin()) { |
| @@ -157,7 +239,7 @@ void LoginDialog::linkSteam() { · 25 unmodified lines | ||
| 157 | 239 | const QString LINK_STEAM_PATH = "api/v1/user/steam/link"; |
| 158 | 240 | |
| 159 | 241 | QJsonObject payload; |
| 160 | − payload.insert("steam_auth_ticket", QJsonValue::fromVariant(QVariant(ticket))); | |
| 242 | + payload["steam_auth_ticket"] = QJsonValue::fromVariant(QVariant(ticket)); | |
| 161 | 243 | |
| 162 | 244 | auto accountManager = DependencyManager::get<AccountManager>(); |
| 163 | 245 | accountManager->sendRequest(LINK_STEAM_PATH, AccountManagerAuth::Required, |
| @@ -184,9 +266,9 @@ void LoginDialog::createAccountFromSteam(QString username) { · 20 unmodified lines | ||
| 184 | 266 | const QString CREATE_ACCOUNT_FROM_STEAM_PATH = "api/v1/user/steam/create"; |
| 185 | 267 | |
| 186 | 268 | QJsonObject payload; |
| 187 | − payload.insert("steam_auth_ticket", QJsonValue::fromVariant(QVariant(ticket))); | |
| 269 | + payload["steam_auth_ticket"] = QJsonValue::fromVariant(QVariant(ticket)); | |
| 188 | 270 | if (!username.isEmpty()) { |
| 189 | − payload.insert("username", QJsonValue::fromVariant(QVariant(username))); | |
| 271 | + payload["username"] = username; | |
| 190 | 272 | } |
| 191 | 273 | |
| 192 | 274 | auto accountManager = DependencyManager::get<AccountManager>(); |
| @@ -214,6 +296,45 @@ void LoginDialog::createCompleted(QNetworkReply* reply) { · 21 unmodified lines | ||
| 214 | 296 | } |
| 215 | 297 | |
| 216 | 298 | void LoginDialog::createFailed(QNetworkReply* reply) { |
| 299 | + if (isOculusRunning()) { | |
| 300 | + auto replyData = reply->readAll(); | |
| 301 | + QJsonParseError parseError; | |
| 302 | + auto doc = QJsonDocument::fromJson(replyData, &parseError); | |
| 303 | + if (parseError.error != QJsonParseError::NoError) { | |
| 304 | + emit handleCreateFailed(reply->errorString()); | |
| 305 | + return; | |
| 306 | + } | |
| 307 | + auto data = doc["data"]; | |
| 308 | + auto error = data["error"]; | |
| 309 | + auto oculusError = data["oculus"]; | |
| 310 | + auto user = error["username"].toArray(); | |
| 311 | + auto uid = error["uid"].toArray(); | |
| 312 | + auto email = error["email"].toArray(); | |
| 313 | + auto password = error["password"].toArray(); | |
| 314 | + QString reply; | |
| 315 | + if (uid[0].isString()) { | |
| 316 | + emit handleCreateFailed("Oculus ID " + uid[0].toString() + "."); | |
| 317 | + return; | |
| 318 | + } | |
| 319 | + if (user[0].isString()) { | |
| 320 | + reply = "Username " + user[0].toString() + "."; | |
| 321 | + } | |
| 322 | + if (email[0].isString()) { | |
| 323 | + reply.append((!reply.isEmpty()) ? "\n" : ""); | |
| 324 | + reply.append("Email " + email[0].toString() + "."); | |
| 325 | + } | |
| 326 | + if (password[0].isString()) { | |
| 327 | + reply.append((!reply.isEmpty()) ? "\n" : ""); | |
| 328 | + reply.append("Password " + password[0].toString() + "."); | |
| 329 | + } | |
| 330 | + if (!oculusError.isNull() && !oculusError.isUndefined()) { | |
| 331 | + emit handleCreateFailed("Could not verify token with Oculus. Please try again."); | |
| 332 | + return; | |
| 333 | + } else { | |
| 334 | + emit handleCreateFailed(reply); | |
| 335 | + return; | |
| 336 | + } | |
| 337 | + } | |
| 217 | 338 | emit handleCreateFailed(reply->errorString()); |
| 218 | 339 | } |
| 219 | 340 | |
| @@ -22,7 +22,6 @@ extern const QUrl OVERLAY_LOGIN_DIALOG; · 21 unmodified lines | ||
| 22 | 22 | |
| 23 | 23 | class LoginDialog : public OffscreenQmlDialog { |
| 24 | 24 | Q_OBJECT |
| 25 | − Q_PROPERTY(bool isLogIn READ getIsLogIn WRITE setIsLogIn) | |
| 26 | 25 | HIFI_QML_DECL |
| 27 | 26 | |
| 28 | 27 | public: |
| @@ -67,24 +66,23 @@ protected slots: · 38 unmodified lines | ||
| 67 | 66 | Q_INVOKABLE void dismissLoginDialog(); |
| 68 | 67 | |
| 69 | 68 | Q_INVOKABLE bool isSteamRunning() const; |
| 70 | − Q_INVOKABLE bool isOculusStoreRunning() const; | |
| 69 | + Q_INVOKABLE bool isOculusRunning() const; | |
| 70 | + | |
| 71 | + Q_INVOKABLE QString oculusUserID() const; | |
| 71 | 72 | |
| 72 | 73 | Q_INVOKABLE void login(const QString& username, const QString& password) const; |
| 73 | 74 | Q_INVOKABLE void loginThroughSteam(); |
| 74 | 75 | Q_INVOKABLE void linkSteam(); |
| 75 | 76 | Q_INVOKABLE void createAccountFromSteam(QString username = QString()); |
| 77 | + Q_INVOKABLE void loginThroughOculus(); | |
| 78 | + Q_INVOKABLE void linkOculus(); | |
| 79 | + Q_INVOKABLE void createAccountFromOculus(QString email = QString(), QString username = QString(), QString password = QString()); | |
| 76 | 80 | |
| 77 | 81 | Q_INVOKABLE void signup(const QString& email, const QString& username, const QString& password); |
| 78 | 82 | |
| 79 | 83 | Q_INVOKABLE void openUrl(const QString& url) const; |
| 80 | 84 | |
| 81 | 85 | Q_INVOKABLE bool getLoginDialogPoppedUp() const; |
| 82 | − | |
| 83 | −private: | |
| 84 | − bool getIsLogIn() const { return _isLogIn; } | |
| 85 | − void setIsLogIn(const bool isLogIn) { _isLogIn = isLogIn; } | |
| 86 | − | |
| 87 | − bool _isLogIn{ false }; | |
| 88 | 86 | }; |
| 89 | 87 | |
| 90 | 88 | #endif // hifi_LoginDialog_h |
| @@ -31,6 +31,8 @@ public: · 30 unmodified lines | ||
| 31 | 31 | |
| 32 | 32 | virtual void compositeExtra() override; |
| 33 | 33 | |
| 34 | + virtual void pluginUpdate() override {}; | |
| 35 | + | |
| 34 | 36 | protected: |
| 35 | 37 | mutable bool _isThrottled = false; |
| 36 | 38 | |
| @@ -20,6 +20,7 @@ public: · 19 unmodified lines | ||
| 20 | 20 | QImage getScreenshot(float aspectRatio = 0.0f) const override; |
| 21 | 21 | QImage getSecondaryCameraScreenshot() const override; |
| 22 | 22 | void copyTextureToQuickFramebuffer(NetworkTexturePointer source, QOpenGLFramebufferObject* target, GLsync* fenceSync) override {}; |
| 23 | + void pluginUpdate() override {}; | |
| 23 | 24 | private: |
| 24 | 25 | static const QString NAME; |
| 25 | 26 | }; |
| @@ -46,6 +46,8 @@ public: · 45 unmodified lines | ||
| 46 | 46 | |
| 47 | 47 | virtual bool onDisplayTextureReset() override { _clearPreviewFlag = true; return true; }; |
| 48 | 48 | |
| 49 | + void pluginUpdate() override {}; | |
| 50 | + | |
| 49 | 51 | signals: |
| 50 | 52 | void hmdMountedChanged(); |
| 51 | 53 | void hmdVisibleChanged(bool visible); |
| @@ -28,6 +28,8 @@ public: · 27 unmodified lines | ||
| 28 | 28 | // to the HMD plugins. |
| 29 | 29 | //virtual glm::mat4 getEyeToHeadTransform(Eye eye) const override; |
| 30 | 30 | |
| 31 | + virtual void pluginUpdate() override {}; | |
| 32 | + | |
| 31 | 33 | protected: |
| 32 | 34 | virtual bool internalActivate() override; |
| 33 | 35 | virtual void internalDeactivate() override; |
| @@ -588,6 +588,29 @@ void AccountManager::requestAccessTokenWithSteam(QByteArray authSessionTicket) { · 587 unmodified lines | ||
| 588 | 588 | connect(requestReply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(requestAccessTokenError(QNetworkReply::NetworkError))); |
| 589 | 589 | } |
| 590 | 590 | |
| 591 | +void AccountManager::requestAccessTokenWithOculus(const QString& nonce, const QString &oculusID) { | |
| 592 | + QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance(); | |
| 593 | + | |
| 594 | + QNetworkRequest request; | |
| 595 | + request.setHeader(QNetworkRequest::UserAgentHeader, _userAgentGetter()); | |
| 596 | + | |
| 597 | + QUrl grantURL = _authURL; | |
| 598 | + grantURL.setPath("/oauth/token"); | |
| 599 | + | |
| 600 | + QByteArray postData; | |
| 601 | + postData.append("grant_type=password&"); | |
| 602 | + postData.append("oculus_nonce=" + nonce + "&"); | |
| 603 | + postData.append("oculus_id=" + oculusID + "&"); | |
| 604 | + postData.append("scope=" + ACCOUNT_MANAGER_REQUESTED_SCOPE); | |
| 605 | + | |
| 606 | + request.setUrl(grantURL); | |
| 607 | + request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded"); | |
| 608 | + | |
| 609 | + QNetworkReply* requestReply = networkAccessManager.post(request, postData); | |
| 610 | + connect(requestReply, &QNetworkReply::finished, this, &AccountManager::requestAccessTokenFinished); | |
| 611 | + connect(requestReply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(requestAccessTokenError(QNetworkReply::NetworkError))); | |
| 612 | +} | |
| 613 | + | |
| 591 | 614 | void AccountManager::refreshAccessToken() { |
| 592 | 615 | |
| 593 | 616 | // we can't refresh our access token if we don't have a refresh token, so check for that first |
| @@ -106,6 +106,7 @@ public: · 105 unmodified lines | ||
| 106 | 106 | public slots: |
| 107 | 107 | void requestAccessToken(const QString& login, const QString& password); |
| 108 | 108 | void requestAccessTokenWithSteam(QByteArray authSessionTicket); |
| 109 | + void requestAccessTokenWithOculus(const QString& nonce, const QString& oculusID); | |
| 109 | 110 | void requestAccessTokenWithAuthCode(const QString& authCode, |
| 110 | 111 | const QString& clientId, |
| 111 | 112 | const QString& clientSecret, |
| @@ -217,6 +217,9 @@ public: · 216 unmodified lines | ||
| 217 | 217 | |
| 218 | 218 | static const QString& MENU_PATH(); |
| 219 | 219 | |
| 220 | + // for updating plugin-related commands. Mimics the input plugin. | |
| 221 | + virtual void pluginUpdate() = 0; | |
| 222 | + | |
| 220 | 223 | signals: |
| 221 | 224 | void recommendedFramebufferSizeChanged(const QSize& size); |
| 222 | 225 | void resetSensorsRequested(); |
| @@ -21,6 +21,7 @@ class DisplayPlugin; · 20 unmodified lines | ||
| 21 | 21 | class InputPlugin; |
| 22 | 22 | class CodecPlugin; |
| 23 | 23 | class SteamClientPlugin; |
| 24 | +class OculusPlatformPlugin; | |
| 24 | 25 | class Plugin; |
| 25 | 26 | class PluginContainer; |
| 26 | 27 | class PluginManager; |
| @@ -35,4 +36,5 @@ using CodecPluginPointer = std::shared_ptr<CodecPlugin>; · 8 unmodified lines | ||
| 35 | 36 | using CodecPluginList = std::vector<CodecPluginPointer>; |
| 36 | 37 | using CodecPluginProvider = std::function<CodecPluginList()>; |
| 37 | 38 | using SteamClientPluginPointer = std::shared_ptr<SteamClientPlugin>; |
| 39 | +using OculusPlatformPluginPointer = std::shared_ptr<OculusPlatformPlugin>; | |
| 38 | 40 | using InputPluginSettingsPersister = std::function<void(const InputPluginList&)>; |
| @@ -0,0 +1,28 @@ | ||
| 1 | +// | |
| 2 | +// Created by Wayne Chen on 2018/12/20 | |
| 3 | +// Copyright 2018 High Fidelity Inc. | |
| 4 | +// | |
| 5 | +// Distributed under the Apache License, Version 2.0. | |
| 6 | +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2-0.html | |
| 7 | +// | |
| 8 | +#pragma once | |
| 9 | + | |
| 10 | +#include <QtCore/QString> | |
| 11 | + | |
| 12 | +#include <functional> | |
| 13 | + | |
| 14 | +using NonceUserIDCallback = std::function<void(QString, QString)>; | |
| 15 | + | |
| 16 | +class OculusPlatformPlugin { | |
| 17 | +public: | |
| 18 | + virtual ~OculusPlatformPlugin() = default; | |
| 19 | + | |
| 20 | + virtual QString getName() const = 0; | |
| 21 | + virtual QString getOculusUserID() const = 0; | |
| 22 | + | |
| 23 | + virtual bool isRunning() const = 0; | |
| 24 | + | |
| 25 | + virtual void requestNonceAndUserID(NonceUserIDCallback callback) = 0; | |
| 26 | + | |
| 27 | + virtual void handleOVREvents() = 0; | |
| 28 | +}; | |
| @@ -188,6 +188,22 @@ const SteamClientPluginPointer PluginManager::getSteamClientPlugin() { · 187 unmodified lines | ||
| 188 | 188 | return steamClientPlugin; |
| 189 | 189 | } |
| 190 | 190 | |
| 191 | +const OculusPlatformPluginPointer PluginManager::getOculusPlatformPlugin() { | |
| 192 | + static OculusPlatformPluginPointer oculusPlatformPlugin; | |
| 193 | + static std::once_flag once; | |
| 194 | + std::call_once(once, [&] { | |
| 195 | + // Now grab the dynamic plugins | |
| 196 | + for (auto loader : getLoadedPlugins()) { | |
| 197 | + OculusPlatformProvider* oculusPlatformProvider = qobject_cast<OculusPlatformProvider*>(loader->instance()); | |
| 198 | + if (oculusPlatformProvider) { | |
| 199 | + oculusPlatformPlugin = oculusPlatformProvider->getOculusPlatformPlugin(); | |
| 200 | + break; | |
| 201 | + } | |
| 202 | + } | |
| 203 | + }); | |
| 204 | + return oculusPlatformPlugin; | |
| 205 | +} | |
| 206 | + | |
| 191 | 207 | const DisplayPluginList& PluginManager::getDisplayPlugins() { |
| 192 | 208 | static std::once_flag once; |
| 193 | 209 | static auto deviceAddedCallback = [](QString deviceName) { |
| @@ -27,6 +27,7 @@ public: · 26 unmodified lines | ||
| 27 | 27 | const InputPluginList& getInputPlugins(); |
| 28 | 28 | const CodecPluginList& getCodecPlugins(); |
| 29 | 29 | const SteamClientPluginPointer getSteamClientPlugin(); |
| 30 | + const OculusPlatformPluginPointer getOculusPlatformPlugin(); | |
| 30 | 31 | |
| 31 | 32 | DisplayPluginList getPreferredDisplayPlugins(); |
| 32 | 33 | void setPreferredDisplayPlugins(const QStringList& displays); |
| @@ -51,5 +51,13 @@ public: · 50 unmodified lines | ||
| 51 | 51 | virtual SteamClientPluginPointer getSteamClientPlugin() = 0; |
| 52 | 52 | }; |
| 53 | 53 | |
| 54 | +class OculusPlatformProvider { | |
| 55 | +public: | |
| 56 | + virtual OculusPlatformPluginPointer getOculusPlatformPlugin() = 0; | |
| 57 | +}; | |
| 58 | + | |
| 54 | 59 | #define SteamClientProvider_iid "com.highfidelity.plugins.steamclient" |
| 55 | 60 | Q_DECLARE_INTERFACE(SteamClientProvider, SteamClientProvider_iid) |
| 61 | + | |
| 62 | +#define OculusPlatformProvider_iid "com.highfidelity.plugins.oculusplatform" | |
| 63 | +Q_DECLARE_INTERFACE(OculusPlatformProvider, OculusPlatformProvider_iid) | |
| @@ -12,6 +12,7 @@ · 11 unmodified lines | ||
| 12 | 12 | #include <display-plugins/CompositorHelper.h> |
| 13 | 13 | #include <gpu/Frame.h> |
| 14 | 14 | #include <gl/Config.h> |
| 15 | +#include <shared/GlobalAppProperties.h> | |
| 15 | 16 | |
| 16 | 17 | #include "OculusHelpers.h" |
| 17 | 18 | |
| @@ -30,7 +31,7 @@ bool OculusBaseDisplayPlugin::beginFrameRender(uint32_t frameIndex) { · 12 unmodified lines | ||
| 30 | 31 | return false; |
| 31 | 32 | } |
| 32 | 33 | |
| 33 | − if (ovr::quitRequested(status) || ovr::displayLost(status) || !ovr::handleOVREvents()) { | |
| 34 | + if (ovr::quitRequested(status) || ovr::displayLost(status)) { | |
| 34 | 35 | QMetaObject::invokeMethod(qApp, "quit"); |
| 35 | 36 | return false; |
| 36 | 37 | } |
| @@ -13,6 +13,9 @@ · 12 unmodified lines | ||
| 13 | 13 | |
| 14 | 14 | #include <OVR_CAPI_GL.h> |
| 15 | 15 | |
| 16 | +#define OVRPL_DISABLED | |
| 17 | +#include <OVR_Platform.h> | |
| 18 | + | |
| 16 | 19 | class OculusBaseDisplayPlugin : public HmdDisplayPlugin { |
| 17 | 20 | using Parent = HmdDisplayPlugin; |
| 18 | 21 | public: |
| @@ -30,7 +33,7 @@ public: · 11 unmodified lines | ||
| 30 | 33 | |
| 31 | 34 | QRectF getPlayAreaRect() override; |
| 32 | 35 | QVector<glm::vec3> getSensorPositions() override; |
| 33 | − | |
| 36 | + | |
| 34 | 37 | protected: |
| 35 | 38 | void customizeContext() override; |
| 36 | 39 | void uncustomizeContext() override; |
| @@ -296,34 +296,3 @@ controller::Pose hifi::ovr::toControllerPose(ovrHandType hand, · 295 unmodified lines | ||
| 296 | 296 | pose.valid = true; |
| 297 | 297 | return pose; |
| 298 | 298 | } |
| 299 | − | |
| 300 | −bool hifi::ovr::handleOVREvents() { | |
| 301 | −#ifdef OCULUS_APP_ID | |
| 302 | − if (qApp->property(hifi::properties::OCULUS_STORE).toBool()) { | |
| 303 | − // pop messages to see if we got a return for an entitlement check | |
| 304 | − ovrMessageHandle message = ovr_PopMessage(); | |
| 305 | − | |
| 306 | − while (message) { | |
| 307 | − switch (ovr_Message_GetType(message)) { | |
| 308 | − case ovrMessage_Entitlement_GetIsViewerEntitled: { | |
| 309 | − if (!ovr_Message_IsError(message)) { | |
| 310 | − // this viewer is entitled, no need to flag anything | |
| 311 | − qCDebug(oculusLog) << "Oculus Platform entitlement check succeeded, proceeding normally"; | |
| 312 | − } else { | |
| 313 | − // we failed the entitlement check, quit | |
| 314 | − qCDebug(oculusLog) << "Oculus Platform entitlement check failed, app will now quit" << OCULUS_APP_ID; | |
| 315 | − return false; | |
| 316 | − } | |
| 317 | − } | |
| 318 | − } | |
| 319 | − | |
| 320 | − // free the message handle to cleanup and not leak | |
| 321 | − ovr_FreeMessage(message); | |
| 322 | − | |
| 323 | − // pop the next message to check, if there is one | |
| 324 | − message = ovr_PopMessage(); | |
| 325 | − } | |
| 326 | − } | |
| 327 | −#endif | |
| 328 | − return true; | |
| 329 | −} | |
| @@ -30,7 +30,6 @@ struct ovr { · 29 unmodified lines | ||
| 30 | 30 | static ovrSessionStatus getStatus(ovrResult& result); |
| 31 | 31 | static ovrTrackingState getTrackingState(double absTime = 0.0, ovrBool latencyMarker = ovrFalse); |
| 32 | 32 | static QString getError(); |
| 33 | − static bool handleOVREvents(); | |
| 34 | 33 | |
| 35 | 34 | static inline bool quitRequested() { return quitRequested(getStatus()); } |
| 36 | 35 | static inline bool reorientRequested() { return reorientRequested(getStatus()); } |
| @@ -0,0 +1,109 @@ | ||
| 1 | +// | |
| 2 | +// Created by Wayne Chen on 2019/01/08 | |
| 3 | +// Copyright 2019 High Fidelity, Inc. | |
| 4 | +// | |
| 5 | +// Distributed under the Apache License, Version 2.0. | |
| 6 | +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html | |
| 7 | +// | |
| 8 | + | |
| 9 | +#include "OculusPlatformPlugin.h" | |
| 10 | + | |
| 11 | +#include <shared/GlobalAppProperties.h> | |
| 12 | + | |
| 13 | +#include <QMetaObject> | |
| 14 | + | |
| 15 | +#include "OculusHelpers.h" | |
| 16 | + | |
| 17 | +QString OculusAPIPlugin::NAME { "Oculus Rift" }; | |
| 18 | + | |
| 19 | +OculusAPIPlugin::OculusAPIPlugin() { | |
| 20 | + _session = hifi::ovr::acquireRenderSession(); | |
| 21 | +} | |
| 22 | + | |
| 23 | +OculusAPIPlugin::~OculusAPIPlugin() { | |
| 24 | + hifi::ovr::releaseRenderSession(_session); | |
| 25 | +} | |
| 26 | + | |
| 27 | +bool OculusAPIPlugin::isRunning() const { | |
| 28 | + return (qApp->property(hifi::properties::OCULUS_STORE).toBool()); | |
| 29 | +} | |
| 30 | + | |
| 31 | +void OculusAPIPlugin::requestNonceAndUserID(NonceUserIDCallback callback) { | |
| 32 | +#ifdef OCULUS_APP_ID | |
| 33 | + _nonceUserIDCallback = callback; | |
| 34 | + ovr_User_GetUserProof(); | |
| 35 | + ovr_User_GetLoggedInUser(); | |
| 36 | +#endif | |
| 37 | +} | |
| 38 | + | |
| 39 | +void OculusAPIPlugin::handleOVREvents() { | |
| 40 | +#ifdef OCULUS_APP_ID | |
| 41 | + if (qApp->property(hifi::properties::OCULUS_STORE).toBool()) { | |
| 42 | + // pop messages to see if we got a return for an entitlement check | |
| 43 | + ovrMessageHandle message { nullptr }; | |
| 44 | + | |
| 45 | + // pop the next message to check, if there is one | |
| 46 | + while ((message = ovr_PopMessage())) { | |
| 47 | + switch (ovr_Message_GetType(message)) { | |
| 48 | + case ovrMessage_Entitlement_GetIsViewerEntitled: { | |
| 49 | + if (!ovr_Message_IsError(message)) { | |
| 50 | + // this viewer is entitled, no need to flag anything | |
| 51 | + qCDebug(oculusLog) << "Oculus Platform entitlement check succeeded, proceeding normally"; | |
| 52 | + } else { | |
| 53 | + // we failed the entitlement check, quit | |
| 54 | + qCDebug(oculusLog) << "Oculus Platform entitlement check failed, app will now quit" << OCULUS_APP_ID; | |
| 55 | + QMetaObject::invokeMethod(qApp, "quit"); | |
| 56 | + } | |
| 57 | + break; | |
| 58 | + } | |
| 59 | + case ovrMessage_User_Get: { | |
| 60 | + if (!ovr_Message_IsError(message)) { | |
| 61 | + qCDebug(oculusLog) << "Oculus Platform user retrieval succeeded"; | |
| 62 | + ovrUserHandle user = ovr_Message_GetUser(message); | |
| 63 | + _user = ovr_User_GetOculusID(user); | |
| 64 | + // went all the way through the `requestNonceAndUserID()` pipeline successfully. | |
| 65 | + } else { | |
| 66 | + qCDebug(oculusLog) << "Oculus Platform user retrieval failed" << QString(ovr_Error_GetMessage(ovr_Message_GetError(message))); | |
| 67 | + // emit the signal so we don't hang for it anywhere else. | |
| 68 | + _user = ""; | |
| 69 | + } | |
| 70 | + break; | |
| 71 | + } | |
| 72 | + case ovrMessage_User_GetLoggedInUser: { | |
| 73 | + if (!ovr_Message_IsError(message)) { | |
| 74 | + ovrUserHandle user = ovr_Message_GetUser(message); | |
| 75 | + _userID = ovr_User_GetID(user); | |
| 76 | + ovr_User_Get(_userID); | |
| 77 | + } else { | |
| 78 | + qCDebug(oculusLog) << "Oculus Platform user ID retrieval failed" << QString(ovr_Error_GetMessage(ovr_Message_GetError(message))); | |
| 79 | + // emit the signal so we don't hang for it anywhere else. | |
| 80 | + } | |
| 81 | + _userIDChanged = true; | |
| 82 | + break; | |
| 83 | + } | |
| 84 | + case ovrMessage_User_GetUserProof: { | |
| 85 | + if (!ovr_Message_IsError(message)) { | |
| 86 | + ovrUserProofHandle userProof = ovr_Message_GetUserProof(message); | |
| 87 | + _nonce = ovr_UserProof_GetNonce(userProof); | |
| 88 | + qCDebug(oculusLog) << "Oculus Platform nonce retrieval succeeded: " << _nonce; | |
| 89 | + } else { | |
| 90 | + qCDebug(oculusLog) << "Oculus Platform nonce retrieval failed" << QString(ovr_Error_GetMessage(ovr_Message_GetError(message))); | |
| 91 | + _nonce = ""; | |
| 92 | + // emit the signal so we don't hang for it anywhere else. | |
| 93 | + } | |
| 94 | + _nonceChanged = true; | |
| 95 | + break; | |
| 96 | + } | |
| 97 | + } | |
| 98 | + | |
| 99 | + if (_nonceChanged && _userIDChanged) { | |
| 100 | + _nonceUserIDCallback(_nonce, QString::number(_userID)); | |
| 101 | + _nonceChanged = _userIDChanged = false; | |
| 102 | + } | |
| 103 | + | |
| 104 | + // free the message handle to cleanup and not leak | |
| 105 | + ovr_FreeMessage(message); | |
| 106 | + } | |
| 107 | + } | |
| 108 | +#endif | |
| 109 | +} | |
| @@ -0,0 +1,39 @@ | ||
| 1 | +// | |
| 2 | +// Created by Wayne Chen on 2019/01/08 | |
| 3 | +// Copyright 2019 High Fidelity, Inc. | |
| 4 | +// | |
| 5 | +// Distributed under the Apache License, Version 2.0. | |
| 6 | +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html | |
| 7 | +// | |
| 8 | +#pragma once | |
| 9 | + | |
| 10 | +#include <plugins/OculusPlatformPlugin.h> | |
| 11 | + | |
| 12 | +#include <OVR_CAPI_GL.h> | |
| 13 | + | |
| 14 | +#define OVRPL_DISABLED | |
| 15 | +#include <OVR_Platform.h> | |
| 16 | + | |
| 17 | +class OculusAPIPlugin : public OculusPlatformPlugin { | |
| 18 | +public: | |
| 19 | + OculusAPIPlugin(); | |
| 20 | + virtual ~OculusAPIPlugin(); | |
| 21 | + QString getName() const { return NAME; } | |
| 22 | + QString getOculusUserID() const { return _user; }; | |
| 23 | + | |
| 24 | + bool isRunning() const; | |
| 25 | + | |
| 26 | + virtual void requestNonceAndUserID(NonceUserIDCallback callback); | |
| 27 | + | |
| 28 | + virtual void handleOVREvents(); | |
| 29 | + | |
| 30 | +private: | |
| 31 | + static QString NAME; | |
| 32 | + NonceUserIDCallback _nonceUserIDCallback; | |
| 33 | + QString _nonce; | |
| 34 | + bool _nonceChanged{ false }; | |
| 35 | + bool _userIDChanged{ false }; | |
| 36 | + QString _user; | |
| 37 | + ovrID _userID; | |
| 38 | + ovrSession _session; | |
| 39 | +}; | |
| @@ -18,15 +18,18 @@ · 17 unmodified lines | ||
| 18 | 18 | |
| 19 | 19 | #include "OculusDisplayPlugin.h" |
| 20 | 20 | #include "OculusDebugDisplayPlugin.h" |
| 21 | +#include "OculusPlatformPlugin.h" | |
| 21 | 22 | #include "OculusControllerManager.h" |
| 22 | 23 | |
| 23 | −class OculusProvider : public QObject, public DisplayProvider, InputProvider | |
| 24 | +class OculusProvider : public QObject, public DisplayProvider, InputProvider, OculusPlatformProvider | |
| 24 | 25 | { |
| 25 | 26 | Q_OBJECT |
| 26 | 27 | Q_PLUGIN_METADATA(IID DisplayProvider_iid FILE "oculus.json") |
| 27 | 28 | Q_INTERFACES(DisplayProvider) |
| 28 | 29 | Q_PLUGIN_METADATA(IID InputProvider_iid FILE "oculus.json") |
| 29 | 30 | Q_INTERFACES(InputProvider) |
| 31 | + Q_PLUGIN_METADATA(IID OculusPlatformProvider_iid FILE "oculus.json") | |
| 32 | + Q_INTERFACES(OculusPlatformProvider) | |
| 30 | 33 | |
| 31 | 34 | public: |
| 32 | 35 | OculusProvider(QObject* parent = nullptr) : QObject(parent) {} |
| @@ -62,6 +65,15 @@ public: · 29 unmodified lines | ||
| 62 | 65 | return _inputPlugins; |
| 63 | 66 | } |
| 64 | 67 | |
| 68 | + virtual OculusPlatformPluginPointer getOculusPlatformPlugin() override { | |
| 69 | + static std::once_flag once; | |
| 70 | + std::call_once(once, [&] { | |
| 71 | + _oculusPlatformPlugin = std::make_shared<OculusAPIPlugin>(); | |
| 72 | + | |
| 73 | + }); | |
| 74 | + return _oculusPlatformPlugin; | |
| 75 | + } | |
| 76 | + | |
| 65 | 77 | virtual void destroyInputPlugins() override { |
| 66 | 78 | _inputPlugins.clear(); |
| 67 | 79 | } |
| @@ -73,6 +85,7 @@ public: · 5 unmodified lines | ||
| 73 | 85 | private: |
| 74 | 86 | DisplayPluginList _displayPlugins; |
| 75 | 87 | InputPluginList _inputPlugins; |
| 88 | + OculusPlatformPluginPointer _oculusPlatformPlugin; | |
| 76 | 89 | }; |
| 77 | 90 | |
| 78 | 91 | #include "OculusProvider.moc" |