[haiku-commits] haiku: hrev53472 - in src/apps/haikudepot: ui server .

  • From: Andrew Lindesay <apl@xxxxxxxxxxxxxx>
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Tue, 10 Sep 2019 02:10:23 -0400 (EDT)

hrev53472 adds 1 changeset to branch 'master'
old head: a310e5e52ff93d15a16b96bf84e486379c6e5f68
new head: 0c82f64bf608fbec4e2637162cc34e562e2343a5
overview: 
https://git.haiku-os.org/haiku/log/?qt=range&q=0c82f64bf608+%5Ea310e5e52ff9

----------------------------------------------------------------------------

0c82f64bf608: HaikuDepot: Conditions on Create User
  
  When the user chooses to create a new user they
  are able to view the current usage conditions for
  users.  They are also required to agree to the
  conditions and they are required to confirm that
  they meet the minimum age requirement.
  
  Relates to 15209
  
  Change-Id: I83cdaabe1b3da31a4cd21139b72341f4b93cab85
  Reviewed-on: https://review.haiku-os.org/c/haiku/+/1842
  Reviewed-by: Jérôme Duval <jerome.duval@xxxxxxxxx>

                                    [ Andrew Lindesay <apl@xxxxxxxxxxxxxx> ]

----------------------------------------------------------------------------

Revision:    hrev53472
Commit:      0c82f64bf608fbec4e2637162cc34e562e2343a5
URL:         https://git.haiku-os.org/haiku/commit/?id=0c82f64bf608
Author:      Andrew Lindesay <apl@xxxxxxxxxxxxxx>
Date:        Tue Sep  3 01:54:10 2019 UTC

----------------------------------------------------------------------------

8 files changed, 354 insertions(+), 109 deletions(-)
src/apps/haikudepot/HaikuDepotConstants.h        |  31 +--
src/apps/haikudepot/server/WebAppInterface.cpp   |  53 +++--
src/apps/haikudepot/server/WebAppInterface.h     |   1 +
src/apps/haikudepot/ui/MainWindow.cpp            |  14 +-
src/apps/haikudepot/ui/UserLoginWindow.cpp       | 217 +++++++++++++++++--
src/apps/haikudepot/ui/UserLoginWindow.h         |  23 +-
.../haikudepot/ui/UserUsageConditionsWindow.cpp  | 113 ++++++----
.../haikudepot/ui/UserUsageConditionsWindow.h    |  11 +-

----------------------------------------------------------------------------

diff --git a/src/apps/haikudepot/HaikuDepotConstants.h 
b/src/apps/haikudepot/HaikuDepotConstants.h
index 752869e0ce..9dc8c062f5 100644
--- a/src/apps/haikudepot/HaikuDepotConstants.h
+++ b/src/apps/haikudepot/HaikuDepotConstants.h
@@ -6,20 +6,23 @@
 #define HAIKU_DEPOT_CONSTANTS_H
 
 enum {
-       MSG_MAIN_WINDOW_CLOSED          = 'mwcl',
-       MSG_PACKAGE_SELECTED            = 'pkgs',
-       MSG_PACKAGE_WORKER_BUSY         = 'pkwb',
-       MSG_PACKAGE_WORKER_IDLE         = 'pkwi',
-       MSG_ADD_VISIBLE_PACKAGES        = 'avpk',
-       MSG_UPDATE_SELECTED_PACKAGE     = 'uspk',
-       MSG_CLIENT_TOO_OLD                      = 'oldc',
-       MSG_NETWORK_TRANSPORT_ERROR     = 'nett',
-       MSG_SERVER_ERROR                        = 'svre',
-       MSG_SERVER_DATA_CHANGED         = 'svdc',
-       MSG_ALERT_SIMPLE_ERROR          = 'nser',
-       MSG_DID_ADD_USER_RATING         = 'adur',
-       MSG_DID_UPDATE_USER_RATING      = 'upur',
-       MSG_LANGUAGE_SELECTED           = 'lngs'
+       MSG_MAIN_WINDOW_CLOSED                                  = 'mwcl',
+       MSG_PACKAGE_SELECTED                                    = 'pkgs',
+       MSG_PACKAGE_WORKER_BUSY                                 = 'pkwb',
+       MSG_PACKAGE_WORKER_IDLE                                 = 'pkwi',
+       MSG_ADD_VISIBLE_PACKAGES                                = 'avpk',
+       MSG_UPDATE_SELECTED_PACKAGE                             = 'uspk',
+       MSG_CLIENT_TOO_OLD                                              = 
'oldc',
+       MSG_NETWORK_TRANSPORT_ERROR                             = 'nett',
+       MSG_SERVER_ERROR                                                = 
'svre',
+       MSG_SERVER_DATA_CHANGED                                 = 'svdc',
+       MSG_ALERT_SIMPLE_ERROR                                  = 'nser',
+       MSG_DID_ADD_USER_RATING                                 = 'adur',
+       MSG_DID_UPDATE_USER_RATING                              = 'upur',
+       MSG_LANGUAGE_SELECTED                                   = 'lngs',
+       MSG_VIEW_LATEST_USER_USAGE_CONDITIONS   = 'vluc',
+       MSG_USER_USAGE_CONDITIONS_DATA                  = 'uucd',
+       MSG_USER_USAGE_CONDITIONS_ERROR                 = 'uuce'
 };
 
 
