fix(ui): explain a 0 Buzz threshold in the price alerts panel

The default threshold is 0 ("only tell me when a version becomes free") and the
settings copy says so, but the panel did not: a real instance with 52 priced paid
versions and an untouched threshold showed "Nothing is under your price threshold
right now" with only a small "Alert threshold: 0 Buzz" in the corner, which reads
as a broken feature.

- the payload now carries pricedCount, so the empty state can say how many paid
  versions already have a known price
- when the threshold is 0 and prices are known, the empty state says so and
  points at Settings - Library instead of implying there is nothing to show
- the read-time threshold comparison means setting one takes effect immediately;
  measured on a copy of that instance: 0 Buzz -> 0 alerts, 100 -> 44,
  500 -> 48, 5000 -> 51
This commit is contained in:
Will Miao
2026-10-04 20:28:57 +08:00
parent 425d90a912
commit 156d2e5eb9
17 changed files with 148 additions and 23 deletions
+32 -12
View File
@@ -29,7 +29,8 @@ async function fetchPriceAlerts(limit = 200) {
enabled: payload.enabled === true,
thresholdBuzz: payload.thresholdBuzz ?? 0,
newestCheckedAt: payload.newestCheckedAt ?? null,
unavailableCount: payload.unavailableCount ?? 0
unavailableCount: payload.unavailableCount ?? 0,
pricedCount: payload.pricedCount ?? 0
};
}
@@ -114,6 +115,7 @@ export class UpdateService {
this.priceAlertsThreshold = 0;
this.priceAlertsNewestCheckedAt = null;
this.priceAlertsUnavailableCount = 0;
this.priceAlertsPricedCount = 0;
this.priceAlertsLoading = false;
this.priceAlertSegment = 'below_threshold';
this.unreadPriceAlertCount = 0;
@@ -407,6 +409,7 @@ export class UpdateService {
this.priceAlertsThreshold = payload.thresholdBuzz;
this.priceAlertsNewestCheckedAt = payload.newestCheckedAt;
this.priceAlertsUnavailableCount = payload.unavailableCount || 0;
this.priceAlertsPricedCount = payload.pricedCount || 0;
this.refreshUnreadPriceAlertCount();
this.renderPriceAlerts();
return this.priceAlerts;
@@ -512,17 +515,7 @@ export class UpdateService {
list.innerHTML = '';
if (!alerts.length) {
empty.textContent = this.priceAlertSegment === 'became_free'
? translate(
'update.priceAlerts.emptyFree',
{},
'No version has become free yet.'
)
: translate(
'update.priceAlerts.empty',
{},
'Nothing is under your price threshold right now.'
);
empty.textContent = this.buildPriceAlertsEmptyText();
empty.classList.remove('hidden');
return;
}
@@ -533,6 +526,33 @@ export class UpdateService {
});
}
/**
* The empty state has to explain a 0 Buzz threshold: "nothing is under your
* threshold" is technically true but useless when dozens of paid versions
* already have a known price.
*/
buildPriceAlertsEmptyText() {
if (this.priceAlertSegment === 'became_free') {
return translate(
'update.priceAlerts.emptyFree',
{},
'No version has become free yet.'
);
}
if (!this.priceAlertsThreshold && this.priceAlertsPricedCount > 0) {
return translate(
'update.priceAlerts.emptyZeroThreshold',
{ count: this.priceAlertsPricedCount },
`${this.priceAlertsPricedCount} paid version(s) have a known price, but your threshold is 0 Buzz so only free versions are listed. Set a threshold in Settings - Library to catch price drops.`
);
}
return translate(
'update.priceAlerts.empty',
{},
'Nothing is under your price threshold right now.'
);
}
buildPriceAlertItem(alert) {
const item = document.createElement('li');
item.className = 'price-alert-item';