[haiku-commits] haiku: hrev53447 - in src/apps/haikudepot: ui server model

  • From: waddlesplash <waddlesplash@xxxxxxxxx>
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Sat, 31 Aug 2019 23:08:13 -0400 (EDT)

hrev53447 adds 1 changeset to branch 'master'
old head: 75e57397725ad811f905684682387a85053afb05
new head: 01339a54db48e4aaa7624b2d2159a8cbd90bf197
overview: 
https://git.haiku-os.org/haiku/log/?qt=range&q=01339a54db48+%5E75e57397725a

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

01339a54db48: HaikuDepot: Display User Usage Conditions
  
  This change will allow the user to view the user
  usage conditions from the HDS system in a
  HaikuDepot window.  The display of the text is not
  currently well formatted in that the Markdown is
  not yet properly parsed, but the display of the
  data is working.
  
  Relates to 15209
  
  Change-Id: Ia6ad4ef995f5fe3c29c40221964e44d4554a033d
  Reviewed-on: https://review.haiku-os.org/c/haiku/+/1750
  Reviewed-by: waddlesplash <waddlesplash@xxxxxxxxx>

                                    [ Andrew Lindesay <apl@xxxxxxxxxxxxxx> ]

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

Revision:    hrev53447
Commit:      01339a54db48e4aaa7624b2d2159a8cbd90bf197
URL:         https://git.haiku-os.org/haiku/commit/?id=01339a54db48
Author:      Andrew Lindesay <apl@xxxxxxxxxxxxxx>
Date:        Tue Jul  9 11:23:14 2019 UTC
Committer:   waddlesplash <waddlesplash@xxxxxxxxx>
Commit-Date: Sun Sep  1 03:08:11 2019 UTC

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

12 files changed, 706 insertions(+), 49 deletions(-)
src/apps/haikudepot/HaikuDepotConstants.h        |   3 +
src/apps/haikudepot/Jamfile                      |   2 +
src/apps/haikudepot/model/LocalIconStore.h       |   2 -
.../haikudepot/model/UserUsageConditions.cpp     | 100 ++++++
src/apps/haikudepot/model/UserUsageConditions.h  |  37 +++
src/apps/haikudepot/server/WebAppInterface.cpp   | 161 ++++++++--
src/apps/haikudepot/server/WebAppInterface.h     |  12 +
src/apps/haikudepot/ui/MainWindow.cpp            |  54 +++-
src/apps/haikudepot/ui/MainWindow.h              |   2 +
src/apps/haikudepot/ui/RatePackageWindow.cpp     |   2 +-
.../haikudepot/ui/UserUsageConditionsWindow.cpp  | 314 +++++++++++++++++++
.../haikudepot/ui/UserUsageConditionsWindow.h    |  66 ++++

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