diff --git a/src/apps/haikudepot/server/WebAppInterface.cpp 
b/src/apps/haikudepot/server/WebAppInterface.cpp
index 218e14c470..326ddd9bd1 100644
--- a/src/apps/haikudepot/server/WebAppInterface.cpp
+++ b/src/apps/haikudepot/server/WebAppInterface.cpp
@@ -693,31 +693,44 @@ status_t
 WebAppInterface::CreateUser(const BString& nickName,
        const BString& passwordClear, const BString& email,
        const BString& captchaToken, const BString& captchaResponse,
-       const BString& languageCode, BMessage& message)
+       const BString& languageCode, const BString& userUsageConditionsCode,
+       BMessage& message)
 {
-       JsonBuilder builder;
-       builder
-               .AddValue("jsonrpc", "2.0")
-               .AddValue("id", ++fRequestIndex)
-               .AddValue("method", "createUser")
-               .AddArray("params")
-                       .AddObject()
-                               .AddValue("nickname", nickName)
-                               .AddValue("passwordClear", passwordClear);
+               // BHttpRequest later takes ownership of this.
+       BMallocIO* requestEnvelopeData = new BMallocIO();
+       BJsonTextWriter requestEnvelopeWriter(requestEnvelopeData);
 
-                               if (!email.IsEmpty())
-                                       builder.AddValue("email", email);
+       requestEnvelopeWriter.WriteObjectStart();
+       _WriteStandardJsonRpcEnvelopeValues(requestEnvelopeWriter, 
"createUser");
+       requestEnvelopeWriter.WriteObjectName("params");
+       requestEnvelopeWriter.WriteArrayStart();
 
-                               builder.AddValue("captchaToken", captchaToken)
-                               .AddValue("captchaResponse", captchaResponse)
-                               .AddValue("naturalLanguageCode", languageCode)
-                       .EndObject()
-               .EndArray()
-       ;
+       requestEnvelopeWriter.WriteObjectStart();
 
-       BString jsonString = builder.End();
+       requestEnvelopeWriter.WriteObjectName("nickname");
+       requestEnvelopeWriter.WriteString(nickName.String());
+       requestEnvelopeWriter.WriteObjectName("passwordClear");
+       requestEnvelopeWriter.WriteString(passwordClear.String());
+       requestEnvelopeWriter.WriteObjectName("captchaToken");
+       requestEnvelopeWriter.WriteString(captchaToken.String());
+       requestEnvelopeWriter.WriteObjectName("captchaResponse");
+       requestEnvelopeWriter.WriteString(captchaResponse.String());
+       requestEnvelopeWriter.WriteObjectName("naturalLanguageCode");
+       requestEnvelopeWriter.WriteString(languageCode.String());
+       requestEnvelopeWriter.WriteObjectName("userUsageConditionsCode");
+       requestEnvelopeWriter.WriteString(userUsageConditionsCode.String());
 
-       return _SendJsonRequest("user", jsonString, 0, message);
+       if (!email.IsEmpty()) {
+               requestEnvelopeWriter.WriteObjectName("email");
+               requestEnvelopeWriter.WriteString(email.String());
+       }
+
+       requestEnvelopeWriter.WriteObjectEnd();
+       requestEnvelopeWriter.WriteArrayEnd();
+       requestEnvelopeWriter.WriteObjectEnd();
+
+       return _SendJsonRequest("user", requestEnvelopeData,
+               _LengthAndSeekToZero(requestEnvelopeData), 0, message);
 }
 
 
diff --git a/src/apps/haikudepot/server/WebAppInterface.h 
b/src/apps/haikudepot/server/WebAppInterface.h
index 36246235f4..0feaf496f1 100644
--- a/src/apps/haikudepot/server/WebAppInterface.h
+++ b/src/apps/haikudepot/server/WebAppInterface.h
@@ -106,6 +106,7 @@ public:
                                                                        const 
BString& captchaToken,
                                                                        const 
BString& captchaResponse,
                                                                        const 
BString& languageCode,
+                                                                       const 
BString& userUsageConditionsCode,
                                                                        
