HaikuDepot: data update actions via msgs
This change will stop the main window from loading all of a selected package's data even if it may not be viewed; for example, people don't always view the changelog. This saves on calls to the server which are not necessary. Where data is loaded by the view, the view layer no longer directly enqueues background processes, but requests the main window to do this for it. This unifies the approach for the view to perform "actions" into a single approach rather than different approaches in different circumstances. The changes also include better tab- management for the "view package" detail. Change-Id: I6a08ce9e37d1968655d14b8cc25519d534eccae1 Reviewed-on: https://review.haiku-os.org/c/haiku/+/10845 Tested-by: Commit checker robot <[email protected]> Reviewed-by: Jérôme Duval <[email protected]>
This commit is contained in:
@@ -15,7 +15,6 @@ enum {
|
||||
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',
|
||||
@@ -29,6 +28,9 @@ enum {
|
||||
MSG_PKG_INSTALL = 'pkgi',
|
||||
MSG_PKG_UNINSTALL = 'pkgu',
|
||||
MSG_PKG_OPEN = 'pkgo',
|
||||
MSG_PKG_CACHE_SCREENSHOT = 'pcsc',
|
||||
MSG_PKG_POPULATE_CHANGELOG = 'pchl',
|
||||
MSG_PKG_POPULATE_USER_RATINGS = 'purg',
|
||||
MSG_SHOW_ALL_PACKAGES_TAB = 'sapt'
|
||||
};
|
||||
|
||||
|
||||
@@ -530,6 +530,10 @@ bool
|
||||
Model::CanPopulatePackage(const PackageInfoRef& package)
|
||||
{
|
||||
const BString depotName = PackageUtils::DepotName(package);
|
||||
|
||||
if (depotName == SINGLE_PACKAGE_DEPOT_NAME)
|
||||
return false;
|
||||
|
||||
const DepotInfoRef& depot = DepotForName(depotName);
|
||||
|
||||
if (!depot.IsSet())
|
||||
|
||||
@@ -22,6 +22,15 @@ ScreenshotCoordinate::ScreenshotCoordinate()
|
||||
}
|
||||
|
||||
|
||||
ScreenshotCoordinate::ScreenshotCoordinate(const ScreenshotCoordinate& other)
|
||||
:
|
||||
fCode(other.fCode),
|
||||
fWidth(other.fWidth),
|
||||
fHeight(other.fHeight)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
ScreenshotCoordinate::ScreenshotCoordinate(const BMessage* from)
|
||||
{
|
||||
if (from->FindString(kKeyCode, &fCode) != B_OK)
|
||||
@@ -75,6 +84,16 @@ ScreenshotCoordinate::IsValid() const
|
||||
}
|
||||
|
||||
|
||||
ScreenshotCoordinate&
|
||||
ScreenshotCoordinate::operator=(const ScreenshotCoordinate& other)
|
||||
{
|
||||
fCode = other.fCode;
|
||||
fHeight = other.fHeight;
|
||||
fWidth = other.fWidth;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
ScreenshotCoordinate::operator==(const ScreenshotCoordinate& other) const
|
||||
{
|
||||
@@ -82,6 +101,13 @@ ScreenshotCoordinate::operator==(const ScreenshotCoordinate& other) const
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
ScreenshotCoordinate::operator!=(const ScreenshotCoordinate& other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
|
||||
const BString
|
||||
ScreenshotCoordinate::Key() const
|
||||
{
|
||||
|
||||
@@ -19,6 +19,7 @@ class ScreenshotCoordinate : public BArchivable {
|
||||
public:
|
||||
ScreenshotCoordinate(const BMessage* from);
|
||||
ScreenshotCoordinate(BString code, uint32 width, uint32 height);
|
||||
ScreenshotCoordinate(const ScreenshotCoordinate& other);
|
||||
ScreenshotCoordinate();
|
||||
virtual ~ScreenshotCoordinate();
|
||||
|
||||
@@ -26,7 +27,10 @@ public:
|
||||
uint32 Width() const;
|
||||
uint32 Height() const;
|
||||
|
||||
ScreenshotCoordinate&
|
||||
operator=(const ScreenshotCoordinate& other);
|
||||
bool operator==(const ScreenshotCoordinate& other) const;
|
||||
bool operator!=(const ScreenshotCoordinate& other) const;
|
||||
|
||||
bool IsValid() const;
|
||||
const BString Key() const;
|
||||
|
||||
@@ -16,6 +16,10 @@
|
||||
|
||||
static const char* const kKeyTitle = "title";
|
||||
static const char* const kKeyDeskbarLink = "deskbar_link";
|
||||
static const char* const kKeyScreenshotCoordinates = "screenshot_coordinates";
|
||||
|
||||
|
||||
// #pragma mark - PackageAction
|
||||
|
||||
|
||||
/*! An abstract superclass of the various sorts of package actions which can be
|
||||
@@ -84,6 +88,9 @@ PackageAction::Archive(BMessage* into, bool deep) const
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - UninstallPackageAction
|
||||
|
||||
|
||||
UninstallPackageAction::UninstallPackageAction(const BString& packageName,
|
||||
const BString& packageTitle)
|
||||
:
|
||||
@@ -113,6 +120,9 @@ UninstallPackageAction::MessageWhat() const
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - InstallPackageAction
|
||||
|
||||
|
||||
InstallPackageAction::InstallPackageAction(const BString& packageName,
|
||||
const BString& packageTitle)
|
||||
:
|
||||
@@ -142,6 +152,9 @@ InstallPackageAction::MessageWhat() const
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - OpenPackageAction
|
||||
|
||||
|
||||
OpenPackageAction::OpenPackageAction(const BString& packageName, const DeskbarLink& deskbarLink)
|
||||
:
|
||||
PackageAction("Open", packageName),
|
||||
@@ -197,3 +210,120 @@ OpenPackageAction::Archive(BMessage* into, bool deep) const
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - CacheScreenshotPackageAction
|
||||
|
||||
|
||||
CacheScreenshotPackageAction::CacheScreenshotPackageAction(const BString& packageName,
|
||||
const ScreenshotCoordinate& screenshotCoordinate)
|
||||
:
|
||||
PackageAction("Screenshot", packageName),
|
||||
fScreenshotCoordinate(screenshotCoordinate)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
CacheScreenshotPackageAction::CacheScreenshotPackageAction(const BMessage* from)
|
||||
:
|
||||
PackageAction(from)
|
||||
{
|
||||
BMessage screenshotCoordinateMessage;
|
||||
if (from->FindMessage(kKeyScreenshotCoordinates, &screenshotCoordinateMessage) == B_OK)
|
||||
fScreenshotCoordinate = ScreenshotCoordinate(&screenshotCoordinateMessage);
|
||||
else
|
||||
HDFATAL("missing key [%s]", kKeyScreenshotCoordinates);
|
||||
}
|
||||
|
||||
|
||||
CacheScreenshotPackageAction::~CacheScreenshotPackageAction()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
const uint32
|
||||
CacheScreenshotPackageAction::MessageWhat() const
|
||||
{
|
||||
return MSG_PKG_CACHE_SCREENSHOT;
|
||||
}
|
||||
|
||||
|
||||
ScreenshotCoordinate
|
||||
CacheScreenshotPackageAction::Coordinate() const
|
||||
{
|
||||
return fScreenshotCoordinate;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
CacheScreenshotPackageAction::Archive(BMessage* into, bool deep) const
|
||||
{
|
||||
status_t result = PackageAction::Archive(into, deep);
|
||||
|
||||
if (result == B_OK) {
|
||||
BMessage screenshotCoordinateMessage;
|
||||
result = fScreenshotCoordinate.Archive(&screenshotCoordinateMessage);
|
||||
if (result == B_OK)
|
||||
result = into->AddMessage(kKeyScreenshotCoordinates, &screenshotCoordinateMessage);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - PopulateChangelogPackageAction
|
||||
|
||||
|
||||
PopulateChangelogPackageAction::PopulateChangelogPackageAction(const BString& packageName)
|
||||
:
|
||||
PackageAction("Populate Changelog", packageName)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
PopulateChangelogPackageAction::PopulateChangelogPackageAction(const BMessage* from)
|
||||
:
|
||||
PackageAction(from)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
PopulateChangelogPackageAction::~PopulateChangelogPackageAction()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
const uint32
|
||||
PopulateChangelogPackageAction::MessageWhat() const
|
||||
{
|
||||
return MSG_PKG_POPULATE_CHANGELOG;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - PopulateUserRatingsPackageAction
|
||||
|
||||
|
||||
PopulateUserRatingsPackageAction::PopulateUserRatingsPackageAction(const BString& packageName)
|
||||
:
|
||||
PackageAction("Populate User Ratings", packageName)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
PopulateUserRatingsPackageAction::PopulateUserRatingsPackageAction(const BMessage* from)
|
||||
:
|
||||
PackageAction(from)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
PopulateUserRatingsPackageAction::~PopulateUserRatingsPackageAction()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
const uint32
|
||||
PopulateUserRatingsPackageAction::MessageWhat() const
|
||||
{
|
||||
return MSG_PKG_POPULATE_USER_RATINGS;
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <String.h>
|
||||
|
||||
#include "DeskbarLink.h"
|
||||
#include "ScreenshotCoordinate.h"
|
||||
|
||||
|
||||
class PackageAction : public BReferenceable, public BArchivable
|
||||
@@ -80,4 +81,44 @@ private:
|
||||
};
|
||||
|
||||
|
||||
class CacheScreenshotPackageAction : public PackageAction {
|
||||
public:
|
||||
CacheScreenshotPackageAction(const BString& packageName,
|
||||
const ScreenshotCoordinate& screenshotCoordinate);
|
||||
CacheScreenshotPackageAction(const BMessage* from);
|
||||
~CacheScreenshotPackageAction();
|
||||
|
||||
virtual const uint32 MessageWhat() const;
|
||||
|
||||
ScreenshotCoordinate
|
||||
Coordinate() const;
|
||||
|
||||
virtual status_t Archive(BMessage* into, bool deep = true) const;
|
||||
|
||||
private:
|
||||
ScreenshotCoordinate
|
||||
fScreenshotCoordinate;
|
||||
};
|
||||
|
||||
|
||||
class PopulateChangelogPackageAction : public PackageAction {
|
||||
public:
|
||||
PopulateChangelogPackageAction(const BString& packageName);
|
||||
PopulateChangelogPackageAction(const BMessage* from);
|
||||
virtual ~PopulateChangelogPackageAction();
|
||||
|
||||
virtual const uint32 MessageWhat() const;
|
||||
};
|
||||
|
||||
|
||||
class PopulateUserRatingsPackageAction : public PackageAction {
|
||||
public:
|
||||
PopulateUserRatingsPackageAction(const BString& packageName);
|
||||
PopulateUserRatingsPackageAction(const BMessage* from);
|
||||
virtual ~PopulateUserRatingsPackageAction();
|
||||
|
||||
virtual const uint32 MessageWhat() const;
|
||||
};
|
||||
|
||||
|
||||
#endif // PACKAGE_ACTION_H
|
||||
|
||||
@@ -67,16 +67,6 @@ public:
|
||||
};
|
||||
|
||||
|
||||
/*! Classes implementing this 'interface' are able to consume process
|
||||
coordinators. This may be in order to run them.
|
||||
*/
|
||||
|
||||
class ProcessCoordinatorConsumer {
|
||||
public:
|
||||
virtual void Consume(ProcessCoordinator *item) = 0;
|
||||
};
|
||||
|
||||
|
||||
/*! It is possible to create a number of ProcessNodes (themselves associated
|
||||
with AbstractProcess-s) that may have dependencies (predecessors and
|
||||
successors) and then an instance of this class is able to coordinate the
|
||||
|
||||
@@ -136,28 +136,11 @@ ProcessCoordinatorFactory::CreateBulkLoadCoordinator(Model* model, bool forceLoc
|
||||
}
|
||||
|
||||
|
||||
/*static*/ ProcessCoordinator*
|
||||
ProcessCoordinatorFactory::CacheScreenshotCoordinator(Model* model,
|
||||
ScreenshotCoordinate& screenshotCoordinate)
|
||||
{
|
||||
return _CreateSingleProcessCoordinator("CacheScreenshot",
|
||||
new CacheScreenshotProcess(model, screenshotCoordinate));
|
||||
}
|
||||
|
||||
|
||||
/*static*/ ProcessCoordinator*
|
||||
ProcessCoordinatorFactory::PopulatePkgChangelogCoordinator(Model* model, const BString& packageName)
|
||||
{
|
||||
return _CreateSingleProcessCoordinator("PopulatePkgChangelog",
|
||||
new PopulatePkgChangelogFromServerProcess(packageName, model));
|
||||
}
|
||||
|
||||
|
||||
/*static*/ ProcessCoordinator*
|
||||
ProcessCoordinatorFactory::PopulatePkgUserRatingsCoordinator(Model* model,
|
||||
const BString& packageName)
|
||||
{
|
||||
return _CreateSingleProcessCoordinator("PopulatePkgUserRatings",
|
||||
return _CreateSingleProcessCoordinator("PopulatePkgUserRatings", NULL,
|
||||
new PopulatePkgUserRatingsFromServerProcess(packageName, model));
|
||||
}
|
||||
|
||||
@@ -166,12 +149,8 @@ ProcessCoordinatorFactory::PopulatePkgUserRatingsCoordinator(Model* model,
|
||||
ProcessCoordinatorFactory::CreateInstallPackageActionCoordinator(Model* model,
|
||||
const InstallPackageAction& action)
|
||||
{
|
||||
ProcessCoordinator* processCoordinator
|
||||
= new ProcessCoordinator("InstallPackage", new BMessage(MSG_PACKAGE_ACTION_DONE));
|
||||
AbstractProcessNode* processNode
|
||||
= new ThreadedProcessNode(new InstallPackageProcess(action.PackageName(), model), 10);
|
||||
processCoordinator->AddNode(processNode);
|
||||
return processCoordinator;
|
||||
return _CreateSingleProcessCoordinator("InstallPackage", new BMessage(MSG_PACKAGE_ACTION_DONE),
|
||||
new InstallPackageProcess(action.PackageName(), model));
|
||||
}
|
||||
|
||||
|
||||
@@ -179,12 +158,9 @@ ProcessCoordinatorFactory::CreateInstallPackageActionCoordinator(Model* model,
|
||||
ProcessCoordinatorFactory::CreateUninstallPackageActionCoordinator(Model* model,
|
||||
const UninstallPackageAction& action)
|
||||
{
|
||||
ProcessCoordinator* processCoordinator
|
||||
= new ProcessCoordinator("UninstallPackage", new BMessage(MSG_PACKAGE_ACTION_DONE));
|
||||
AbstractProcessNode* processNode
|
||||
= new ThreadedProcessNode(new UninstallPackageProcess(action.PackageName(), model), 10);
|
||||
processCoordinator->AddNode(processNode);
|
||||
return processCoordinator;
|
||||
return _CreateSingleProcessCoordinator("UninstallPackage",
|
||||
new BMessage(MSG_PACKAGE_ACTION_DONE),
|
||||
new UninstallPackageProcess(action.PackageName(), model));
|
||||
}
|
||||
|
||||
|
||||
@@ -192,12 +168,37 @@ ProcessCoordinatorFactory::CreateUninstallPackageActionCoordinator(Model* model,
|
||||
ProcessCoordinatorFactory::CreateOpenPackageActionCoordinator(Model* model,
|
||||
const OpenPackageAction& action)
|
||||
{
|
||||
ProcessCoordinator* processCoordinator
|
||||
= new ProcessCoordinator("OpenPackage", new BMessage(MSG_PACKAGE_ACTION_DONE));
|
||||
AbstractProcessNode* processNode = new ThreadedProcessNode(
|
||||
return _CreateSingleProcessCoordinator("OpenPackage", new BMessage(MSG_PACKAGE_ACTION_DONE),
|
||||
new OpenPackageProcess(action.PackageName(), model, action.Link()));
|
||||
processCoordinator->AddNode(processNode);
|
||||
return processCoordinator;
|
||||
}
|
||||
|
||||
|
||||
/*static*/ ProcessCoordinator*
|
||||
ProcessCoordinatorFactory::CreateCacheScreenshotPackageActionCoordinator(Model* model,
|
||||
const CacheScreenshotPackageAction& action)
|
||||
{
|
||||
return _CreateSingleProcessCoordinator("CacheScreenshot", new BMessage(MSG_PACKAGE_ACTION_DONE),
|
||||
new CacheScreenshotProcess(model, action.Coordinate()));
|
||||
}
|
||||
|
||||
|
||||
/*static*/ ProcessCoordinator*
|
||||
ProcessCoordinatorFactory::CreatePopulateChangelogPackageActionCoordinator(Model* model,
|
||||
const PopulateChangelogPackageAction& action)
|
||||
{
|
||||
return _CreateSingleProcessCoordinator("PopulatePkgChangelog",
|
||||
new BMessage(MSG_PACKAGE_ACTION_DONE),
|
||||
new PopulatePkgChangelogFromServerProcess(action.PackageName(), model));
|
||||
}
|
||||
|
||||
|
||||
/*static*/ ProcessCoordinator*
|
||||
ProcessCoordinatorFactory::CreatePopulateUserRatingsPackageActionCoordinator(Model* model,
|
||||
const PopulateUserRatingsPackageAction& action)
|
||||
{
|
||||
return _CreateSingleProcessCoordinator("PopulatePkgUserRatings",
|
||||
new BMessage(MSG_PACKAGE_ACTION_DONE),
|
||||
new PopulatePkgUserRatingsFromServerProcess(action.PackageName(), model));
|
||||
}
|
||||
|
||||
|
||||
@@ -225,10 +226,10 @@ ProcessCoordinatorFactory::_CalculateServerProcessOptions()
|
||||
|
||||
|
||||
/*static*/ ProcessCoordinator*
|
||||
ProcessCoordinatorFactory::_CreateSingleProcessCoordinator(const char* name,
|
||||
ProcessCoordinatorFactory::_CreateSingleProcessCoordinator(const char* name, BMessage* message,
|
||||
AbstractProcess* process)
|
||||
{
|
||||
ProcessCoordinator* processCoordinator = new ProcessCoordinator(name);
|
||||
ProcessCoordinator* processCoordinator = new ProcessCoordinator(name, message);
|
||||
AbstractProcessNode* cacheScreenshotNode = new ThreadedProcessNode(process);
|
||||
processCoordinator->AddNode(cacheScreenshotNode);
|
||||
return processCoordinator;
|
||||
|
||||
@@ -33,12 +33,6 @@ public:
|
||||
UserDetailVerifierListener* userDetailVerifierListener,
|
||||
Model* model);
|
||||
|
||||
static ProcessCoordinator* CacheScreenshotCoordinator(
|
||||
Model* model, ScreenshotCoordinate& screenshotCoordinate);
|
||||
|
||||
static ProcessCoordinator* PopulatePkgChangelogCoordinator(Model* model,
|
||||
const BString& packageName);
|
||||
|
||||
static ProcessCoordinator* PopulatePkgUserRatingsCoordinator(Model* model,
|
||||
const BString& packageName);
|
||||
|
||||
@@ -51,12 +45,20 @@ public:
|
||||
static ProcessCoordinator* CreateOpenPackageActionCoordinator(Model* model,
|
||||
const OpenPackageAction& action);
|
||||
|
||||
static ProcessCoordinator* CreateCacheScreenshotPackageActionCoordinator(Model* model,
|
||||
const CacheScreenshotPackageAction& action);
|
||||
|
||||
static ProcessCoordinator* CreatePopulateChangelogPackageActionCoordinator(Model* model,
|
||||
const PopulateChangelogPackageAction& action);
|
||||
|
||||
static ProcessCoordinator* CreatePopulateUserRatingsPackageActionCoordinator(Model* model,
|
||||
const PopulateUserRatingsPackageAction& action);
|
||||
|
||||
private:
|
||||
static uint32 _CalculateServerProcessOptions();
|
||||
|
||||
static ProcessCoordinator* _CreateSingleProcessCoordinator(const char* name,
|
||||
static ProcessCoordinator* _CreateSingleProcessCoordinator(const char* name, BMessage* message,
|
||||
AbstractProcess *process);
|
||||
|
||||
};
|
||||
|
||||
#endif // PROCESS_COORDINATOR_FACTORY_H
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2023-2025, Andrew Lindesay <[email protected]>.
|
||||
* Copyright 2023-2026, Andrew Lindesay <[email protected]>.
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#include "CacheScreenshotProcess.h"
|
||||
@@ -15,8 +15,8 @@
|
||||
#define B_TRANSLATION_CONTEXT "CacheScreenshotProcess"
|
||||
|
||||
|
||||
CacheScreenshotProcess::CacheScreenshotProcess(Model *model,
|
||||
ScreenshotCoordinate& screenshotCoordinate)
|
||||
CacheScreenshotProcess::CacheScreenshotProcess(Model* model,
|
||||
const ScreenshotCoordinate& screenshotCoordinate)
|
||||
:
|
||||
fModel(model),
|
||||
fScreenshotCoordinate(screenshotCoordinate)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2023, Andrew Lindesay <[email protected]>.
|
||||
* Copyright 2023-2026, Andrew Lindesay <[email protected]>.
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef CACHE_SCREENSHOT_PROCESS__H
|
||||
@@ -15,8 +15,8 @@ class Model;
|
||||
|
||||
class CacheScreenshotProcess : public AbstractProcess {
|
||||
public:
|
||||
CacheScreenshotProcess(
|
||||
Model* model, ScreenshotCoordinate& screenshotCoordinate);
|
||||
CacheScreenshotProcess(Model* model,
|
||||
const ScreenshotCoordinate& screenshotCoordinate);
|
||||
virtual ~CacheScreenshotProcess();
|
||||
|
||||
const char* Name() const;
|
||||
|
||||
@@ -137,7 +137,11 @@ App::MessageReceived(BMessage* message)
|
||||
_AlertSimpleError(message);
|
||||
break;
|
||||
|
||||
case MSG_SERVER_DATA_CHANGED:
|
||||
case MSG_PKG_POPULATE_USER_RATINGS:
|
||||
// This will come from the `RatePackageWindow` when somebody has
|
||||
// modified a user rating in the UI. The main window and trigger
|
||||
// a background process to re-load the user rating data and then
|
||||
// show it.
|
||||
fMainWindow->PostMessage(message);
|
||||
break;
|
||||
|
||||
|
||||
@@ -236,7 +236,7 @@ MainWindow::MainWindow(const BMessage& settings)
|
||||
fFilterView = new FilterView();
|
||||
fFeaturedPackagesView = new FeaturedPackagesView(fModel);
|
||||
fPackageListView = new PackageListView(&fModel);
|
||||
fPackageInfoView = new PackageInfoView(&fModel, this);
|
||||
fPackageInfoView = new PackageInfoView(&fModel);
|
||||
|
||||
fSplitView = new BSplitView(B_VERTICAL, 5.0f);
|
||||
|
||||
@@ -329,7 +329,7 @@ MainWindow::MainWindow(const BMessage& settings, const PackageInfoRef package)
|
||||
fPackageInfoListener = PackageInfoListenerRef(new MainWindowPackageInfoListener(this), true);
|
||||
|
||||
fFilterView = new FilterView();
|
||||
fPackageInfoView = new PackageInfoView(&fModel, this);
|
||||
fPackageInfoView = new PackageInfoView(&fModel);
|
||||
fWorkStatusView = new WorkStatusView("work status");
|
||||
|
||||
BLayoutBuilder::Group<>(this, B_VERTICAL)
|
||||
@@ -580,23 +580,6 @@ MainWindow::MessageReceived(BMessage* message)
|
||||
break;
|
||||
}
|
||||
|
||||
// this may be triggered by, for example, a user rating being added
|
||||
// or having been altered.
|
||||
case MSG_SERVER_DATA_CHANGED:
|
||||
{
|
||||
BString name;
|
||||
if (message->FindString(shared_message_keys::kKeyPackageName, &name) == B_OK) {
|
||||
if (fPackageInfoView->Package()->Name() == name) {
|
||||
_PopulatePackageAsync(true);
|
||||
} else {
|
||||
HDDEBUG("pkg [%s] is updated on the server, but is not selected so will not be "
|
||||
"updated.",
|
||||
name.String());
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case MSG_INCREMENT_VIEW_COUNTER:
|
||||
_HandleIncrementViewCounter(message);
|
||||
break;
|
||||
@@ -688,6 +671,36 @@ MainWindow::MessageReceived(BMessage* message)
|
||||
break;
|
||||
}
|
||||
|
||||
case MSG_PKG_CACHE_SCREENSHOT:
|
||||
{
|
||||
CacheScreenshotPackageAction action(message);
|
||||
ProcessCoordinator* coordinator
|
||||
= ProcessCoordinatorFactory::CreateCacheScreenshotPackageActionCoordinator(&fModel,
|
||||
action);
|
||||
_AddProcessCoordinator(coordinator);
|
||||
break;
|
||||
}
|
||||
|
||||
case MSG_PKG_POPULATE_CHANGELOG:
|
||||
{
|
||||
PopulateChangelogPackageAction action(message);
|
||||
ProcessCoordinator* coordinator
|
||||
= ProcessCoordinatorFactory::CreatePopulateChangelogPackageActionCoordinator(
|
||||
&fModel, action);
|
||||
_AddProcessCoordinator(coordinator);
|
||||
break;
|
||||
}
|
||||
|
||||
case MSG_PKG_POPULATE_USER_RATINGS:
|
||||
{
|
||||
PopulateUserRatingsPackageAction action(message);
|
||||
ProcessCoordinator* coordinator
|
||||
= ProcessCoordinatorFactory::CreatePopulateUserRatingsPackageActionCoordinator(
|
||||
&fModel, action);
|
||||
_AddProcessCoordinator(coordinator);
|
||||
break;
|
||||
}
|
||||
|
||||
case MSG_PKG_OPEN:
|
||||
{
|
||||
OpenPackageAction action(message);
|
||||
@@ -795,13 +808,6 @@ MainWindow::StoreSettings(BMessage& settings)
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
MainWindow::Consume(ProcessCoordinator* item)
|
||||
{
|
||||
_AddProcessCoordinator(item);
|
||||
}
|
||||
|
||||
|
||||
/*! This method is invoked in the situation that a package changes in the model.
|
||||
|
||||
The events are processed into a `BMessage` which is then posted to the
|
||||
@@ -1310,8 +1316,6 @@ MainWindow::_AdoptPackage(const PackageInfoRef& package)
|
||||
if (fPackageListView != NULL)
|
||||
fPackageListView->SelectPackage(package);
|
||||
}
|
||||
|
||||
_PopulatePackageAsync(false);
|
||||
}
|
||||
|
||||
|
||||
@@ -1511,62 +1515,6 @@ MainWindow::_HandleWorkStatusChangeMessageReceived(const BMessage* message)
|
||||
}
|
||||
|
||||
|
||||
/*! Initially only superficial data is loaded from the server into the data
|
||||
model of the packages. When the package is viewed, additional data needs
|
||||
to be populated including ratings.
|
||||
|
||||
This method will cause the package to have its data refreshed from
|
||||
the server application. The refresh happens in the background; this method
|
||||
is asynchronous.
|
||||
*/
|
||||
|
||||
void
|
||||
MainWindow::_PopulatePackageAsync(bool forcePopulate)
|
||||
{
|
||||
const PackageInfoRef package = fPackageInfoView->Package();
|
||||
|
||||
if (!fModel.CanPopulatePackage(package))
|
||||
return;
|
||||
|
||||
const char* packageNameStr = package->Name().String();
|
||||
|
||||
PackageLocalizedTextRef localized = package->LocalizedText();
|
||||
bool networkAvailable = ServerHelper::IsNetworkAvailable();
|
||||
|
||||
if (localized.IsSet()) {
|
||||
if (forcePopulate || localized->Changelog().IsEmpty()) {
|
||||
if (localized->HasChangelog()) {
|
||||
if (networkAvailable) {
|
||||
_AddProcessCoordinator(
|
||||
ProcessCoordinatorFactory::PopulatePkgChangelogCoordinator(&fModel,
|
||||
package->Name()));
|
||||
HDINFO("pkg [%s] will have changelog updated from server.", packageNameStr);
|
||||
} else {
|
||||
HDINFO(
|
||||
"pkg [%s] will not have changelog updated from server; network unavailable",
|
||||
packageNameStr);
|
||||
}
|
||||
} else {
|
||||
HDINFO("pkg [%s] does not have a changelog -- won't try fetch it.", packageNameStr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (forcePopulate || RatingUtils::ShouldTryPopulateUserRatings(package->UserRatingInfo())) {
|
||||
if (networkAvailable) {
|
||||
_AddProcessCoordinator(ProcessCoordinatorFactory::PopulatePkgUserRatingsCoordinator(
|
||||
&fModel, package->Name()));
|
||||
HDINFO("pkg [%s] will have user ratings updated from server.", packageNameStr);
|
||||
} else {
|
||||
HDINFO("pkg [%s] won't have user ratings updated from server; network unavailable",
|
||||
packageNameStr);
|
||||
}
|
||||
} else {
|
||||
HDDEBUG("pkg [%s] not have user ratings updated from server.", packageNameStr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
MainWindow::_OpenSettingsWindow()
|
||||
{
|
||||
|
||||
@@ -46,9 +46,9 @@ extern const char* const kKeyWindowSettings;
|
||||
}; // namespace main_window_keys
|
||||
|
||||
|
||||
class MainWindow :
|
||||
private ProcessCoordinatorConsumer, public ProcessCoordinatorListener,
|
||||
public UserDetailVerifierListener, public BWindow {
|
||||
class MainWindow : public ProcessCoordinatorListener,
|
||||
public UserDetailVerifierListener,
|
||||
public BWindow {
|
||||
public:
|
||||
MainWindow(const BMessage& settings);
|
||||
MainWindow(const BMessage& settings,
|
||||
@@ -61,9 +61,6 @@ public:
|
||||
|
||||
void StoreSettings(BMessage& message);
|
||||
|
||||
// ProcessCoordinatorConsumer
|
||||
virtual void Consume(ProcessCoordinator *item);
|
||||
|
||||
// ProcessCoordinatorListener
|
||||
virtual void CoordinatorChanged(
|
||||
ProcessCoordinatorState& coordinatorState);
|
||||
@@ -115,7 +112,6 @@ private:
|
||||
void _HandleIncrementViewCounter(const BMessage* message);
|
||||
void _IncrementViewCounter(const BString& packageName);
|
||||
|
||||
void _PopulatePackageAsync(bool forcePopulate);
|
||||
void _StartBulkLoad(bool force = false);
|
||||
void _BulkLoadCompleteReceived(status_t errorStatus);
|
||||
|
||||
@@ -213,5 +209,4 @@ private:
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif // MAIN_WINDOW_H
|
||||
|
||||
@@ -45,7 +45,6 @@
|
||||
#include "PackageInfo.h"
|
||||
#include "PackageManager.h"
|
||||
#include "PackageUtils.h"
|
||||
#include "ProcessCoordinatorFactory.h"
|
||||
#include "RatingView.h"
|
||||
#include "ScrollableGroupView.h"
|
||||
#include "ServerHelper.h"
|
||||
@@ -1226,35 +1225,84 @@ public:
|
||||
fAboutView->SetScreenshotThumbnail(bitmap);
|
||||
}
|
||||
|
||||
void SetPackage(const PackageInfoRef package, bool switchToDefaultTab)
|
||||
void PopulateDataForTab(int32 index)
|
||||
{
|
||||
if (switchToDefaultTab)
|
||||
Select(TAB_ABOUT);
|
||||
switch (index) {
|
||||
case TAB_ABOUT:
|
||||
break;
|
||||
case TAB_RATINGS:
|
||||
_MaybePopulateUserRatings(fPackage);
|
||||
break;
|
||||
case TAB_CHANGELOG:
|
||||
_MaybePopulateChangelog(fPackage);
|
||||
break;
|
||||
case TAB_CONTENTS:
|
||||
break;
|
||||
default:
|
||||
HDERROR("unhandled tab index for data population");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void SetPackage(const PackageInfoRef package)
|
||||
{
|
||||
fPackage = package;
|
||||
|
||||
bool enableUserRatingsTab = false;
|
||||
bool enableChangelogTab = false;
|
||||
bool enableContentsTab = false;
|
||||
|
||||
if (package.IsSet()) {
|
||||
PackageLocalizedTextRef localizedText = package->LocalizedText();
|
||||
|
||||
if (localizedText.IsSet())
|
||||
enableChangelogTab = localizedText->HasChangelog();
|
||||
|
||||
enableChangelogTab = _ShowChangelog(package);
|
||||
enableContentsTab = PackageUtils::IsActivatedOrLocalFile(package);
|
||||
enableUserRatingsTab = _PackageCanHaveRatings(package);
|
||||
enableUserRatingsTab = _ShowUserRatings(package);
|
||||
}
|
||||
|
||||
TabAt(TAB_CHANGELOG)->SetEnabled(enableChangelogTab);
|
||||
TabAt(TAB_CONTENTS)->SetEnabled(enableContentsTab);
|
||||
TabAt(TAB_RATINGS)->SetEnabled(enableUserRatingsTab);
|
||||
Invalidate(TabFrame(TAB_CHANGELOG));
|
||||
Invalidate(TabFrame(TAB_CONTENTS));
|
||||
|
||||
fAboutView->SetPackage(package);
|
||||
fUserRatingsView->SetPackage(package);
|
||||
fChangelogView->SetPackage(package);
|
||||
fContentsView->SetPackage(package);
|
||||
|
||||
int32 currentTab = Selection();
|
||||
int32 futureTab = currentTab;
|
||||
|
||||
switch (futureTab) {
|
||||
case TAB_ABOUT:
|
||||
break;
|
||||
case TAB_RATINGS:
|
||||
if (!enableUserRatingsTab)
|
||||
futureTab = TAB_ABOUT;
|
||||
break;
|
||||
case TAB_CHANGELOG:
|
||||
if (!enableChangelogTab)
|
||||
futureTab = TAB_ABOUT;
|
||||
break;
|
||||
case TAB_CONTENTS:
|
||||
if (!enableContentsTab)
|
||||
futureTab = TAB_ABOUT;
|
||||
break;
|
||||
default:
|
||||
HDERROR("unhandled tab index");
|
||||
futureTab = TAB_ABOUT;
|
||||
break;
|
||||
}
|
||||
|
||||
if (currentTab != futureTab)
|
||||
Select(futureTab);
|
||||
else
|
||||
PopulateDataForTab(currentTab);
|
||||
}
|
||||
|
||||
/*! This is overridden so that data can be loaded as the tab is selected
|
||||
on-demand rather than load all the data anyway.
|
||||
*/
|
||||
virtual void Select(int32 index) {
|
||||
BTabView::Select(index);
|
||||
PopulateDataForTab(index);
|
||||
}
|
||||
|
||||
void Clear()
|
||||
@@ -1266,22 +1314,78 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
/*! It is only possible for a package to have ratings if it is associated with a server-side
|
||||
repository (depot). Otherwise there will be no means to display ratings.
|
||||
*/
|
||||
bool _PackageCanHaveRatings(const PackageInfoRef package)
|
||||
|
||||
bool _ShowUserRatings(const PackageInfoRef package)
|
||||
{
|
||||
BString depotName = PackageUtils::DepotName(package);
|
||||
if (!package.IsSet())
|
||||
return false;
|
||||
return PackageUtils::IsPopulatedUserRatings(package)
|
||||
|| (fModel->CanPopulatePackage(package) && ServerHelper::IsNetworkAvailable()
|
||||
&& PackageUtils::HasUserRatings(package));
|
||||
}
|
||||
|
||||
if (depotName == SINGLE_PACKAGE_DEPOT_NAME)
|
||||
return false;
|
||||
bool _ShowChangelog(const PackageInfoRef package) {
|
||||
if (!package.IsSet())
|
||||
return false;
|
||||
return PackageUtils::IsPopulatedChangelog(package)
|
||||
|| (fModel->CanPopulatePackage(package) && ServerHelper::IsNetworkAvailable()
|
||||
&& PackageUtils::HasChangelog(package));
|
||||
}
|
||||
|
||||
const DepotInfoRef depotInfo = fModel->DepotForName(depotName);
|
||||
/*! Returns true if the changelog should be available.
|
||||
*/
|
||||
void _MaybePopulateChangelog(const PackageInfoRef package) {
|
||||
if (!package.IsSet())
|
||||
return;
|
||||
|
||||
if (depotInfo.IsSet())
|
||||
return !depotInfo->WebAppRepositoryCode().IsEmpty();
|
||||
if (PackageUtils::IsPopulatedChangelog(package))
|
||||
return;
|
||||
|
||||
return false;
|
||||
if (!fModel->CanPopulatePackage(package))
|
||||
return;
|
||||
|
||||
if (!ServerHelper::IsNetworkAvailable()) {
|
||||
HDINFO("will skip populating changelog for [%s] as no network is available",
|
||||
package->Name().String());
|
||||
return;
|
||||
}
|
||||
|
||||
if (!PackageUtils::HasChangelog(package))
|
||||
return;
|
||||
|
||||
// This will case a background task to start which will fetch the changelog
|
||||
// from the server and populate it into the package data stored in the model.
|
||||
// The correct view will be updated when the data arrives to present.
|
||||
PopulateChangelogPackageAction action(package->Name());
|
||||
BMessage message = action.Message();
|
||||
Window()->PostMessage(&message);
|
||||
}
|
||||
|
||||
void _MaybePopulateUserRatings(const PackageInfoRef package) {
|
||||
if (!package.IsSet())
|
||||
return;
|
||||
|
||||
if (PackageUtils::IsPopulatedUserRatings(package))
|
||||
return;
|
||||
|
||||
if (!fModel->CanPopulatePackage(package))
|
||||
return;
|
||||
|
||||
if (!ServerHelper::IsNetworkAvailable()) {
|
||||
HDINFO("will skip populating user ratings for [%s] as no network is available",
|
||||
package->Name().String());
|
||||
return;
|
||||
}
|
||||
|
||||
if (!PackageUtils::HasUserRatings(package))
|
||||
return;
|
||||
|
||||
// This will case a background task to start which will fetch the user ratings
|
||||
// from the server and populate it into the package data stored in the model.
|
||||
// The correct view will be updated when the data arrives to present.
|
||||
PopulateUserRatingsPackageAction action(package->Name());
|
||||
BMessage message = action.Message();
|
||||
Window()->PostMessage(&message);
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -1290,18 +1394,17 @@ private:
|
||||
UserRatingsView* fUserRatingsView;
|
||||
ChangelogView* fChangelogView;
|
||||
ContentsView* fContentsView;
|
||||
PackageInfoRef fPackage;
|
||||
};
|
||||
|
||||
|
||||
// #pragma mark - PackageInfoView
|
||||
|
||||
|
||||
PackageInfoView::PackageInfoView(Model* model,
|
||||
ProcessCoordinatorConsumer* processCoordinatorConsumer)
|
||||
PackageInfoView::PackageInfoView(Model* model)
|
||||
:
|
||||
BView("package info view", 0),
|
||||
fModel(model),
|
||||
fProcessCoordinatorConsumer(processCoordinatorConsumer)
|
||||
fModel(model)
|
||||
{
|
||||
fCardLayout = new BCardLayout();
|
||||
SetLayout(fCardLayout);
|
||||
@@ -1362,23 +1465,9 @@ PackageInfoView::SetPackage(const PackageInfoRef& packageRef)
|
||||
return;
|
||||
}
|
||||
|
||||
bool switchToDefaultTab = true;
|
||||
if (fPackage == packageRef) {
|
||||
// When asked to display the already showing package ref,
|
||||
// don't switch to the default tab.
|
||||
switchToDefaultTab = false;
|
||||
} else if (fPackage.IsSet() && packageRef.IsSet() && fPackage->Name() == packageRef->Name()) {
|
||||
// When asked to display a different PackageInfo instance,
|
||||
// but it has the same package title as the already showing
|
||||
// instance, this probably means there was a repository
|
||||
// refresh and we are in fact still requested to show the
|
||||
// same package as before the refresh.
|
||||
switchToDefaultTab = false;
|
||||
}
|
||||
|
||||
fTitleView->SetPackage(packageRef);
|
||||
fPackageActionView->SetPackage(packageRef);
|
||||
fPagesView->SetPackage(packageRef, switchToDefaultTab);
|
||||
fPagesView->SetPackage(packageRef);
|
||||
|
||||
_SetPackageScreenshotThumb(packageRef);
|
||||
|
||||
@@ -1411,7 +1500,7 @@ PackageInfoView::_HandlePackageChanged(const PackageInfoChangeEvent& event)
|
||||
|
||||
if ((changes & PKG_CHANGED_LOCALIZED_TEXT) != 0 || (changes & PKG_CHANGED_SCREENSHOTS) != 0
|
||||
|| (changes & PKG_CHANGED_RATINGS) != 0 || (changes & PKG_CHANGED_LOCAL_INFO) != 0) {
|
||||
fPagesView->SetPackage(package, false);
|
||||
fPagesView->SetPackage(package);
|
||||
}
|
||||
|
||||
if ((changes & PKG_CHANGED_LOCALIZED_TEXT) != 0 || (changes & PKG_CHANGED_RATINGS) != 0)
|
||||
@@ -1443,7 +1532,6 @@ PackageInfoView::HandlePackagesChanged(const std::vector<PackageInfoChangeEvent>
|
||||
the background. A message will come through later once it is
|
||||
cached and ready to load.
|
||||
*/
|
||||
|
||||
void
|
||||
PackageInfoView::_SetPackageScreenshotThumb(const PackageInfoRef& package)
|
||||
{
|
||||
@@ -1467,9 +1555,9 @@ PackageInfoView::_SetPackageScreenshotThumb(const PackageInfoRef& package)
|
||||
HDINFO("screenshot won't be cached [%s] -- network unavailable", packageNameCStr);
|
||||
} else {
|
||||
HDDEBUG("screenshot is not cached [%s] -- will cache it", packageNameCStr);
|
||||
ProcessCoordinator* processCoordinator
|
||||
= ProcessCoordinatorFactory::CacheScreenshotCoordinator(fModel, desiredCoordinate);
|
||||
fProcessCoordinatorConsumer->Consume(processCoordinator);
|
||||
CacheScreenshotPackageAction action(package->Name(), desiredCoordinate);
|
||||
BMessage message = action.Message();
|
||||
Window()->PostMessage(&message);
|
||||
}
|
||||
} else {
|
||||
HDDEBUG("no screenshot for pkg [%s]", packageNameCStr);
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
#include "Model.h"
|
||||
#include "PackageInfo.h"
|
||||
#include "PackageInfoListener.h"
|
||||
#include "ProcessCoordinator.h"
|
||||
|
||||
|
||||
class BCardLayout;
|
||||
@@ -31,9 +30,7 @@ enum {
|
||||
|
||||
class PackageInfoView : public BView {
|
||||
public:
|
||||
PackageInfoView(Model* model,
|
||||
ProcessCoordinatorConsumer*
|
||||
processCoordinatorConsumer);
|
||||
PackageInfoView(Model* model);
|
||||
virtual ~PackageInfoView();
|
||||
|
||||
virtual void AttachedToWindow();
|
||||
@@ -68,8 +65,6 @@ private:
|
||||
PackageInfoRef fPackage;
|
||||
OnePackageMessagePackageListener*
|
||||
fPackageListener;
|
||||
ProcessCoordinatorConsumer*
|
||||
fProcessCoordinatorConsumer;
|
||||
};
|
||||
|
||||
#endif // PACKAGE_INFO_VIEW_H
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include "LanguageMenuUtils.h"
|
||||
#include "Logger.h"
|
||||
#include "MarkupParser.h"
|
||||
#include "PackageAction.h"
|
||||
#include "PackageUtils.h"
|
||||
#include "RatingView.h"
|
||||
#include "ServerHelper.h"
|
||||
@@ -371,8 +372,8 @@ RatePackageWindow::MessageReceived(BMessage* message)
|
||||
void
|
||||
RatePackageWindow::_RefreshPackageData()
|
||||
{
|
||||
BMessage message(MSG_SERVER_DATA_CHANGED);
|
||||
message.AddString(shared_message_keys::kKeyPackageName, fPackage->Name());
|
||||
PopulateUserRatingsPackageAction action(fPackage->Name());
|
||||
BMessage message = action.Message();
|
||||
be_app->PostMessage(&message);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2024-2025, Andrew Lindesay <apl@lindesay.co.nz>.
|
||||
* Copyright 2024-2026, Andrew Lindesay <apl@lindesay.co.nz>.
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
@@ -52,6 +52,66 @@ PackageUtils::Summary(const PackageInfoRef& package, BString& summary)
|
||||
}
|
||||
|
||||
|
||||
/*static*/ bool
|
||||
PackageUtils::HasChangelog(const PackageInfoRef& package)
|
||||
{
|
||||
if (package.IsSet()) {
|
||||
PackageLocalizedTextRef localizedText = package->LocalizedText();
|
||||
|
||||
if (localizedText.IsSet())
|
||||
return localizedText->HasChangelog();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/*static*/ bool
|
||||
PackageUtils::IsPopulatedChangelog(const PackageInfoRef& package)
|
||||
{
|
||||
if (package.IsSet()) {
|
||||
PackageLocalizedTextRef localizedText = package->LocalizedText();
|
||||
|
||||
if (localizedText.IsSet())
|
||||
return !localizedText->Changelog().IsEmpty();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/*static*/ bool
|
||||
PackageUtils::HasUserRatings(const PackageInfoRef& package)
|
||||
{
|
||||
if (package.IsSet()) {
|
||||
PackageUserRatingInfoRef userRatingInfo = package->UserRatingInfo();
|
||||
|
||||
if (userRatingInfo.IsSet()) {
|
||||
UserRatingSummaryRef summary = userRatingInfo->Summary();
|
||||
|
||||
if (summary.IsSet())
|
||||
return summary->RatingCount() > 0;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/*static*/ bool
|
||||
PackageUtils::IsPopulatedUserRatings(const PackageInfoRef& package)
|
||||
{
|
||||
if (package.IsSet()) {
|
||||
PackageUserRatingInfoRef userRatingInfo = package->UserRatingInfo();
|
||||
|
||||
if (userRatingInfo.IsSet())
|
||||
return userRatingInfo->UserRatingsPopulated();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/*static*/ const BString
|
||||
PackageUtils::DepotName(const PackageInfoRef& package)
|
||||
{
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2024-2025, Andrew Lindesay <apl@lindesay.co.nz>.
|
||||
* Copyright 2024-2026, Andrew Lindesay <apl@lindesay.co.nz>.
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef PACKAGE_UTILS_H
|
||||
@@ -15,6 +15,12 @@ public:
|
||||
static void Title(const PackageInfoRef& package, BString& title);
|
||||
static void Summary(const PackageInfoRef& package, BString& summary);
|
||||
|
||||
static bool HasChangelog(const PackageInfoRef& package);
|
||||
static bool IsPopulatedChangelog(const PackageInfoRef& package);
|
||||
|
||||
static bool HasUserRatings(const PackageInfoRef& package);
|
||||
static bool IsPopulatedUserRatings(const PackageInfoRef& package);
|
||||
|
||||
static PackageVersionRef
|
||||
Version(const PackageInfoRef& package);
|
||||
static const BString Architecture(const PackageInfoRef& package);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2025, Andrew Lindesay <apl@lindesay.co.nz>.
|
||||
* Copyright 2020-2026, Andrew Lindesay <apl@lindesay.co.nz>.
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
@@ -99,26 +99,3 @@ RatingUtils::Draw(BView* target, BPoint at, float value, const BBitmap* star)
|
||||
target->FillRect(shadeOverRect, B_SOLID_HIGH);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*! With the `userRatingInfo` provided, does it make sense for the application
|
||||
to attempt to download the user ratings? If it looks like there are none
|
||||
then it's making no sense and if it has already downloaded some then it
|
||||
also does not make any sense.
|
||||
*/
|
||||
/*static*/ bool
|
||||
RatingUtils::ShouldTryPopulateUserRatings(PackageUserRatingInfoRef userRatingInfo)
|
||||
{
|
||||
if (!userRatingInfo.IsSet())
|
||||
return true;
|
||||
|
||||
UserRatingSummaryRef summary = userRatingInfo->Summary();
|
||||
|
||||
if (!summary.IsSet())
|
||||
return true;
|
||||
|
||||
if (summary->RatingCount() == 0)
|
||||
return false;
|
||||
|
||||
return !userRatingInfo->UserRatingsPopulated();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2025, Andrew Lindesay <apl@lindesay.co.nz>.
|
||||
* Copyright 2020-2026, Andrew Lindesay <apl@lindesay.co.nz>.
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef RATING_UTILS_H
|
||||
@@ -36,8 +36,6 @@ public:
|
||||
static void Draw(BView* target, BPoint at, float value,
|
||||
const BBitmap* star);
|
||||
static void Draw(BView* target, BPoint at, float value);
|
||||
|
||||
static bool ShouldTryPopulateUserRatings(PackageUserRatingInfoRef userRatingInfo);
|
||||
};
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user