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@gmail.com>
This commit is contained in:
parent
75e5739772
commit
01339a54db
@ -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)
|
||||
|
@ -143,6 +143,8 @@ local applicationSources =
|
||||
ScrollableGroupView.cpp
|
||||
SharedBitmap.cpp
|
||||
UserLoginWindow.cpp
|
||||
UserUsageConditions.cpp
|
||||
UserUsageConditionsWindow.cpp
|
||||
WorkStatusView.cpp
|
||||
|
||||
# network + server / local processes
|
||||
|
@ -2,8 +2,6 @@
|
||||
* Copyright 2017, Andrew Lindesay <apl@lindesay.co.nz>.
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef LOCAL_ICON_STORE_H
|
||||
#define LOCAL_ICON_STORE_H
|
||||
|
||||
|
100
src/apps/haikudepot/model/UserUsageConditions.cpp
Normal file
100
src/apps/haikudepot/model/UserUsageConditions.cpp
Normal file
@ -0,0 +1,100 @@
|
||||
/*
|
||||
* Copyright 2019, Andrew Lindesay <apl@lindesay.co.nz>.
|
||||
*
|
||||
* 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;
|
||||
}
|
37
src/apps/haikudepot/model/UserUsageConditions.h
Normal file
37
src/apps/haikudepot/model/UserUsageConditions.h
Normal file
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright 2019, Andrew Lindesay <apl@lindesay.co.nz>.
|
||||
*
|
||||
* 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
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
@ -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_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'
|
||||
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();
|
||||
}
|
@ -101,6 +101,8 @@ private:
|
||||
void _RatePackage();
|
||||
void _ShowScreenshot();
|
||||
|
||||
void _ViewLatestUserUsageConditions();
|
||||
|
||||
private:
|
||||
FilterView* fFilterView;
|
||||
TabView* fListTabs;
|
||||
|
@ -465,7 +465,7 @@ RatePackageWindow::_SetWorkerThread(thread_id thread)
|
||||
}
|
||||
|
||||
|
||||
int32
|
||||
/*static*/ int32
|
||||
RatePackageWindow::_QueryRatingThreadEntry(void* data)
|
||||
{
|
||||
RatePackageWindow* window = reinterpret_cast<RatePackageWindow*>(data);
|
||||
|
314
src/apps/haikudepot/ui/UserUsageConditionsWindow.cpp
Normal file
314
src/apps/haikudepot/ui/UserUsageConditionsWindow.cpp
Normal file
@ -0,0 +1,314 @@
|
||||
/*
|
||||
* Copyright 2019, Andrew Lindesay <apl@lindesay.co.nz>.
|
||||
* 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;
|
||||
}
|
66
src/apps/haikudepot/ui/UserUsageConditionsWindow.h
Normal file
66
src/apps/haikudepot/ui/UserUsageConditionsWindow.h
Normal file
@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright 2019, Andrew Lindesay <apl@lindesay.co.nz>.
|
||||
* 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
|
Loading…
Reference in New Issue
Block a user