BMessage& message);
 
                        status_t                        AuthenticateUser(const 
BString& nickName,
diff --git a/src/apps/haikudepot/ui/MainWindow.cpp 
b/src/apps/haikudepot/ui/MainWindow.cpp
index ca38dac563..5d9adf9c6e 100644
--- a/src/apps/haikudepot/ui/MainWindow.cpp
+++ b/src/apps/haikudepot/ui/MainWindow.cpp
@@ -68,7 +68,6 @@ enum {
        MSG_PACKAGE_CHANGED                                             = 
'pchd',
        MSG_WORK_STATUS_CHANGE                                  = 'wsch',
        MSG_WORK_STATUS_CLEAR                                   = 'wscl',
-       MSG_VIEW_LATEST_USER_USAGE_CONDITIONS   = 'vluc',
 
        MSG_SHOW_FEATURED_PACKAGES                              = 'sofp',
        MSG_SHOW_AVAILABLE_PACKAGES                             = 'savl',
@@ -740,10 +739,11 @@ MainWindow::_BuildUserMenu(BMenuBar* menuBar)
                new BMessage(MSG_LOG_OUT));
        fUserMenu->AddItem(fLogOutItem);
 
-       fLogOutItem = new BMenuItem(B_TRANSLATE("View latest user usage 
conditions"
-               B_UTF8_ELLIPSIS),
-               new BMessage(MSG_VIEW_LATEST_USER_USAGE_CONDITIONS));
-       fUserMenu->AddItem(fLogOutItem);
+       BMenuItem *latestUserUsageConditionsMenuItem =
+               new BMenuItem(B_TRANSLATE("View latest user usage conditions"
+                       B_UTF8_ELLIPSIS),
+                       new BMessage(MSG_VIEW_LATEST_USER_USAGE_CONDITIONS));
+       fUserMenu->AddItem(latestUserUsageConditionsMenuItem);
 
        menuBar->AddItem(fUserMenu);
 }
@@ -1349,6 +1349,6 @@ void
 MainWindow::_ViewLatestUserUsageConditions()
 {
        UserUsageConditionsWindow* window = new UserUsageConditionsWindow(
-               this, BRect(0, 0, 500, 400), fModel, LATEST);
+               fModel, LATEST);
        window->Show();
-}
\ No newline at end of file
+}
diff --git a/src/apps/haikudepot/ui/UserLoginWindow.cpp 
b/src/apps/haikudepot/ui/UserLoginWindow.cpp
index 6b9eea3e92..b28cfffc21 100644
--- a/src/apps/haikudepot/ui/UserLoginWindow.cpp
+++ b/src/apps/haikudepot/ui/UserLoginWindow.cpp
@@ -15,6 +15,7 @@
 #include <Autolock.h>
 #include <AutoLocker.h>
 #include <Catalog.h>
+#include <CheckBox.h>
 #include <Button.h>
 #include <LayoutBuilder.h>
 #include <MenuField.h>
@@ -22,17 +23,27 @@
 #include <TextControl.h>
 #include <UnicodeChar.h>
 
+#include "AppUtils.h"
 #include "BitmapView.h"
 #include "HaikuDepotConstants.h"
 #include "LanguageMenuUtils.h"
+#include "LinkView.h"
 #include "Model.h"
 #include "TabView.h"
+#include "UserUsageConditions.h"
+#include "UserUsageConditionsWindow.h"
 #include "WebAppInterface.h"
 
 
 #undef B_TRANSLATION_CONTEXT
 #define B_TRANSLATION_CONTEXT "UserLoginWindow"
 