diff --git a/src/apps/haikudepot/HaikuDepotConstants.h 
b/src/apps/haikudepot/HaikuDepotConstants.h
index 9671451c7e..97014a1d20 100644
--- a/src/apps/haikudepot/HaikuDepotConstants.h
+++ b/src/apps/haikudepot/HaikuDepotConstants.h
@@ -27,6 +27,9 @@ enum {
 #define RATING_MIN                                             0.0f
 
 
+#define RGB_COLOR_WHITE                                                
(rgb_color) { 255, 255, 255, 255 }
+
+
 #define HD_ERROR_BASE                                  (B_ERRORS_END + 1)
 #define HD_NETWORK_INACCESSIBLE                        (HD_ERROR_BASE + 1)
 #define HD_CLIENT_TOO_OLD                              (HD_ERROR_BASE + 2)
diff --git a/src/apps/haikudepot/Jamfile b/src/apps/haikudepot/Jamfile
index dbc2ef984f..f6912f45a9 100644
--- a/src/apps/haikudepot/Jamfile
+++ b/src/apps/haikudepot/Jamfile
@@ -143,6 +143,8 @@ local applicationSources =
        ScrollableGroupView.cpp
        SharedBitmap.cpp
        UserLoginWindow.cpp
+       UserUsageConditions.cpp
+       UserUsageConditionsWindow.cpp
        WorkStatusView.cpp
 
        # network + server / local processes
diff --git a/src/apps/haikudepot/model/LocalIconStore.h 
b/src/apps/haikudepot/model/LocalIconStore.h
index 5745d21137..008b1fcf95 100644
--- a/src/apps/haikudepot/model/LocalIconStore.h
+++ b/src/apps/haikudepot/model/LocalIconStore.h
@@ -2,8 +2,6 @@
  * Copyright 2017, Andrew Lindesay <apl@xxxxxxxxxxxxxx>.
  * All rights reserved. Distributed under the terms of the MIT License.
  */
-
-
 #ifndef LOCAL_ICON_STORE_H
 #define LOCAL_ICON_STORE_H
 
diff --git a/src/apps/haikudepot/model/UserUsageConditions.cpp 
b/src/apps/haikudepot/model/UserUsageConditions.cpp
new file mode 100644
index 0000000000..24fc6fdf54
--- /dev/null
+++ b/src/apps/haikudepot/model/UserUsageConditions.cpp
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2019, Andrew Lindesay <apl@xxxxxxxxxxxxxx>.
+ *
+ * All rights reserved. Distributed under the terms of the MIT License.
+ */
+#include "UserUsageConditions.h"
+
+
+// These are keys that are used to store this object's data into a BMessage
+// instance.
+
+#define KEY_COPY_MARKDOWN      "copyMarkdown"
+#define KEY_CODE                       "code"
+#define KEY_MINIMUM_AGE                "minimumAge"
+
+
+UserUsageConditions::UserUsageConditions(BMessage* from)
+       :
+       fCode(""),
+       fCopyMarkdown(""),
+       fMinimumAge(0)
+{
+       int16 minimumAge;
+
+       if (from->FindInt16(KEY_MINIMUM_AGE, &minimumAge) != B_OK)
+               printf("expected key [%s] in the message data\n", 
KEY_MINIMUM_AGE);
+       fMinimumAge = (uint8) minimumAge;
+
+       if (from->FindString(KEY_CODE, &fCode) != B_OK)
+               printf("expected key [%s] in the message data\n", KEY_CODE);
+
+       if (from->FindString(KEY_COPY_MARKDOWN, &fCopyMarkdown) != B_OK)
+               printf("expected key [%s] in the message data\n", 
KEY_COPY_MARKDOWN);
+}
+
+
+UserUsageConditions::UserUsageConditions()
+       :
+       fCode(""),
+       fCopyMarkdown(""),
+       fMinimumAge(0)
+{
+}
+
+
+UserUsageConditions::~UserUsageConditions()
+{
+}
+
+
+const BString&
+UserUsageConditions::Code() const
+{
+       return fCode;
+}
+
+
+const uint8
+UserUsageConditions::MinimumAge() const
+{
+       return fMinimumAge;
+}
+
+
+const BString&
+UserUsageConditions::CopyMarkdown() const
+{
+       return fCopyMarkdown;
+}
+
+
+void
+UserUsageConditions::SetCode(const BString& code)
+{
+       fCode = code;
+}
+
+
+void
+UserUsageConditions::SetMinimumAge(uint8 age)
+{
+       fMinimumAge = age;
+}
+
+
+void
+UserUsageConditions::SetCopyMarkdown(const BString& copyMarkdown)
+{
+       fCopyMarkdown = copyMarkdown;
+}
+
+
+status_t
+UserUsageConditions::Archive(BMessage* into, bool deep) const
+{
+       into->AddInt16(KEY_MINIMUM_AGE, (int16) fMinimumAge);
+       into->AddString(KEY_CODE, fCode);
+       into->AddString(KEY_COPY_MARKDOWN, fCopyMarkdown);
+       return B_OK;
+}
\ No newline at end of file
diff --git a/src/apps/haikudepot/model/UserUsageConditions.h 
b/src/apps/haikudepot/model/UserUsageConditions.h
new file mode 100644
index 0000000000..5dffca35e4
--- /dev/null
+++ b/src/apps/haikudepot/model/UserUsageConditions.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2019, Andrew Lindesay <apl@xxxxxxxxxxxxxx>.
+ *
+ * All rights reserved. Distributed under the terms of the MIT License.
+ */
+#ifndef USER_USAGE_CONDITIONS_H
+#define USER_USAGE_CONDITIONS_H
+
+#include <stdio.h>
+
+#include <Archivable.h>
+#include <String.h>
+
+
+class UserUsageConditions : public BArchivable {
+public:
+                                                               
UserUsageConditions(BMessage* from);
+                                                               
UserUsageConditions();
+       virtual                                         ~UserUsageConditions();
+
+       const   BString&                        Code() const;
+       const   uint8                           MinimumAge() const;
+       const   BString&                        CopyMarkdown() const;
+
+                       void                            SetCode(const BString& 
code);
+                       void                            SetMinimumAge(uint8 
age);
+                       void                            SetCopyMarkdown(const 
BString& copyMarkdown);
+
+                       status_t                        Archive(BMessage* into, 
bool deep = true) const;
+private:
+                       BString                         fCode;
+                       BString                         fCopyMarkdown;
+                       uint8                           fMinimumAge;
+};
+
+
+#endif // USER_USAGE_CONDITIONS_H
diff --git a/src/apps/haikudepot/server/WebAppInterface.cpp 
b/src/apps/haikudepot/server/WebAppInterface.cpp
index 30231264a3..3928b50d45 100644
--- a/src/apps/haikudepot/server/WebAppInterface.cpp
+++ b/src/apps/haikudepot/server/WebAppInterface.cpp
@@ -411,6 +411,102 @@ WebAppInterface::RetrieveUserRating(const BString& 
packageName,
 }
 
 
+/*! \brief Returns data relating to the user usage conditions
+
+       \param code defines the version of the data to return or if empty then 
the
+               latest is returned.
+
+    This method will go to the server and get details relating to the user 
usage
+    conditions.  It does this in two API calls; first gets the details (the
+    minimum age) and in the second call, the text of the conditions is 
returned.
+*/
+
+status_t
+WebAppInterface::RetrieveUserUsageConditions(const BString& code,
+       UserUsageConditions& conditions)
+{
+       BMessage responseEnvelopeMessage;
+       status_t result = _RetrieveUserUsageConditionsMeta(code,
+               responseEnvelopeMessage);
+
+       if (result != B_OK)
+               return result;
+
+       BMessage resultMessage;
+       if (responseEnvelopeMessage.FindMessage("result", &resultMessage) != 
B_OK) {
+               fprintf(stderr, "bad response envelope missing 'result' 
entry\n");
+               return B_BAD_DATA;
+       }
+
+       BString metaDataCode;
+       double metaDataMinimumAge;
+       BString copyMarkdown;
+
+       if ( (resultMessage.FindString("code", &metaDataCode) != B_OK)
+               || (resultMessage.FindDouble(
+                       "minimumAge", &metaDataMinimumAge) != B_OK) ) {
+               printf("unexpected response from server with missing user usage 
"
+                       "conditions data\n");
+               return B_BAD_DATA;
+       }
+
+       BMallocIO* copyMarkdownData = new BMallocIO();
+       result = _RetrieveUserUsageConditionsCopy(metaDataCode, 
copyMarkdownData);
+
+       if (result != B_OK)
+               return result;
+
+       conditions.SetCode(metaDataCode);
+       conditions.SetMinimumAge(metaDataMinimumAge);
+       conditions.SetCopyMarkdown(
+               BString(static_cast<const char*>(copyMarkdownData->Buffer()),
+                       copyMarkdownData->BufferLength()));
+
+       return B_OK;
+}
+
+
+status_t
+WebAppInterface::_RetrieveUserUsageConditionsMeta(const BString& code,
+       BMessage& message)
+{
+       BMallocIO* requestEnvelopeData = new BMallocIO();
+       BJsonTextWriter requestEnvelopeWriter(requestEnvelopeData);
+
+       requestEnvelopeWriter.WriteObjectStart();
+       _WriteStandardJsonRpcEnvelopeValues(requestEnvelopeWriter,
+               "getUserUsageConditions");
+       requestEnvelopeWriter.WriteObjectName("params");
+       requestEnvelopeWriter.WriteArrayStart();
+
+       requestEnvelopeWriter.WriteObjectStart();
+
+       if (!code.IsEmpty()) {
+               requestEnvelopeWriter.WriteObjectName("code");
+               requestEnvelopeWriter.WriteString(code.String());
+       }
+
+       requestEnvelopeWriter.WriteObjectEnd();
+       requestEnvelopeWriter.WriteArrayEnd();
+       requestEnvelopeWriter.WriteObjectEnd();
+
+       // now fetch this information into an object.
+
+       return _SendJsonRequest("user", requestEnvelopeData,
+               _LengthAndSeekToZero(requestEnvelopeData), 0, message);
+}
+
+
+status_t
+WebAppInterface::_RetrieveUserUsageConditionsCopy(const BString& code,
+       BDataIO* stream)
+{
+       return _SendRawGetRequest(
+               BString("/__user/usageconditions/") << code << "/document.md",
+               stream);
+}
+
+
 status_t
 WebAppInterface::CreateUserRating(const BString& packageName,
        const BPackageVersion& version,
@@ -555,36 +651,9 @@ status_t
 WebAppInterface::RetrieveScreenshot(const BString& code,
        int32 width, int32 height, BDataIO* stream)
 {
-       BUrl url = ServerSettings::CreateFullUrl(
+       return _SendRawGetRequest(
                BString("/__pkgscreenshot/") << code << ".png" << "?tw="
-                       << width << "&th=" << height);
-
-       bool isSecure = url.Protocol() == "https";
-
-       ProtocolListener listener(Logger::IsTraceEnabled());
-       listener.SetDownloadIO(stream);
-
-       BHttpHeaders headers;
-       ServerSettings::AugmentHeaders(headers);
-
-       BHttpRequest request(url, isSecure, "HTTP", &listener);
-       request.SetMethod(B_HTTP_GET);
-       request.SetHeaders(headers);
-
-       thread_id thread = request.Run();
-       wait_for_thread(thread, NULL);
-
-       const BHttpResult& result = dynamic_cast<const BHttpResult&>(
-               request.Result());
-
-       int32 statusCode = result.StatusCode();
-
-       if (statusCode == 200)
-               return B_OK;
-
-       fprintf(stderr, "failed to get screenshot from '%s': %" B_PRIi32 "\n",
-               url.UrlString().String(), statusCode);
-       return B_ERROR;
+                       << width << "&th=" << height, stream);
 }
 
 
@@ -830,6 +899,40 @@ WebAppInterface::_SendJsonRequest(const char* domain, 
const BString& jsonString,
 }
 
 
+status_t
+WebAppInterface::_SendRawGetRequest(const BString urlPathComponents,
+       BDataIO* stream)
+{
+       BUrl url = ServerSettings::CreateFullUrl(urlPathComponents);
+       bool isSecure = url.Protocol() == "https";
+
+       ProtocolListener listener(Logger::IsTraceEnabled());
+       listener.SetDownloadIO(stream);
+
+       BHttpHeaders headers;
+       ServerSettings::AugmentHeaders(headers);
+
+       BHttpRequest request(url, isSecure, "HTTP", &listener);
+       request.SetMethod(B_HTTP_GET);
+       request.SetHeaders(headers);
+
+       thread_id thread = request.Run();
+       wait_for_thread(thread, NULL);
+
+       const BHttpResult& result = dynamic_cast<const BHttpResult&>(
+               request.Result());
+
+       int32 statusCode = result.StatusCode();
+
+       if (statusCode == 200)
+               return B_OK;
+
+       fprintf(stderr, "failed to get data from '%s': %" B_PRIi32 "\n",
+               url.UrlString().String(), statusCode);
+       return B_ERROR;
+}
+
+
 void
 WebAppInterface::_LogPayload(BPositionIO* requestData, size_t size)
 {
diff --git a/src/apps/haikudepot/server/WebAppInterface.h 
b/src/apps/haikudepot/server/WebAppInterface.h
index 4b99fa231f..4eb8ac29d4 100644
--- a/src/apps/haikudepot/server/WebAppInterface.h
+++ b/src/apps/haikudepot/server/WebAppInterface.h
@@ -13,6 +13,7 @@
 #include <package/PackageVersion.h>
 
 #include "List.h"
+#include "UserUsageConditions.h"
 
 
 class BDataIO;
@@ -88,6 +89,10 @@ public:
                                                                        int 
rating, bool active,
                                                                        
BMessage& message);
 
+                       status_t                        
RetrieveUserUsageConditions(
+                                                                       const 
BString& code,
+                                                                       
UserUsageConditions& conditions);
+
                        status_t                        RetrieveScreenshot(
                                                                        const 
BString& code,
                                                                        int32 
width, int32 height,
@@ -110,6 +115,13 @@ public:
        static int32                            ErrorCodeFromResponse(BMessage& 
response);
 
 private:
+                       status_t                        _SendRawGetRequest(
+                                                                       const 
BString urlPathComponents,
+                                                                       
BDataIO* stream);
+                       status_t                        
_RetrieveUserUsageConditionsMeta(
+                                                                       const 
BString& code, BMessage& message);
+                       status_t                        
_RetrieveUserUsageConditionsCopy(
+                                                                       const 
BString& code, BDataIO* stream);
                        void                            
_WriteStandardJsonRpcEnvelopeValues(
                                                                        
BJsonWriter& writer,
                                                                        const 
char* methodName);
diff --git a/src/apps/haikudepot/ui/MainWindow.cpp 
b/src/apps/haikudepot/ui/MainWindow.cpp
index e0a32ec567..270623045f 100644
--- a/src/apps/haikudepot/ui/MainWindow.cpp
+++ b/src/apps/haikudepot/ui/MainWindow.cpp
@@ -48,6 +48,7 @@
 #include "support.h"
 #include "ScreenshotWindow.h"
 #include "UserLoginWindow.h"
+#include "UserUsageConditionsWindow.h"
 #include "WorkStatusView.h"
 
 
@@ -56,23 +57,24 @@
 
 
 enum {
-       MSG_BULK_LOAD_DONE              = 'mmwd',
-       MSG_REFRESH_REPOS                       = 'mrrp',
-       MSG_MANAGE_REPOS                        = 'mmrp',
-       MSG_SOFTWARE_UPDATER            = 'mswu',
-       MSG_LOG_IN                                      = 'lgin',
-       MSG_LOG_OUT                                     = 'lgot',
-       MSG_AUTHORIZATION_CHANGED       = 'athc',
-       MSG_CATEGORIES_LIST_CHANGED     = 'clic',
-       MSG_PACKAGE_CHANGED                     = 'pchd',
-       MSG_WORK_STATUS_CHANGE          = 'wsch',
-       MSG_WORK_STATUS_CLEAR           = 'wscl',
-
-       MSG_SHOW_FEATURED_PACKAGES      = 'sofp',
-       MSG_SHOW_AVAILABLE_PACKAGES     = 'savl',
-       MSG_SHOW_INSTALLED_PACKAGES     = 'sins',
-       MSG_SHOW_SOURCE_PACKAGES        = 'ssrc',
-       MSG_SHOW_DEVELOP_PACKAGES       = 'sdvl'
+       MSG_BULK_LOAD_DONE                                              = 
'mmwd',
+       MSG_REFRESH_REPOS                                               = 
'mrrp',
+       MSG_MANAGE_REPOS                                                = 
'mmrp',
+       MSG_SOFTWARE_UPDATER                                    = 'mswu',
+       MSG_LOG_IN                                                              
= 'lgin',
+       MSG_LOG_OUT                                                             
= 'lgot',
+       MSG_AUTHORIZATION_CHANGED                               = 'athc',
+       MSG_CATEGORIES_LIST_CHANGED                             = 'clic',
+       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',
+       MSG_SHOW_INSTALLED_PACKAGES                             = 'sins',
+       MSG_SHOW_SOURCE_PACKAGES                                = 'ssrc',
+       MSG_SHOW_DEVELOP_PACKAGES                               = 'sdvl'
 };
 
 
@@ -334,6 +336,10 @@ MainWindow::MessageReceived(BMessage* message)
                        fModel.SetUsername("");
                        break;
 
+               case MSG_VIEW_LATEST_USER_USAGE_CONDITIONS:
+                       _ViewLatestUserUsageConditions();
+                       break;
+
                case MSG_AUTHORIZATION_CHANGED:
                        _UpdateAuthorization();
                        break;
@@ -734,6 +740,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);
+
        menuBar->AddItem(fUserMenu);
 }
 
@@ -1332,3 +1343,12 @@ MainWindow::_ShowScreenshot()
 
        fScreenshotWindow->Unlock();
 }
+
+
+void
+MainWindow::_ViewLatestUserUsageConditions()
+{
+       UserUsageConditionsWindow* window = new UserUsageConditionsWindow(
+               this, BRect(0, 0, 500, 400), fModel, LATEST);
+       window->Show();
+}
\ No newline at end of file
diff --git a/src/apps/haikudepot/ui/MainWindow.h 
b/src/apps/haikudepot/ui/MainWindow.h
index 9210824bcf..841b2800ff 100644
--- a/src/apps/haikudepot/ui/MainWindow.h
+++ b/src/apps/haikudepot/ui/MainWindow.h
@@ -101,6 +101,8 @@ private:
                        void                            _RatePackage();
                        void                            _ShowScreenshot();
 
+                       void                            
_ViewLatestUserUsageConditions();
+
 private:
                        FilterView*                     fFilterView;
                        TabView*                        fListTabs;
diff --git a/src/apps/haikudepot/ui/RatePackageWindow.cpp 
b/src/apps/haikudepot/ui/RatePackageWindow.cpp
index e4a7c4aba4..1743043d29 100644
--- a/src/apps/haikudepot/ui/RatePackageWindow.cpp
+++ b/src/apps/haikudepot/ui/RatePackageWindow.cpp
@@ -465,7 +465,7 @@ RatePackageWindow::_SetWorkerThread(thread_id thread)
 }
 
 
