HaikuDepot: Add 'All packages' message
I've noticed that reviewers often search for something in Haiku Depot on launch, and assume the package doesn't exist when they don't find it under featured/don't check the other tab. This change adds a message to the featured packages view if no results are found, and gives them a link to click to switch tabs. It also adds a loading message to the featured packages view. Also, modify TextSpan::ClickMessage to remove empty message check Change-Id: I045a2a91c945e28e6512232d203da680a70d4d36 Reviewed-on: https://review.haiku-os.org/c/haiku/+/9146 Reviewed-by: humdinger humdinger <[email protected]> Tested-by: Commit checker robot <[email protected]> Reviewed-by: Andrew Lindesay <[email protected]>
This commit is contained in:
@@ -28,7 +28,8 @@ enum {
|
|||||||
MSG_LOG_OUT = 'lgot',
|
MSG_LOG_OUT = 'lgot',
|
||||||
MSG_PKG_INSTALL = 'pkgi',
|
MSG_PKG_INSTALL = 'pkgi',
|
||||||
MSG_PKG_UNINSTALL = 'pkgu',
|
MSG_PKG_UNINSTALL = 'pkgu',
|
||||||
MSG_PKG_OPEN = 'pkgo'
|
MSG_PKG_OPEN = 'pkgo',
|
||||||
|
MSG_SHOW_ALL_PACKAGES_TAB = 'sapt'
|
||||||
};
|
};
|
||||||
|
|
||||||
enum BitmapSize {
|
enum BitmapSize {
|
||||||
|
|||||||
@@ -15,7 +15,6 @@
|
|||||||
#include <Shape.h>
|
#include <Shape.h>
|
||||||
#include <Window.h>
|
#include <Window.h>
|
||||||
|
|
||||||
|
|
||||||
const char* kMimeTypePlainText = "text/plain";
|
const char* kMimeTypePlainText = "text/plain";
|
||||||
|
|
||||||
|
|
||||||
@@ -802,4 +801,4 @@ TextDocumentView::_PasteAllowedChars(const char* str, int32 maxLength)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ public:
|
|||||||
{ return fCursor; }
|
{ return fCursor; }
|
||||||
void SetClickMessage(BMessage* message);
|
void SetClickMessage(BMessage* message);
|
||||||
inline const BMessage* ClickMessage() const
|
inline const BMessage* ClickMessage() const
|
||||||
{ return fClickMessage.IsEmpty() ? NULL : &fClickMessage; }
|
{ return &fClickMessage; }
|
||||||
private:
|
private:
|
||||||
void _TruncateInsert(int32& start) const;
|
void _TruncateInsert(int32& start) const;
|
||||||
void _TruncateRemove(int32& start,
|
void _TruncateRemove(int32& start,
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-214, Stephan Aßmus <[email protected]>.
|
* Copyright 2013-2014, Stephan Aßmus <[email protected]>.
|
||||||
* Copyright 2017, Julian Harnath <[email protected]>.
|
* Copyright 2017, Julian Harnath <[email protected]>.
|
||||||
* Copyright 2020-2025, Andrew Lindesay <[email protected]>.
|
* Copyright 2020-2025, Andrew Lindesay <[email protected]>.
|
||||||
|
* Copyright 2025, Pawan Yerramilli <[email protected]>.
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -21,11 +22,12 @@
|
|||||||
#include <StringView.h>
|
#include <StringView.h>
|
||||||
|
|
||||||
#include "BitmapView.h"
|
#include "BitmapView.h"
|
||||||
|
#include "Cursor.h"
|
||||||
#include "HaikuDepotConstants.h"
|
#include "HaikuDepotConstants.h"
|
||||||
|
#include "InterfaceDefs.h"
|
||||||
#include "LocaleUtils.h"
|
#include "LocaleUtils.h"
|
||||||
#include "Logger.h"
|
#include "Logger.h"
|
||||||
#include "MainWindow.h"
|
#include "MainWindow.h"
|
||||||
#include "MarkupTextView.h"
|
|
||||||
#include "PackageUtils.h"
|
#include "PackageUtils.h"
|
||||||
#include "RatingUtils.h"
|
#include "RatingUtils.h"
|
||||||
#include "RatingView.h"
|
#include "RatingView.h"
|
||||||
@@ -50,6 +52,11 @@
|
|||||||
// The faction of an M-space that is left between the title and the first trailing icon.
|
// The faction of an M-space that is left between the title and the first trailing icon.
|
||||||
#define TITLE_RIGHT_TRAILING_ICON_PADDING_M_FACTOR 0.1
|
#define TITLE_RIGHT_TRAILING_ICON_PADDING_M_FACTOR 0.1
|
||||||
|
|
||||||
|
enum {
|
||||||
|
PACKAGE_BULDING_CARD = 0,
|
||||||
|
PACKAGE_LIST_CARD = 1,
|
||||||
|
NO_RESULTS_CARD = 2
|
||||||
|
};
|
||||||
|
|
||||||
// #pragma mark - PackageView
|
// #pragma mark - PackageView
|
||||||
|
|
||||||
@@ -966,22 +973,62 @@ private:
|
|||||||
FeaturedPackagesView::FeaturedPackagesView(Model& model)
|
FeaturedPackagesView::FeaturedPackagesView(Model& model)
|
||||||
:
|
:
|
||||||
BView(B_TRANSLATE("Featured packages"), 0),
|
BView(B_TRANSLATE("Featured packages"), 0),
|
||||||
fModel(model)
|
fModel(model),
|
||||||
|
fIsLoadingAndNoData(false)
|
||||||
{
|
{
|
||||||
fPackagesView = new StackedFeaturedPackagesView(fModel);
|
fPackagesView = new StackedFeaturedPackagesView(fModel);
|
||||||
|
|
||||||
fScrollView = new BScrollView("featured packages scroll view", fPackagesView, 0, false, true,
|
fScrollView = new BScrollView("featured packages scroll view", fPackagesView, 0, false, true,
|
||||||
B_FANCY_BORDER);
|
B_FANCY_BORDER);
|
||||||
|
|
||||||
BLayoutBuilder::Group<>(this).Add(fScrollView, 1.0f);
|
_BuildNoResultsView();
|
||||||
}
|
|
||||||
|
|
||||||
|
BStringView* pleaseWaitText = new BStringView(
|
||||||
|
"please wait text", B_TRANSLATE("Creating package list" B_UTF8_ELLIPSIS));
|
||||||
|
|
||||||
|
pleaseWaitText->SetExplicitAlignment(
|
||||||
|
BAlignment(B_ALIGN_HORIZONTAL_CENTER, B_ALIGN_VERTICAL_CENTER));
|
||||||
|
|
||||||
|
fFeaturedCardLayout = new BCardLayout();
|
||||||
|
SetLayout(fFeaturedCardLayout);
|
||||||
|
|
||||||
|
BGroupView* pleaseWaitGroup = new BGroupView("please wait");
|
||||||
|
pleaseWaitGroup->SetViewColor(ui_color(B_LIST_BACKGROUND_COLOR));
|
||||||
|
AddChild(pleaseWaitGroup);
|
||||||
|
|
||||||
|
BGroupView* foundResultsGroup = new BGroupView("search results");
|
||||||
|
AddChild(foundResultsGroup);
|
||||||
|
|
||||||
|
BGroupView* noResultsGroup = new BGroupView("no search results");
|
||||||
|
noResultsGroup->SetViewColor(ui_color(B_LIST_BACKGROUND_COLOR));
|
||||||
|
AddChild(noResultsGroup);
|
||||||
|
|
||||||
|
BLayoutBuilder::Group<>(pleaseWaitGroup)
|
||||||
|
.Add(pleaseWaitText)
|
||||||
|
.SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNLIMITED));
|
||||||
|
BLayoutBuilder::Group<>(foundResultsGroup).Add(fScrollView, 1.0f);
|
||||||
|
BLayoutBuilder::Group<>(noResultsGroup)
|
||||||
|
.AddGroup(B_VERTICAL)
|
||||||
|
.AddGlue()
|
||||||
|
.Add(fNoResultsView)
|
||||||
|
.AddGlue()
|
||||||
|
.End()
|
||||||
|
.SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNLIMITED));
|
||||||
|
_AdjustViews();
|
||||||
|
}
|
||||||
|
|
||||||
FeaturedPackagesView::~FeaturedPackagesView()
|
FeaturedPackagesView::~FeaturedPackagesView()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
FeaturedPackagesView::AttachedToWindow()
|
||||||
|
{
|
||||||
|
fNoResultsView->SetTarget(Window());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
FeaturedPackagesView::RetainPackages(const std::vector<PackageInfoRef>& packages)
|
FeaturedPackagesView::RetainPackages(const std::vector<PackageInfoRef>& packages)
|
||||||
{
|
{
|
||||||
@@ -994,6 +1041,9 @@ void
|
|||||||
FeaturedPackagesView::AddRemovePackages(const std::vector<PackageInfoRef>& addedPackages,
|
FeaturedPackagesView::AddRemovePackages(const std::vector<PackageInfoRef>& addedPackages,
|
||||||
const std::vector<PackageInfoRef>& removedPackages)
|
const std::vector<PackageInfoRef>& removedPackages)
|
||||||
{
|
{
|
||||||
|
if (!addedPackages.empty())
|
||||||
|
fIsLoadingAndNoData = false;
|
||||||
|
|
||||||
if (!addedPackages.empty() || !removedPackages.empty()) {
|
if (!addedPackages.empty() || !removedPackages.empty()) {
|
||||||
fPackagesView->AddRemovePackages(addedPackages, removedPackages);
|
fPackagesView->AddRemovePackages(addedPackages, removedPackages);
|
||||||
_AdjustViews();
|
_AdjustViews();
|
||||||
@@ -1045,8 +1095,59 @@ FeaturedPackagesView::HandlePackagesChanged(const PackageInfoEvents& events)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
FeaturedPackagesView::SetLoading(bool isLoading)
|
||||||
|
{
|
||||||
|
if ((isLoading && fPackagesView->IsEmpty()) != fIsLoadingAndNoData) {
|
||||||
|
fIsLoadingAndNoData = !fIsLoadingAndNoData;
|
||||||
|
_AdjustViews();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
FeaturedPackagesView::_BuildNoResultsView()
|
||||||
|
{
|
||||||
|
fNoResultsView = new TextDocumentView();
|
||||||
|
TextDocumentRef noResultsTextDocument = new TextDocument();
|
||||||
|
ParagraphStyle paragraphStyle;
|
||||||
|
paragraphStyle.SetAlignment(ALIGN_CENTER);
|
||||||
|
Paragraph paragraph(paragraphStyle);
|
||||||
|
|
||||||
|
TextSpan prefix;
|
||||||
|
prefix.SetText(B_TRANSLATE("No results? "));
|
||||||
|
|
||||||
|
CharacterStyle linkStyle;
|
||||||
|
linkStyle.SetForegroundColor(ui_color(B_LINK_TEXT_COLOR));
|
||||||
|
TextSpan link(B_TRANSLATE_COMMENT(
|
||||||
|
"Click here", "Appears in the sentence 'Click here to search all packages.'"), linkStyle);
|
||||||
|
link.SetClickMessage(new BMessage(MSG_SHOW_ALL_PACKAGES_TAB));
|
||||||
|
BCursor cursor(B_CURSOR_ID_SYSTEM_DEFAULT);
|
||||||
|
link.SetCursor(cursor);
|
||||||
|
|
||||||
|
TextSpan suffix;
|
||||||
|
suffix.SetText(B_TRANSLATE_COMMENT(" to search all packages.",
|
||||||
|
"Appears in the sentence 'Click here to search all packages.'"));
|
||||||
|
|
||||||
|
paragraph.Append(prefix);
|
||||||
|
paragraph.Append(link);
|
||||||
|
paragraph.Append(suffix);
|
||||||
|
noResultsTextDocument->Append(paragraph);
|
||||||
|
fNoResultsView->SetTextDocument(noResultsTextDocument);
|
||||||
|
fNoResultsView->SetSelectionEnabled(false);
|
||||||
|
fNoResultsView->SetViewUIColor(B_LIST_BACKGROUND_COLOR);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
FeaturedPackagesView::_AdjustViews()
|
FeaturedPackagesView::_AdjustViews()
|
||||||
{
|
{
|
||||||
|
if (fIsLoadingAndNoData)
|
||||||
|
fFeaturedCardLayout->SetVisibleItem(PACKAGE_BULDING_CARD);
|
||||||
|
else if (fPackagesView->IsEmpty())
|
||||||
|
fFeaturedCardLayout->SetVisibleItem(NO_RESULTS_CARD);
|
||||||
|
else
|
||||||
|
fFeaturedCardLayout->SetVisibleItem(PACKAGE_LIST_CARD);
|
||||||
|
|
||||||
fScrollView->FrameResized(fScrollView->Frame().Width(), fScrollView->Frame().Height());
|
fScrollView->FrameResized(fScrollView->Frame().Width(), fScrollView->Frame().Height());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,11 +9,14 @@
|
|||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include <CardLayout.h>
|
||||||
#include <View.h>
|
#include <View.h>
|
||||||
|
#include <StringView.h>
|
||||||
|
|
||||||
#include "Model.h"
|
#include "Model.h"
|
||||||
#include "PackageInfo.h"
|
#include "PackageInfo.h"
|
||||||
#include "PackageInfoListener.h"
|
#include "PackageInfoListener.h"
|
||||||
|
#include "TextDocumentView.h"
|
||||||
|
|
||||||
|
|
||||||
class StackedFeaturedPackagesView;
|
class StackedFeaturedPackagesView;
|
||||||
@@ -25,6 +28,7 @@ public:
|
|||||||
virtual ~FeaturedPackagesView();
|
virtual ~FeaturedPackagesView();
|
||||||
|
|
||||||
virtual void DoLayout();
|
virtual void DoLayout();
|
||||||
|
void AttachedToWindow();
|
||||||
|
|
||||||
void RetainPackages(const std::vector<PackageInfoRef>& packages);
|
void RetainPackages(const std::vector<PackageInfoRef>& packages);
|
||||||
void AddRemovePackages(const std::vector<PackageInfoRef>& addedPackages,
|
void AddRemovePackages(const std::vector<PackageInfoRef>& addedPackages,
|
||||||
@@ -38,16 +42,21 @@ public:
|
|||||||
|
|
||||||
void HandlePackagesChanged(const PackageInfoEvents& events);
|
void HandlePackagesChanged(const PackageInfoEvents& events);
|
||||||
|
|
||||||
|
void SetLoading(bool isLoading);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void _AdjustViews();
|
void _AdjustViews();
|
||||||
void _HandlePackageChanged(const PackageInfoEvent& event);
|
void _HandlePackageChanged(const PackageInfoEvent& event);
|
||||||
|
void _BuildNoResultsView();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Model& fModel;
|
Model& fModel;
|
||||||
BScrollView* fScrollView;
|
BScrollView* fScrollView;
|
||||||
StackedFeaturedPackagesView*
|
StackedFeaturedPackagesView*
|
||||||
fPackagesView;
|
fPackagesView;
|
||||||
|
BCardLayout* fFeaturedCardLayout;
|
||||||
|
TextDocumentView* fNoResultsView;
|
||||||
|
bool fIsLoadingAndNoData;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif // FEATURED_PACKAGES_VIEW_H
|
#endif // FEATURED_PACKAGES_VIEW_H
|
||||||
|
|||||||
@@ -672,6 +672,10 @@ MainWindow::MessageReceived(BMessage* message)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case MSG_SHOW_ALL_PACKAGES_TAB:
|
||||||
|
fListTabs->Select(TAB_ALL_PACKAGES);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
BWindow::MessageReceived(message);
|
BWindow::MessageReceived(message);
|
||||||
break;
|
break;
|
||||||
@@ -1193,6 +1197,7 @@ MainWindow::_StartBulkLoad(bool force)
|
|||||||
}
|
}
|
||||||
|
|
||||||
fPackageInfoView->Clear();
|
fPackageInfoView->Clear();
|
||||||
|
fFeaturedPackagesView->SetLoading(true);
|
||||||
|
|
||||||
fRefreshRepositoriesItem->SetEnabled(false);
|
fRefreshRepositoriesItem->SetEnabled(false);
|
||||||
ProcessCoordinator* bulkLoadCoordinator
|
ProcessCoordinator* bulkLoadCoordinator
|
||||||
@@ -1213,6 +1218,7 @@ MainWindow::_BulkLoadCompleteReceived(status_t errorStatus)
|
|||||||
"logs." ALERT_MSG_LOGS_USER_GUIDE));
|
"logs." ALERT_MSG_LOGS_USER_GUIDE));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fFeaturedPackagesView->SetLoading(false);
|
||||||
fRefreshRepositoriesItem->SetEnabled(true);
|
fRefreshRepositoriesItem->SetEnabled(true);
|
||||||
_AdoptModel();
|
_AdoptModel();
|
||||||
_UpdateAvailableRepositories();
|
_UpdateAvailableRepositories();
|
||||||
|
|||||||
@@ -12,8 +12,7 @@
|
|||||||
|
|
||||||
class LinkView : public BStringView, public BInvoker {
|
class LinkView : public BStringView, public BInvoker {
|
||||||
public:
|
public:
|
||||||
LinkView(const char* name, const char* string,
|
LinkView(const char* name, const char* string, BMessage* message);
|
||||||
BMessage* message);
|
|
||||||
|
|
||||||
virtual void AttachedToWindow();
|
virtual void AttachedToWindow();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user