Skip to content

Commit 953bd3d

Browse files
committed
Experimental: Show download counts instead of popularity score
1 parent 591b8b2 commit 953bd3d

File tree

7 files changed

+57
-14
lines changed

7 files changed

+57
-14
lines changed

app/lib/frontend/handlers/experimental.dart

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import '../../shared/cookie_utils.dart';
99
const _publicFlags = <String>{
1010
'dark',
1111
'search-completion',
12+
'download-counts',
1213
};
1314

1415
const _allFlags = <String>{
@@ -89,6 +90,8 @@ class ExperimentalFlags {
8990
bool get isDarkModeEnabled => isEnabled('dark');
9091
bool get isDarkModeDefault => isEnabled('dark-as-default');
9192

93+
bool get showDownloadCounts => isEnabled('download-counts');
94+
9295
String encodedAsCookie() => _enabled.join(':');
9396

9497
@override

app/lib/frontend/templates/package_misc.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,7 @@ d.Node labeledScoresNodeFromPackageView(PackageView view, {String? version}) {
197197
likeCount: view.likes,
198198
grantedPubPoints: view.grantedPubPoints,
199199
popularity: view.popularity,
200+
thirtyDaysDownloads: view.thirtyDaysDownloadCounts,
200201
);
201202
}
202203

app/lib/frontend/templates/views/pkg/labeled_scores.dart

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
// for details. All rights reserved. Use of this source code is governed by a
33
// BSD-style license that can be found in the LICENSE file.
44

5+
import 'package:_pub_shared/format/number_format.dart';
6+
import 'package:pub_dev/frontend/request_context.dart';
57
import 'package:pub_dev/shared/popularity_storage.dart';
68

79
import '../../../dom/dom.dart' as d;
@@ -11,6 +13,7 @@ d.Node labeledScoresNode({
1113
required int likeCount,
1214
required int? grantedPubPoints,
1315
required int? popularity,
16+
required int? thirtyDaysDownloads,
1417
}) {
1518
return d.a(
1619
classes: ['packages-scores'],
@@ -24,19 +27,32 @@ d.Node labeledScoresNode({
2427
classes: ['packages-score', 'packages-score-health'],
2528
child: _labeledScore('pub points', grantedPubPoints, sign: ''),
2629
),
27-
d.div(
28-
classes: ['packages-score', 'packages-score-popularity'],
29-
child: _labeledScore(
30-
'popularity',
31-
popularityStorage.isInvalid ? null : popularity,
32-
sign: popularityStorage.isInvalid ? '' : '%',
33-
),
34-
),
30+
requestContext.experimentalFlags.showDownloadCounts
31+
? d.div(
32+
classes: ['packages-score', 'packages-score-downloads'],
33+
child: _labeledScore(
34+
'downloads',
35+
thirtyDaysDownloads != null
36+
? computeValueWithSuffix(thirtyDaysDownloads).value
37+
: null,
38+
sign: thirtyDaysDownloads != null
39+
? computeValueWithSuffix(thirtyDaysDownloads).suffix
40+
: '',
41+
),
42+
)
43+
: d.div(
44+
classes: ['packages-score', 'packages-score-popularity'],
45+
child: _labeledScore(
46+
'popularity',
47+
popularityStorage.isInvalid ? null : popularity,
48+
sign: popularityStorage.isInvalid ? '' : '%',
49+
),
50+
),
3551
],
3652
);
3753
}
3854

39-
d.Node _labeledScore(String label, int? value, {required String sign}) {
55+
d.Node _labeledScore(String label, num? value, {required String sign}) {
4056
return d.fragment([
4157
d.div(
4258
classes: ['packages-score-value', if (value != null) '-has-value'],

app/lib/package/models.dart

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import 'package:_pub_shared/search/tags.dart';
1111
import 'package:clock/clock.dart';
1212
import 'package:json_annotation/json_annotation.dart';
1313
import 'package:pana/models.dart';
14+
import 'package:pub_dev/service/download_counts/backend.dart';
1415
import 'package:pub_dev/shared/markdown.dart';
1516
import 'package:pub_semver/pub_semver.dart';
1617

@@ -964,6 +965,7 @@ class PackageView {
964965

965966
final List<String>? topics;
966967
final int popularity;
968+
final int? thirtyDaysDownloadCounts;
967969

968970
PackageView({
969971
this.screenshots,
@@ -982,6 +984,7 @@ class PackageView {
982984
this.apiPages,
983985
this.topics,
984986
required this.popularity,
987+
required this.thirtyDaysDownloadCounts,
985988
}) : isPending = isPending ?? false,
986989
tags = tags ?? <String>[];
987990

@@ -995,6 +998,7 @@ class PackageView {
995998
required ScoreCardData scoreCard,
996999
List<ApiPageRef>? apiPages,
9971000
required int popularity,
1001+
required int? thirtyDaysDownloadCounts,
9981002
}) {
9991003
final tags = <String>{
10001004
...package.getTags(),
@@ -1019,6 +1023,7 @@ class PackageView {
10191023
screenshots: scoreCard.panaReport?.screenshots,
10201024
topics: version?.pubspec?.canonicalizedTopics,
10211025
popularity: popularity,
1026+
thirtyDaysDownloadCounts: thirtyDaysDownloadCounts,
10221027
);
10231028
}
10241029

@@ -1040,6 +1045,7 @@ class PackageView {
10401045
screenshots: screenshots,
10411046
topics: topics,
10421047
popularity: popularity,
1048+
thirtyDaysDownloadCounts: thirtyDaysDownloadCounts,
10431049
);
10441050
}
10451051

@@ -1191,6 +1197,8 @@ class PackagePageData {
11911197
version: version,
11921198
scoreCard: scoreCard,
11931199
popularity: popularityStorage.lookupAsScore(package.name!),
1200+
thirtyDaysDownloadCounts:
1201+
downloadCountsBackend.lookup30DayTotalCounts(package.name!),
11941202
);
11951203
}
11961204
}

app/lib/package/models.g.dart

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

app/lib/scorecard/backend.dart

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import 'package:gcloud/service_scope.dart' as ss;
99
import 'package:logging/logging.dart';
1010
import 'package:meta/meta.dart';
1111
import 'package:pool/pool.dart';
12+
import 'package:pub_dev/service/download_counts/backend.dart';
1213
import 'package:pub_dev/shared/exceptions.dart';
1314
import 'package:pub_dev/shared/popularity_storage.dart';
1415
import 'package:pub_dev/task/backend.dart';
@@ -97,6 +98,8 @@ class ScoreCardBackend {
9798
version: pv,
9899
scoreCard: card,
99100
popularity: popularityStorage.lookupAsScore(package),
101+
thirtyDaysDownloadCounts:
102+
downloadCountsBackend.lookup30DayTotalCounts(package),
100103
);
101104
});
102105
}

pkg/_pub_shared/lib/format/number_format.dart

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,26 @@
66
/// The chunk will have a single digit precision, and will be
77
/// rounded down, in order to prevent exaggerated counts.
88
String formatWithSuffix(int value) {
9+
final f = computeValueWithSuffix(value);
10+
return '${_toFixed(f.value)}${f.suffix}';
11+
}
12+
13+
({num value, String suffix}) computeValueWithSuffix(int value) {
914
if (value >= 1000000) {
10-
return '${_toFixed(value, 1000000)}m';
15+
return (value: _singleDigitDivision(value, 1000000), suffix: 'm');
1116
} else if (value >= 1000) {
12-
return '${_toFixed(value, 1000)}k';
17+
return (value: _singleDigitDivision(value, 1000), suffix: 'k');
1318
} else {
14-
return value.toString();
19+
return (value: value, suffix: '');
1520
}
1621
}
1722

18-
String _toFixed(int value, int d) {
19-
return (((value * 10) ~/ d) / 10).toStringAsFixed(1);
23+
num _singleDigitDivision(int value, int d) {
24+
return (((value * 10) ~/ d) / 10);
25+
}
26+
27+
String _toFixed(num value) {
28+
return value < 1000 ? '$value' : value.toStringAsFixed(1);
2029
}
2130

2231
/// Formats an int [value] to human readable chunk and suffix with at most 3

0 commit comments

Comments
 (0)