+#define PLACEHOLDER_TEXT B_UTF8_ELLIPSIS
+
+enum ActionTabs {
+       TAB_LOGIN                                       = 0,
+       TAB_CREATE_ACCOUNT                      = 1
+};
 
 enum {
        MSG_SEND                                        = 'send',
@@ -41,6 +52,26 @@ enum {
        MSG_VALIDATE_FIELDS                     = 'vldt'
 };
 
+/*! The creation of an account requires that some prerequisite data is first
+    loaded in or may later need to be refreshed.  This enum controls what
+    elements of the setup should be performed.
+*/
+
+enum CreateAccountSetupMask {
+       CREATE_CAPTCHA                                  = 1 << 1,
+       FETCH_USER_USAGE_CONDITIONS             = 1 << 2
+};
+
+/*! A background thread runs to gather data to use in the interface for 
creating
+    a new user.  This structure is passed to the background thread.
+*/
+
+struct CreateAccountSetupThreadData {
+       UserLoginWindow*        window;
+       uint32                          mask;
+               // defines what setup steps are required
+};
+
 
 UserLoginWindow::UserLoginWindow(BWindow* parent, BRect frame, Model& model)
        :
@@ -51,6 +82,7 @@ UserLoginWindow::UserLoginWindow(BWindow* parent, BRect 
frame, Model& model)
        fPreferredLanguageCode(LANGUAGE_DEFAULT_CODE),
        fModel(model),
        fMode(NONE),
+       fUserUsageConditions(NULL),
        fWorkerThread(-1)
 {
        AddToSubset(parent);
@@ -90,6 +122,19 @@ UserLoginWindow::UserLoginWindow(BWindow* parent, BRect 
frame, Model& model)
        fEmailField = new BTextControl(B_TRANSLATE("Email address:"), "", NULL);
        fCaptchaView = new BitmapView("captcha view");
        fCaptchaResultField = new BTextControl("", "", NULL);
+       fConfirmMinimumAgeCheckBox = new BCheckBox("confirm minimum age",
+               PLACEHOLDER_TEXT,
+                       // is filled in when the user usage conditions data is 
available
+               NULL);
+       fConfirmMinimumAgeCheckBox->SetEnabled(false);
+       fConfirmUserUsageConditionsCheckBox = new BCheckBox(
+               "confirm user usage conditions",
+               B_TRANSLATE("I agree to the usage conditions for users"),
+               NULL);
+       fUserUsageConditionsLink = new LinkView("user usage conditions view",
+               B_TRANSLATE("View the usage conditions for users"),
+               new BMessage(MSG_VIEW_LATEST_USER_USAGE_CONDITIONS));
+       fUserUsageConditionsLink->SetTarget(this);
 
        // Setup modification messages on all text fields to trigger validation
        // of input
@@ -103,7 +148,6 @@ UserLoginWindow::UserLoginWindow(BWindow* parent, BRect 
frame, Model& model)
                new BMessage(MSG_VALIDATE_FIELDS));
        fCaptchaResultField->SetModificationMessage(
                new BMessage(MSG_VALIDATE_FIELDS));
-
        fTabView = new TabView(BMessenger(this),
                BMessage(MSG_TAB_SELECTED));
 
@@ -126,7 +170,9 @@ UserLoginWindow::UserLoginWindow(BWindow* parent, BRect 
frame, Model& model)
                .AddMenuField(fLanguageCodeField, 0, 4)
                .Add(fCaptchaView, 0, 5)
                .Add(fCaptchaResultField, 1, 5)
-
+               .Add(fConfirmMinimumAgeCheckBox, 1, 6)
+               .Add(fConfirmUserUsageConditionsCheckBox, 1, 7)
+               .Add(fUserUsageConditionsLink, 1, 8)
                .SetInsets(B_USE_DEFAULT_SPACING)
        ;
        fTabView->AddTab(createAccountCard);
@@ -172,6 +218,10 @@ UserLoginWindow::MessageReceived(BMessage* message)
                        _ValidateCreateAccountFields();
                        break;
 
+               case MSG_VIEW_LATEST_USER_USAGE_CONDITIONS:
+                       _ViewUserUsageConditions();
+                       break;
+
                case MSG_SEND:
                        switch (fMode) {
                                case LOGIN:
@@ -190,10 +240,10 @@ UserLoginWindow::MessageReceived(BMessage* message)
                        int32 tabIndex;
                        if (message->FindInt32("tab index", &tabIndex) == B_OK) 
{
                                switch (tabIndex) {
-                                       case 0:
+                                       case TAB_LOGIN:
                                                _SetMode(LOGIN);
                                                break;
-                                       case 1:
+                                       case TAB_CREATE_ACCOUNT:
                                                _SetMode(CREATE_ACCOUNT);
                                                break;
                                        default:
@@ -212,6 +262,10 @@ UserLoginWindow::MessageReceived(BMessage* message)
                        fCaptchaResultField->SetText("");
                        break;
 
+               case MSG_USER_USAGE_CONDITIONS_DATA:
+                       _SetUserUsageConditions(new 
UserUsageConditions(message));
+                       break;
+
                case MSG_LANGUAGE_SELECTED:
                        message->FindString("code", &fPreferredLanguageCode);
                        break;
@@ -242,15 +296,14 @@ UserLoginWindow::_SetMode(Mode mode)
 
        switch (fMode) {
                case LOGIN:
-                       fTabView->Select((int32)0);
+                       fTabView->Select(TAB_LOGIN);
                        fSendButton->SetLabel(B_TRANSLATE("Log in"));
                        fUsernameField->MakeFocus();
                        break;
                case CREATE_ACCOUNT:
-                       fTabView->Select(1);
+                       fTabView->Select(TAB_CREATE_ACCOUNT);
                        fSendButton->SetLabel(B_TRANSLATE("Create account"));
-                       if (fCaptchaToken.IsEmpty())
-                               _RequestCaptcha();
+                       _CreateAccountSetupIfNecessary();
                        fNewUsernameField->MakeFocus();
                        _ValidateCreateAccountFields();
                        break;
@@ -296,6 +349,9 @@ UserLoginWindow::_ValidateCreateAccountFields(bool 
alertProblems)
        BString password2(fRepeatPasswordField->Text());
        BString email(fEmailField->Text());
        BString captcha(fCaptchaResultField->Text());
+       bool minimumAgeConfirmed = fConfirmMinimumAgeCheckBox->Value() != 0;
+       bool userUsageConditionsConfirmed =
+               fConfirmUserUsageConditionsCheckBox->Value() != 0;
 
        // TODO: Use the same validation as the web-serivce
        bool validUserName = nickName.Length() >= 3;
@@ -356,6 +412,16 @@ UserLoginWindow::_ValidateCreateAccountFields(bool 
alertProblems)
                                "The captcha puzzle needs to be solved.") << 
"\n\n";
                }
 
+               if (!minimumAgeConfirmed) {
+                       message << B_TRANSLATE(
+                               "The minimum age requirements must be met.") << 
"\n\n";
+               }
+
+               if (!userUsageConditionsConfirmed) {
+                       message << B_TRANSLATE(
+                               "The usage conditions for users must be agreed 
to.") << "\n\n";
+               }
+
                BAlert* alert = new(std::nothrow) BAlert(
                        B_TRANSLATE("Input validation"),
                        message,
@@ -407,24 +473,57 @@ UserLoginWindow::_CreateAccount()
 
 
 void
-UserLoginWindow::_RequestCaptcha()
+UserLoginWindow::_CreateAccountSetupIfNecessary()
 {
-       if (Lock()) {
+       uint32 setupMask = 0;
+       if (fCaptchaToken.IsEmpty())
+               setupMask |= CREATE_CAPTCHA;
+       if (fUserUsageConditions == NULL)
+               setupMask |= FETCH_USER_USAGE_CONDITIONS;
+       _CreateAccountSetup(setupMask);
+}
+
+
+void
+UserLoginWindow::_CreateAccountSetup(uint32 mask)
+{
+       if (mask == 0)
+               return;
+
+       BAutolock locker(&fLock);
+
+       if (fWorkerThread >= 0)
+               return;
+
+       if (!Lock())
+               debugger("unable to lock the user login window");
+
+       if ((mask & CREATE_CAPTCHA) != 0) {
                fCaptchaToken = "";
                fCaptchaView->UnsetBitmap();
                fCaptchaImage.Unset();
-               Unlock();
        }
 
-       BAutolock locker(&fLock);
+       if ((mask & FETCH_USER_USAGE_CONDITIONS) != 0) {
+               fConfirmMinimumAgeCheckBox->SetLabel(PLACEHOLDER_TEXT);
+               fConfirmMinimumAgeCheckBox->SetValue(0);
+               fConfirmUserUsageConditionsCheckBox->SetValue(0);
+       }
 
-       if (fWorkerThread >= 0)
-               return;
+       Unlock();
 
-       thread_id thread = spawn_thread(&_RequestCaptchaThreadEntry,
-               "Captcha requester", B_NORMAL_PRIORITY, this);
+       CreateAccountSetupThreadData* threadData = new 
CreateAccountSetupThreadData;
+       threadData->window = this;
+       threadData->mask = mask;
+
+       thread_id thread = spawn_thread(&_CreateAccountSetupThreadEntry,
+               "Create account setup", B_NORMAL_PRIORITY, threadData);
        if (thread >= 0)
                _SetWorkerThread(thread);
+       else {
+               debugger("unable to start a thread to gather data for creating 
an "
+                       "account");
+       }
 }
 
 
@@ -469,6 +568,9 @@ UserLoginWindow::_SetWorkerThread(thread_id thread)
        fEmailField->SetEnabled(enabled);
        fLanguageCodeField->SetEnabled(enabled);
        fCaptchaResultField->SetEnabled(enabled);
+       fConfirmMinimumAgeCheckBox->SetEnabled(enabled);
+       fConfirmUserUsageConditionsCheckBox->SetEnabled(enabled);
+       fUserUsageConditionsLink->SetEnabled(enabled);
        fSendButton->SetEnabled(enabled);
 
        if (thread >= 0) {
@@ -482,6 +584,45 @@ UserLoginWindow::_SetWorkerThread(thread_id thread)
 }
 
 
+void
+UserLoginWindow::_CreateAccountUserUsageConditionsSetupThread()
+{
+       UserUsageConditions conditions;
+       WebAppInterface interface = fModel.GetWebAppInterface();
+
+       if (interface.RetrieveUserUsageConditions(NULL, conditions) == B_OK) {
+               BMessage dataMessage(MSG_USER_USAGE_CONDITIONS_DATA);
+               conditions.Archive(&dataMessage, true);
+               BMessenger(this).SendMessage(&dataMessage);
+       } else {
+               AppUtils::NotifySimpleError(
+                       B_TRANSLATE("User Usage Conditions Download Problem"),
+                       B_TRANSLATE("An error has arisen downloading the user 
usage "
+                               "conditions.  Check the log for details and try 
again."));
+               BMessenger(this).SendMessage(B_QUIT_REQUESTED);
+       }
+}
+
+
+/*! This method is hit when the user usage conditions data arrives back from 
the
+    server.  At this point some of the UI elements may need to be updated.
+*/
+
+void
+UserLoginWindow::_SetUserUsageConditions(
+       UserUsageConditions* userUsageConditions)
+{
+       fUserUsageConditions = userUsageConditions;
+       BString minimumAgeString;
+       minimumAgeString.SetToFormat("%" B_PRId8,
+               fUserUsageConditions->MinimumAge());
+       BString label = B_TRANSLATE(
+               "I am %MinimumAgeYears% years of age or older");
+       label.ReplaceAll("%MinimumAgeYears%", minimumAgeString);
+       fConfirmMinimumAgeCheckBox->SetLabel(label);
+}
+
+
 int32
 UserLoginWindow::_AuthenticateThreadEntry(void* data)
 {
@@ -549,16 +690,22 @@ UserLoginWindow::_AuthenticateThread()
 
 
 int32
-UserLoginWindow::_RequestCaptchaThreadEntry(void* data)
+UserLoginWindow::_CreateAccountSetupThreadEntry(void* data)
 {
-       UserLoginWindow* window = reinterpret_cast<UserLoginWindow*>(data);
-       window->_RequestCaptchaThread();
+       CreateAccountSetupThreadData* threadData =
+               reinterpret_cast<CreateAccountSetupThreadData*>(data);
+       if ((threadData->mask & CREATE_CAPTCHA) != 0)
+               threadData->window->_CreateAccountCaptchaSetupThread();
+       if ((threadData->mask & FETCH_USER_USAGE_CONDITIONS) != 0)
+               
threadData->window->_CreateAccountUserUsageConditionsSetupThread();
+       threadData->window->_SetWorkerThread(-1);
+       delete threadData;
        return 0;
 }
 
 
 void
-UserLoginWindow::_RequestCaptchaThread()
+UserLoginWindow::_CreateAccountCaptchaSetupThread()
 {
        WebAppInterface interface;
        BMessage info;
@@ -593,8 +740,6 @@ UserLoginWindow::_RequestCaptchaThread()
        } else {
                fprintf(stderr, "Failed to obtain captcha: %s\n", 
strerror(status));
        }
-
-       _SetWorkerThread(-1);
 }
 
 
@@ -613,12 +758,22 @@ UserLoginWindow::_CreateAccountThread()
        if (!Lock())
                return;
 
+       if (fUserUsageConditions == NULL)
+               debugger("missing user usage conditions when creating an 
account");
+
+       if (fConfirmMinimumAgeCheckBox->Value() == 0
+               || fConfirmUserUsageConditionsCheckBox->Value() == 0) {
+               debugger("expected that the minimum age and user usage 
conditions are"
+                       "agreed to at this point");
+       }
+
        BString nickName(fNewUsernameField->Text());
        BString passwordClear(fNewPasswordField->Text());
        BString email(fEmailField->Text());
        BString captchaToken(fCaptchaToken);
        BString captchaResponse(fCaptchaResultField->Text());
        BString languageCode(fPreferredLanguageCode);
+       BString userUsageConditionsCode(fUserUsageConditions->Code());
 
        Unlock();
 
@@ -627,7 +782,7 @@ UserLoginWindow::_CreateAccountThread()
 
        status_t status = interface.CreateUser(
                nickName, passwordClear, email, captchaToken, captchaResponse,
-               languageCode, info);
+               languageCode, userUsageConditionsCode, info);
 
        BAutolock locker(&fLock);
 
@@ -678,7 +833,7 @@ UserLoginWindow::_CreateAccountThread()
 
                // We need a new captcha, it can be used only once
                fCaptchaToken = "";
-               _RequestCaptcha();
+               _CreateAccountSetup(CREATE_CAPTCHA);
        } else {
                fModel.SetAuthorization(nickName, passwordClear, true);
 
@@ -739,3 +894,17 @@ UserLoginWindow::_CollectValidationFailures(const 
BMessage& result,
                error << B_TRANSLATE("But none could be listed here, sorry.");
        }
 }
+
+
+/*! Opens a new window that shows the already downloaded user usage conditions.
+*/
+
+void
+UserLoginWindow::_ViewUserUsageConditions()
+{
+       if (fUserUsageConditions == NULL)
+               debugger("the user usage conditions should be set");
+       UserUsageConditionsWindow* window = new UserUsageConditionsWindow(
+               fModel, *fUserUsageConditions);
+       window->Show();
+}
\ No newline at end of file
diff --git a/src/apps/haikudepot/ui/UserLoginWindow.h 
b/src/apps/haikudepot/ui/UserLoginWindow.h
index ee52d452ca..7cc1ee0147 100644
--- a/src/apps/haikudepot/ui/UserLoginWindow.h
+++ b/src/apps/haikudepot/ui/UserLoginWindow.h
@@ -14,11 +14,14 @@
 
 
 class BButton;
+class BCheckBox;
 class BMenuField;
 class BTabView;
 class BTextControl;
 class BitmapView;
+class LinkView;
 class Model;
+class UserUsageConditions;
 
 
 class UserLoginWindow : public BWindow {
@@ -34,6 +37,7 @@ public:
                                                                        const 
BMessage& message);
 
 private:
+
                        enum Mode {
                                NONE = 0,
                                LOGIN,
@@ -45,7 +49,8 @@ private:
                                                                        bool 
alertProblems = false);
                        void                            _Login();
                        void                            _CreateAccount();
-                       void                            _RequestCaptcha();
+                       void                            
_CreateAccountSetup(uint32 mask);
+                       void                            
_CreateAccountSetupIfNecessary();
                        void                            _LoginSuccessful(const 
BString& message);
 
                        void                            
_SetWorkerThread(thread_id thread);
@@ -53,8 +58,12 @@ private:
        static  int32                           _AuthenticateThreadEntry(void* 
data);
                        void                            _AuthenticateThread();
 
-       static  int32                           
_RequestCaptchaThreadEntry(void* data);
-                       void                            _RequestCaptchaThread();
+       static  int32                           
_CreateAccountSetupThreadEntry(void* data);
+                       void                            
_CreateAccountCaptchaSetupThread();
+                       void                            
_CreateAccountUserUsageConditionsSetupThread();
+
+                       void                            _SetUserUsageConditions(
+                                                                       
UserUsageConditions* userUsageConditions);
 
        static  int32                           _CreateAccountThreadEntry(void* 
data);
                        void                            _CreateAccountThread();
@@ -63,6 +72,8 @@ private:
                                                                        const 
BMessage& result,
                                                                        
BString& error) const;
 
+                       void                            
_ViewUserUsageConditions();
+
 private:
                        BMessenger                      fOnSuccessTarget;
                        BMessage                        fOnSuccessMessage;
@@ -79,6 +90,9 @@ private:
                        BMenuField*                     fLanguageCodeField;
                        BitmapView*                     fCaptchaView;
                        BTextControl*           fCaptchaResultField;
+                       BCheckBox*                      
fConfirmMinimumAgeCheckBox;
+                       BCheckBox*                      
fConfirmUserUsageConditionsCheckBox;
+                       LinkView*                       
fUserUsageConditionsLink;
 
                        BButton*                        fSendButton;
                        BButton*                        fCancelButton;
@@ -91,6 +105,9 @@ private:
 
                        Mode                            fMode;
 
+                       UserUsageConditions*
+                                                               
fUserUsageConditions;
+
                        BLocker                         fLock;
                        thread_id                       fWorkerThread;
 };
diff --git a/src/apps/haikudepot/ui/UserUsageConditionsWindow.cpp 
b/src/apps/haikudepot/ui/UserUsageConditionsWindow.cpp
index 829e08d2a2..88853da2d1 100644
--- a/src/apps/haikudepot/ui/UserUsageConditionsWindow.cpp
+++ b/src/apps/haikudepot/ui/UserUsageConditionsWindow.cpp
@@ -43,71 +43,76 @@
 
 #define LINES_INTRODUCTION_TEXT 2
 
+#define WINDOW_FRAME BRect(0, 0, 500, 400)
 
-enum {
-       MSG_USER_USAGE_CONDITIONS_DATA  = 'uucd',
-       MSG_USER_USAGE_CONDITIONS_ERROR = 'uuce'
-};
 
+UserUsageConditionsWindow::UserUsageConditionsWindow(Model& model,
+       UserUsageConditions& userUsageConditions)
+       :
+       BWindow(WINDOW_FRAME, B_TRANSLATE("User Usage Conditions"),
+                       B_FLOATING_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL,
+                       B_ASYNCHRONOUS_CONTROLS | B_AUTO_UPDATE_SIZE_LIMITS
+                               | B_NOT_RESIZABLE | B_NOT_ZOOMABLE),
+       fMode(FIXED),
+       fModel(model),
+       fWorkerThread(-1)
+{
+       _InitUiControls();
+
+       BScrollView* scrollView = new BScrollView("copy scroll view", fCopyView,
+               0, false, true, B_PLAIN_BORDER);
+       BButton* okButton = new BButton("ok", B_TRANSLATE("OK"),
+               new BMessage(B_QUIT_REQUESTED));
+
+       BLayoutBuilder::Group<>(this, B_VERTICAL)
+               .SetInsets(B_USE_WINDOW_INSETS)
+               .Add(fVersionStringView, 1)
+               .Add(scrollView, 97)
+               .Add(fAgeNoteStringView, 1)
+               .AddGroup(B_HORIZONTAL, 1)
+                       .AddGlue()
+                       .Add(okButton)
+                       .End()
+               .End();
 
-UserUsageConditionsWindow::UserUsageConditionsWindow(BWindow* parent,
-       BRect frame, Model& model, UserUsageConditionsSelectionMode mode)
+       CenterOnScreen();
+       _DisplayData(userUsageConditions);
+}
+
+UserUsageConditionsWindow::UserUsageConditionsWindow(
+       Model& model, UserUsageConditionsSelectionMode mode)
        :
-       BWindow(frame, B_TRANSLATE("User Usage Conditions"),
-                       B_FLOATING_WINDOW_LOOK, B_FLOATING_SUBSET_WINDOW_FEEL,
+       BWindow(WINDOW_FRAME, B_TRANSLATE("User Usage Conditions"),
+                       B_FLOATING_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL,
                        B_ASYNCHRONOUS_CONTROLS | B_AUTO_UPDATE_SIZE_LIMITS
                                | B_NOT_RESIZABLE | B_NOT_ZOOMABLE),
        fMode(mode),
        fModel(model),
        fWorkerThread(-1)
 {
-       AddToSubset(parent);
-
        if (mode != LATEST)
                debugger("only the LATEST user usage conditions are handled for 
now");
 
+       _InitUiControls();
+
        fWorkerIndicator = new BarberPole("fetch data worker indicator");
        BSize workerIndicatorSize;
        workerIndicatorSize.SetHeight(20);
        fWorkerIndicator->SetExplicitMinSize(workerIndicatorSize);
 
-       fCopyView = new MarkupTextView("copy view");
-       fCopyView->SetViewUIColor(B_NO_COLOR);
-       fCopyView->SetLowColor(RGB_COLOR_WHITE);
-       fCopyView->SetInsets(8.0f);
-
-       BScrollView* scrollView = new BScrollView("copy scroll view", fCopyView,
-               0, false, true, B_PLAIN_BORDER);
-
        BTextView* introductionTextView = new BTextView("introduction text 
view");
        introductionTextView->AdoptSystemColors();
        introductionTextView->MakeEditable(false);
        introductionTextView->MakeSelectable(false);
        
introductionTextView->SetText(B_TRANSLATE(_IntroductionTextForMode(mode)));
 
-       fAgeNoteStringView = new BStringView("age note string view",
-               PLACEHOLDER_TEXT);
-       fAgeNoteStringView->AdoptSystemColors();
-       fAgeNoteStringView->SetExplicitMaxSize(
-               BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET));
-
-       BFont versionFont(be_plain_font);
-       versionFont.SetSize(9.0);
-
-       fVersionStringView = new BStringView("version string view",
-               PLACEHOLDER_TEXT);
-       fVersionStringView->AdoptSystemColors();
-       fVersionStringView->SetFont(&versionFont);
-       fVersionStringView->SetAlignment(B_ALIGN_RIGHT);
-       fVersionStringView->SetHighUIColor(B_PANEL_TEXT_COLOR, B_DARKEN_3_TINT);
-       fVersionStringView->SetExplicitMaxSize(
-               BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET));
-
        BSize introductionSize;
        introductionSize.SetHeight(
                _ExpectedIntroductionTextHeight(introductionTextView));
        introductionTextView->SetExplicitPreferredSize(introductionSize);
 
+       BScrollView* scrollView = new BScrollView("copy scroll view", fCopyView,
+               0, false, true, B_PLAIN_BORDER);
        BButton* okButton = new BButton("ok", B_TRANSLATE("OK"),
                new BMessage(B_QUIT_REQUESTED));
 
@@ -116,7 +121,7 @@ 
UserUsageConditionsWindow::UserUsageConditionsWindow(BWindow* parent,
                .Add(introductionTextView, 1)
                .AddGlue()
                .Add(fVersionStringView, 1)
-               .Add(scrollView, 96)
+               .Add(scrollView, 95)
                .Add(fAgeNoteStringView, 1)
                .AddGroup(B_HORIZONTAL, 1)
                        .AddGlue()
@@ -125,7 +130,7 @@ 
UserUsageConditionsWindow::UserUsageConditionsWindow(BWindow* parent,
                .Add(fWorkerIndicator, 1)
                .End();
 
-       CenterIn(parent->Frame());
+       CenterOnScreen();
 
        _FetchData();
                // start a new thread to pull down the user usage conditions 
data.
@@ -137,6 +142,38 @@ UserUsageConditionsWindow::~UserUsageConditionsWindow()
 }
 
 
+/*! This sets up the UI controls / interface elements that are not specific to
+    a given mode of viewing.
+*/
+
+void
+UserUsageConditionsWindow::_InitUiControls()
+{
+       fCopyView = new MarkupTextView("copy view");
+       fCopyView->SetViewUIColor(B_NO_COLOR);
+       fCopyView->SetLowColor(RGB_COLOR_WHITE);
+       fCopyView->SetInsets(8.0f);
+
+       fAgeNoteStringView = new BStringView("age note string view",
+               PLACEHOLDER_TEXT);
+       fAgeNoteStringView->AdoptSystemColors();
+       fAgeNoteStringView->SetExplicitMaxSize(
+               BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET));
+
+       BFont versionFont(be_plain_font);
+       versionFont.SetSize(9.0);
+
+       fVersionStringView = new BStringView("version string view",
+               PLACEHOLDER_TEXT);
+       fVersionStringView->AdoptSystemColors();
+       fVersionStringView->SetFont(&versionFont);
+       fVersionStringView->SetAlignment(B_ALIGN_RIGHT);
+       fVersionStringView->SetHighUIColor(B_PANEL_TEXT_COLOR, B_DARKEN_3_TINT);
+       fVersionStringView->SetExplicitMaxSize(
+               BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET));
+}
+
+
 void
 UserUsageConditionsWindow::MessageReceived(BMessage* message)
 {
diff --git a/src/apps/haikudepot/ui/UserUsageConditionsWindow.h 
b/src/apps/haikudepot/ui/UserUsageConditionsWindow.h
index 07c4fdcaff..6e8facc0e9 100644
--- a/src/apps/haikudepot/ui/UserUsageConditionsWindow.h
+++ b/src/apps/haikudepot/ui/UserUsageConditionsWindow.h
@@ -22,14 +22,17 @@ class Model;
 
 enum UserUsageConditionsSelectionMode {
        LATEST          = 1,
-       USER            = 2
+       USER            = 2,
+       FIXED           = 3
+               // means that the user usage conditions are supplied to the 
window.
 };
 
 
 class UserUsageConditionsWindow : public BWindow {
 public:
-                                                               
UserUsageConditionsWindow(BWindow* parent,
-                                                                       BRect 
frame, Model& model,
+                                                               
UserUsageConditionsWindow(Model& model,
+                                                                       
UserUsageConditions& userUsageConditions);
+                                                               
UserUsageConditionsWindow(Model& model,
                                                                        
UserUsageConditionsSelectionMode mode);
        virtual                                         
~UserUsageConditionsWindow();
 
@@ -37,6 +40,8 @@ public:
        virtual bool                            QuitRequested();
 
 private:
+       void                                            _InitUiControls();
+
        static const BString            _VersionText(const BString& code);
        static const BString            _MinimumAgeText(uint8 minimumAge);
        static const BString            _IntroductionTextForMode(


Other related posts:

  • » [haiku-commits] haiku: hrev53472 - in src/apps/haikudepot: ui server . - Andrew Lindesay