-int32
+/*static*/ int32
 RatePackageWindow::_QueryRatingThreadEntry(void* data)
 {
        RatePackageWindow* window = reinterpret_cast<RatePackageWindow*>(data);
diff --git a/src/apps/haikudepot/ui/UserUsageConditionsWindow.cpp 
b/src/apps/haikudepot/ui/UserUsageConditionsWindow.cpp
new file mode 100644
index 0000000000..829e08d2a2
--- /dev/null
+++ b/src/apps/haikudepot/ui/UserUsageConditionsWindow.cpp
@@ -0,0 +1,314 @@
+/*
+ * Copyright 2019, Andrew Lindesay <apl@xxxxxxxxxxxxxx>.
+ * All rights reserved. Distributed under the terms of the MIT License.
+ */
+
+#include "UserUsageConditionsWindow.h"
+
+#include <Button.h>
+#include <Catalog.h>
+#include <Font.h>
+#include <LayoutBuilder.h>
+#include <ScrollView.h>
+#include <StringView.h>
+#include <TextView.h>
+
+#include "AppUtils.h"
+#include "BarberPole.h"
+#include "HaikuDepotConstants.h"
+#include "Logger.h"
+#include "MarkupTextView.h"
+#include "Model.h"
+#include "UserUsageConditions.h"
+#include "WebAppInterface.h"
+
+
+#undef B_TRANSLATION_CONTEXT
+#define B_TRANSLATION_CONTEXT "UserUsageConditions"
+
+#define PLACEHOLDER_TEXT "..."
+
+#define INTRODUCTION_TEXT_LATEST "HaikuDepot communicates with a " \
+       "sever component called HaikuDepotServer.  These are the latest user " \
+       "usage conditions for use of the HaikuDepotServer service."
+
+#define INTRODUCTION_TEXT_USER "HaikuDepot communicates with a " \
+       "sever component called HaikuDepotServer.  These are the user usage " \
+       "conditions that the user has agreed to in relation to the use of the " 
\
+       "HaikuDepotServer service."
+
+/*!    This is the anticipated number of lines of test that appear in the
+       introduction.
+*/
+
+#define LINES_INTRODUCTION_TEXT 2
+
+
+enum {
+       MSG_USER_USAGE_CONDITIONS_DATA  = 'uucd',
+       MSG_USER_USAGE_CONDITIONS_ERROR = 'uuce'
+};
+
+
+UserUsageConditionsWindow::UserUsageConditionsWindow(BWindow* parent,
+       BRect frame, Model& model, UserUsageConditionsSelectionMode mode)
+       :
+       BWindow(frame, B_TRANSLATE("User Usage Conditions"),
+                       B_FLOATING_WINDOW_LOOK, B_FLOATING_SUBSET_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");
+
+       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);
+
+       BButton* okButton = new BButton("ok", B_TRANSLATE("OK"),
+               new BMessage(B_QUIT_REQUESTED));
+
+       BLayoutBuilder::Group<>(this, B_VERTICAL)
+               .SetInsets(B_USE_WINDOW_INSETS)
+               .Add(introductionTextView, 1)
+               .AddGlue()
+               .Add(fVersionStringView, 1)
+               .Add(scrollView, 96)
+               .Add(fAgeNoteStringView, 1)
+               .AddGroup(B_HORIZONTAL, 1)
+                       .AddGlue()
+                       .Add(okButton)
+                       .End()
+               .Add(fWorkerIndicator, 1)
+               .End();
+
+       CenterIn(parent->Frame());
+
+       _FetchData();
+               // start a new thread to pull down the user usage conditions 
data.
+}
+
+
+UserUsageConditionsWindow::~UserUsageConditionsWindow()
+{
+}
+
+
+void
+UserUsageConditionsWindow::MessageReceived(BMessage* message)
+{
+       switch (message->what) {
+               case MSG_USER_USAGE_CONDITIONS_DATA:
+               {
+                       UserUsageConditions data(message);
+                       _DisplayData(data);
+                       fWorkerIndicator->Stop();
+                       break;
+               }
+               default:
+                       BWindow::MessageReceived(message);
+                       break;
+       }
+}
+
+
+bool
+UserUsageConditionsWindow::QuitRequested()
+{
+       // for now we just don't allow the quit when the background thread
+       // is processing.  In the future it would be good if the HTTP
+       // requests were re-organized such that cancellations were easier to
+       // implement.
+
+       if (fWorkerThread == -1)
+               return true;
+       if (Logger::IsInfoEnabled()) {
+               fprintf(stderr, "unable to quit when the user usage "
+                       "conditions window is still fetching data\n");
+       }
+       return false;
+}
+
+
+/*!    This method is called on the main thread in order to initiate the 
background
+       processing to obtain the user usage conditions data.  It will take
+       responsibility for coordinating the creation of the thread and starting 
the
+       thread etc...
+*/
+
+void
+UserUsageConditionsWindow::_FetchData()
+{
+       if (-1 != fWorkerThread)
+               debugger("illegal state - attempt to fetch, but fetch in 
progress");
+       thread_id thread = spawn_thread(&_FetchDataThreadEntry,
+               "Fetch user usage conditions data", B_NORMAL_PRIORITY, this);
+       if (thread >= 0) {
+               fWorkerIndicator->Start();
+               _SetWorkerThread(thread);
+               resume_thread(fWorkerThread);
+       } else {
+               debugger("unable to start a thread to fetch the user usage "
+                       "conditions.");
+       }
+}
+
+
+/*!    This method is called from the thread in order to start the thread; it 
is
+       the entry-point for the background processing to obtain the user usage
+       conditions.
+*/
+
+/*static*/ int32
+UserUsageConditionsWindow::_FetchDataThreadEntry(void* data)
+{
+       UserUsageConditionsWindow* win
+               = reinterpret_cast<UserUsageConditionsWindow*>(data);
+       win->_FetchDataPerform();
+       return 0;
+}
+
+
+/*!    This method will perform the task of obtaining data about the user usage
+       conditions.
+*/
+
+void
+UserUsageConditionsWindow::_FetchDataPerform()
+{
+       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);
+       }
+
+       _SetWorkerThread(-1);
+}
+
+
+void
+UserUsageConditionsWindow::_SetWorkerThread(thread_id thread)
+{
+       if (!Lock()) {
+               if (Logger::IsInfoEnabled())
+                       fprintf(stderr, "failed to lock window\n");
+       } else {
+               fWorkerThread = thread;
+               Unlock();
+       }
+}
+
+
+void
+UserUsageConditionsWindow::_DisplayData(const UserUsageConditions& data)
+{
+       fCopyView->SetText(data.CopyMarkdown());
+       fAgeNoteStringView->SetText(_MinimumAgeText(data.MinimumAge()));
+       fVersionStringView->SetText(_VersionText(data.Code()));
+}
+
+
+/*static*/ const BString
+UserUsageConditionsWindow::_VersionText(const BString& code)
+{
+       BString versionText(
+               B_TRANSLATE("Version %Code%"));
+       versionText.ReplaceAll("%Code%", code);
+       return versionText;
+}
+
+
+/*static*/ const BString
+UserUsageConditionsWindow::_MinimumAgeText(uint8 minimumAge)
+{
+       BString minimumAgeString;
+       minimumAgeString.SetToFormat("%" B_PRId8, minimumAge);
+       BString ageNoteText(
+               B_TRANSLATE("Users are required to be %AgeYears% years of age 
or "
+                       "older."));
+       ageNoteText.ReplaceAll("%AgeYears%", minimumAgeString);
+       return ageNoteText;
+}
+
+
+/*static*/ const BString
+UserUsageConditionsWindow::_IntroductionTextForMode(
+       UserUsageConditionsSelectionMode mode)
+{
+       switch (mode) {
+               case LATEST:
+                       return INTRODUCTION_TEXT_LATEST;
+               case USER:
+                       return INTRODUCTION_TEXT_USER;
+               default:
+                       return "???";
+       }
+}
+
+
+/*static*/ float
+UserUsageConditionsWindow::_ExpectedIntroductionTextHeight(
+       BTextView* introductionTextView)
+{
+       float insetTop;
+       float insetBottom;
+       introductionTextView->GetInsets(NULL, &insetTop, NULL, &insetBottom);
+
+       BSize introductionSize;
+       font_height fh;
+       be_plain_font->GetHeight(&fh);
+       return ((fh.ascent + fh.descent + fh.leading) * LINES_INTRODUCTION_TEXT)
+               + insetTop + insetBottom;
+}
diff --git a/src/apps/haikudepot/ui/UserUsageConditionsWindow.h 
b/src/apps/haikudepot/ui/UserUsageConditionsWindow.h
new file mode 100644
index 0000000000..07c4fdcaff
--- /dev/null
+++ b/src/apps/haikudepot/ui/UserUsageConditionsWindow.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2019, Andrew Lindesay <apl@xxxxxxxxxxxxxx>.
+ * All rights reserved. Distributed under the terms of the MIT License.
+ */
+#ifndef USER_USAGE_CONDITIONS_WINDOW_H
+#define USER_USAGE_CONDITIONS_WINDOW_H
+
+#include <Locker.h>
+#include <Messenger.h>
+#include <Window.h>
+
+#include "PackageInfo.h"
+#include "UserUsageConditions.h"
+
+
+class BarberPole;
+class BTextView;
+class BStringView;
+class MarkupTextView;
+class Model;
+
+
+enum UserUsageConditionsSelectionMode {
+       LATEST          = 1,
+       USER            = 2
+};
+
+
+class UserUsageConditionsWindow : public BWindow {
+public:
+                                                               
UserUsageConditionsWindow(BWindow* parent,
+                                                                       BRect 
frame, Model& model,
+                                                                       
UserUsageConditionsSelectionMode mode);
+       virtual                                         
~UserUsageConditionsWindow();
+
+       virtual void                            MessageReceived(BMessage* 
message);
+       virtual bool                            QuitRequested();
+
+private:
+       static const BString            _VersionText(const BString& code);
+       static const BString            _MinimumAgeText(uint8 minimumAge);
+       static const BString            _IntroductionTextForMode(
+                                                                       
UserUsageConditionsSelectionMode mode);
+       static float                            _ExpectedIntroductionTextHeight(
+                                                                       
BTextView* introductionTextView);
+
+       void                                            _DisplayData(const 
UserUsageConditions& data);
+
+       void                                            _FetchData();
+       void                                            
_SetWorkerThread(thread_id thread);
+       static int32                            _FetchDataThreadEntry(void* 
data);
+       void                                            _FetchDataPerform();
+
+private:
+                       UserUsageConditionsSelectionMode
+                                                               fMode;
+                       MarkupTextView*         fCopyView;
+                       Model&                          fModel;
+                       BStringView*            fAgeNoteStringView;
+                       BStringView*            fVersionStringView;
+                       BarberPole*                     fWorkerIndicator;
+                       thread_id                       fWorkerThread;
+};
+
+
+#endif // USER_USAGE_CONDITIONS_WINDOW_H


Other related posts:

  • » [haiku-commits] haiku: hrev53447 - in src/apps/haikudepot: ui server model - waddlesplash