diff --git a/app/lib/account/like_backend.dart b/app/lib/account/like_backend.dart index 3d33de72ef..902c0eeacc 100644 --- a/app/lib/account/like_backend.dart +++ b/app/lib/account/like_backend.dart @@ -75,6 +75,7 @@ class LikeBackend { tx.queueMutations(inserts: [p, newLike]); return newLike; }); + await cache.packageView(package).purge(); await purgeAccountCache(userId: user.userId); return res; } @@ -100,6 +101,7 @@ class LikeBackend { p.likes--; tx.queueMutations(inserts: [p], deletes: [likeKey]); }); + await cache.packageView(package).purge(); await cache.userPackageLikes(user.userId).purge(); } } diff --git a/app/lib/frontend/templates/views/pkg/liked_package_list.dart b/app/lib/frontend/templates/views/pkg/liked_package_list.dart index dec1249cc5..19cc4ccd42 100644 --- a/app/lib/frontend/templates/views/pkg/liked_package_list.dart +++ b/app/lib/frontend/templates/views/pkg/liked_package_list.dart @@ -72,22 +72,20 @@ d.Node renderLikeButtonAndLabel( return d.div( classes: ['like-button-and-label'], children: [ - _renderLikeButton(package, isLiked), + renderLikeButton(package, likeCount: likeCount, isLiked: isLiked), d.span( classes: ['like-button-and-label--count-wrapper'], child: d.span( classes: ['like-button-and-label--count'], text: _formatPackageLikes(likeCount), - attributes: { - 'data-value': likeCount.toString(), - }, ), ), ], ); } -d.Node _renderLikeButton(String package, bool isLiked) { +d.Node renderLikeButton(String package, + {required int likeCount, required bool isLiked}) { return material.iconButton( classes: ['like-button-and-label--button'], isOn: isLiked, @@ -108,6 +106,7 @@ d.Node _renderLikeButton(String package, bool isLiked) { 'data-ga-click-event': 'toggle-like', 'aria-pressed': isLiked ? 'true' : 'false', 'data-package': package, + 'data-value': likeCount.toString(), }, ); } diff --git a/app/lib/frontend/templates/views/pkg/package_list.dart b/app/lib/frontend/templates/views/pkg/package_list.dart index e3e5cd070e..12f869dcd3 100644 --- a/app/lib/frontend/templates/views/pkg/package_list.dart +++ b/app/lib/frontend/templates/views/pkg/package_list.dart @@ -6,6 +6,8 @@ import 'package:_pub_shared/format/x_ago_format.dart'; import 'package:_pub_shared/search/search_form.dart'; import 'package:_pub_shared/search/tags.dart'; import 'package:clock/clock.dart'; +import 'package:pub_dev/frontend/request_context.dart'; +import 'package:pub_dev/frontend/templates/views/pkg/liked_package_list.dart'; import '../../../../package/models.dart'; import '../../../../package/screenshots/backend.dart'; @@ -31,6 +33,11 @@ d.Node listOfPackagesNode({ }) { final bestNameMatch = (nameMatches == null || nameMatches.isEmpty) ? null : nameMatches.first; + final listingPackagesLikedByMe = + requestContext.experimentalFlags.useMyLikedSearch && + (searchForm?.parsedQuery.tagsPredicate + .isRequiredTag(AccountTag.isLikedByMe) ?? + false); return d.div( classes: ['packages'], children: [ @@ -39,6 +46,7 @@ d.Node listOfPackagesNode({ hit, searchForm: searchForm, isNameMatch: hit.name == bestNameMatch, + isLiked: listingPackagesLikedByMe, )), imageCarousel(), ], @@ -77,6 +85,7 @@ d.Node _packageItem( PackageView view, { required SearchForm? searchForm, required bool isNameMatch, + required bool isLiked, }) { final isFlutterFavorite = view.tags.contains(PackageTags.isFlutterFavorite); final isNullSafe = view.tags.contains(PackageVersionTags.isNullSafe); @@ -188,6 +197,9 @@ d.Node _packageItem( labeledScoresNode: labeledScoresNodeFromPackageView(view), description: view.ellipsizedDescription ?? '', metadataNode: metadataNode, + likeIcon: isLiked + ? renderLikeButton(view.name, likeCount: view.likes, isLiked: isLiked) + : null, copyIcon: copyIcon(package: view.name, version: view.releases.stable.version), tagsNode: tagsNodeFromPackageView(searchForm: searchForm, package: view), @@ -220,6 +232,7 @@ d.Node _item({ required String description, required d.Node metadataNode, required d.Node? tagsNode, + d.Node? likeIcon, d.Node? copyIcon, required String? replacedBy, required List<_ApiPageUrl>? apiPages, @@ -237,6 +250,7 @@ d.Node _item({ 'pub-monochrome-icon-hoverable', ], children: [ d.a(href: url, text: name), + if (likeIcon != null) ...[d.text(' '), likeIcon], if (copyIcon != null) copyIcon, d.text(' '), if (isNameMatch) nameMatchBadgeNode, diff --git a/app/test/frontend/golden/pkg_activity_log_page.html b/app/test/frontend/golden/pkg_activity_log_page.html index 269e732a29..b4960f90d9 100644 --- a/app/test/frontend/golden/pkg_activity_log_page.html +++ b/app/test/frontend/golden/pkg_activity_log_page.html @@ -186,12 +186,12 @@

-
diff --git a/app/test/frontend/golden/pkg_admin_page.html b/app/test/frontend/golden/pkg_admin_page.html index 00595e346d..042e02fde1 100644 --- a/app/test/frontend/golden/pkg_admin_page.html +++ b/app/test/frontend/golden/pkg_admin_page.html @@ -186,12 +186,12 @@

-
diff --git a/app/test/frontend/golden/pkg_changelog_page.html b/app/test/frontend/golden/pkg_changelog_page.html index dbd5e7559d..9fa751533c 100644 --- a/app/test/frontend/golden/pkg_changelog_page.html +++ b/app/test/frontend/golden/pkg_changelog_page.html @@ -161,12 +161,12 @@

-
diff --git a/app/test/frontend/golden/pkg_example_page.html b/app/test/frontend/golden/pkg_example_page.html index 37263ca75f..9d6e649250 100644 --- a/app/test/frontend/golden/pkg_example_page.html +++ b/app/test/frontend/golden/pkg_example_page.html @@ -161,12 +161,12 @@

-
diff --git a/app/test/frontend/golden/pkg_install_page.html b/app/test/frontend/golden/pkg_install_page.html index 13a25c95da..8bb63acedb 100644 --- a/app/test/frontend/golden/pkg_install_page.html +++ b/app/test/frontend/golden/pkg_install_page.html @@ -161,12 +161,12 @@

-
diff --git a/app/test/frontend/golden/pkg_score_page.html b/app/test/frontend/golden/pkg_score_page.html index be2c1a29b6..96549ca7e8 100644 --- a/app/test/frontend/golden/pkg_score_page.html +++ b/app/test/frontend/golden/pkg_score_page.html @@ -161,12 +161,12 @@

-
diff --git a/app/test/frontend/golden/pkg_score_page_with_downloads_chart.html b/app/test/frontend/golden/pkg_score_page_with_downloads_chart.html index be2c1a29b6..96549ca7e8 100644 --- a/app/test/frontend/golden/pkg_score_page_with_downloads_chart.html +++ b/app/test/frontend/golden/pkg_score_page_with_downloads_chart.html @@ -161,12 +161,12 @@

-
diff --git a/app/test/frontend/golden/pkg_show_page.html b/app/test/frontend/golden/pkg_show_page.html index af68a92d5d..f6ba2049f8 100644 --- a/app/test/frontend/golden/pkg_show_page.html +++ b/app/test/frontend/golden/pkg_show_page.html @@ -152,12 +152,12 @@

-
diff --git a/app/test/frontend/golden/pkg_show_page_discontinued.html b/app/test/frontend/golden/pkg_show_page_discontinued.html index e736343abf..06754b1f37 100644 --- a/app/test/frontend/golden/pkg_show_page_discontinued.html +++ b/app/test/frontend/golden/pkg_show_page_discontinued.html @@ -160,12 +160,12 @@

-
diff --git a/app/test/frontend/golden/pkg_show_page_flutter_plugin.html b/app/test/frontend/golden/pkg_show_page_flutter_plugin.html index 975fba5106..74053bf0e9 100644 --- a/app/test/frontend/golden/pkg_show_page_flutter_plugin.html +++ b/app/test/frontend/golden/pkg_show_page_flutter_plugin.html @@ -150,12 +150,12 @@

-
diff --git a/app/test/frontend/golden/pkg_show_page_publisher.html b/app/test/frontend/golden/pkg_show_page_publisher.html index 4c53104a61..677c1d5f8b 100644 --- a/app/test/frontend/golden/pkg_show_page_publisher.html +++ b/app/test/frontend/golden/pkg_show_page_publisher.html @@ -155,12 +155,12 @@

-
diff --git a/app/test/frontend/golden/pkg_show_page_retracted.html b/app/test/frontend/golden/pkg_show_page_retracted.html index cdd3716100..069d0b2360 100644 --- a/app/test/frontend/golden/pkg_show_page_retracted.html +++ b/app/test/frontend/golden/pkg_show_page_retracted.html @@ -143,12 +143,12 @@

retracted
-
diff --git a/app/test/frontend/golden/pkg_show_page_retracted_non_retracted_version.html b/app/test/frontend/golden/pkg_show_page_retracted_non_retracted_version.html index 24ee2e3fc5..36a593d4c0 100644 --- a/app/test/frontend/golden/pkg_show_page_retracted_non_retracted_version.html +++ b/app/test/frontend/golden/pkg_show_page_retracted_non_retracted_version.html @@ -151,12 +151,12 @@

-
diff --git a/app/test/frontend/golden/pkg_show_version_page.html b/app/test/frontend/golden/pkg_show_version_page.html index 1281df1116..18c786cd46 100644 --- a/app/test/frontend/golden/pkg_show_version_page.html +++ b/app/test/frontend/golden/pkg_show_version_page.html @@ -161,12 +161,12 @@

-
diff --git a/app/test/frontend/golden/pkg_versions_page.html b/app/test/frontend/golden/pkg_versions_page.html index 5c375e6bb4..f3e51ffe3e 100644 --- a/app/test/frontend/golden/pkg_versions_page.html +++ b/app/test/frontend/golden/pkg_versions_page.html @@ -160,12 +160,12 @@

-
diff --git a/app/test/task/testdata/goldens/packages/oxygen.html b/app/test/task/testdata/goldens/packages/oxygen.html index f8ed0f947b..6245c89564 100644 --- a/app/test/task/testdata/goldens/packages/oxygen.html +++ b/app/test/task/testdata/goldens/packages/oxygen.html @@ -153,12 +153,12 @@

-
diff --git a/app/test/task/testdata/goldens/packages/oxygen/changelog.html b/app/test/task/testdata/goldens/packages/oxygen/changelog.html index 1c3f7c7afd..68a6c5213e 100644 --- a/app/test/task/testdata/goldens/packages/oxygen/changelog.html +++ b/app/test/task/testdata/goldens/packages/oxygen/changelog.html @@ -153,12 +153,12 @@

-
diff --git a/app/test/task/testdata/goldens/packages/oxygen/example.html b/app/test/task/testdata/goldens/packages/oxygen/example.html index a3e6788e33..9b24bf9544 100644 --- a/app/test/task/testdata/goldens/packages/oxygen/example.html +++ b/app/test/task/testdata/goldens/packages/oxygen/example.html @@ -153,12 +153,12 @@

-
diff --git a/app/test/task/testdata/goldens/packages/oxygen/install.html b/app/test/task/testdata/goldens/packages/oxygen/install.html index 7e5cbe8c87..a261d4bd6d 100644 --- a/app/test/task/testdata/goldens/packages/oxygen/install.html +++ b/app/test/task/testdata/goldens/packages/oxygen/install.html @@ -153,12 +153,12 @@

-
diff --git a/app/test/task/testdata/goldens/packages/oxygen/license.html b/app/test/task/testdata/goldens/packages/oxygen/license.html index 58ed2570e9..96b2aa6f0e 100644 --- a/app/test/task/testdata/goldens/packages/oxygen/license.html +++ b/app/test/task/testdata/goldens/packages/oxygen/license.html @@ -153,12 +153,12 @@

-
diff --git a/app/test/task/testdata/goldens/packages/oxygen/score.html b/app/test/task/testdata/goldens/packages/oxygen/score.html index 80b6748411..3f362ac2d6 100644 --- a/app/test/task/testdata/goldens/packages/oxygen/score.html +++ b/app/test/task/testdata/goldens/packages/oxygen/score.html @@ -153,12 +153,12 @@

-
diff --git a/app/test/task/testdata/goldens/packages/oxygen/versions.html b/app/test/task/testdata/goldens/packages/oxygen/versions.html index bd17e6b3e6..39ccd3a3d7 100644 --- a/app/test/task/testdata/goldens/packages/oxygen/versions.html +++ b/app/test/task/testdata/goldens/packages/oxygen/versions.html @@ -152,12 +152,12 @@

-
diff --git a/app/test/task/testdata/goldens/packages/oxygen/versions/1.0.0.html b/app/test/task/testdata/goldens/packages/oxygen/versions/1.0.0.html index 684ad631a6..5460275eea 100644 --- a/app/test/task/testdata/goldens/packages/oxygen/versions/1.0.0.html +++ b/app/test/task/testdata/goldens/packages/oxygen/versions/1.0.0.html @@ -157,12 +157,12 @@

-
diff --git a/app/test/task/testdata/goldens/packages/oxygen/versions/1.0.0/changelog.html b/app/test/task/testdata/goldens/packages/oxygen/versions/1.0.0/changelog.html index a3cbc11b47..fcc3637be1 100644 --- a/app/test/task/testdata/goldens/packages/oxygen/versions/1.0.0/changelog.html +++ b/app/test/task/testdata/goldens/packages/oxygen/versions/1.0.0/changelog.html @@ -157,12 +157,12 @@

-
diff --git a/app/test/task/testdata/goldens/packages/oxygen/versions/1.0.0/example.html b/app/test/task/testdata/goldens/packages/oxygen/versions/1.0.0/example.html index 0aa62eef7d..098fbcc61b 100644 --- a/app/test/task/testdata/goldens/packages/oxygen/versions/1.0.0/example.html +++ b/app/test/task/testdata/goldens/packages/oxygen/versions/1.0.0/example.html @@ -157,12 +157,12 @@

-
diff --git a/app/test/task/testdata/goldens/packages/oxygen/versions/1.0.0/install.html b/app/test/task/testdata/goldens/packages/oxygen/versions/1.0.0/install.html index f8a380a489..53783e83e0 100644 --- a/app/test/task/testdata/goldens/packages/oxygen/versions/1.0.0/install.html +++ b/app/test/task/testdata/goldens/packages/oxygen/versions/1.0.0/install.html @@ -157,12 +157,12 @@

-
diff --git a/app/test/task/testdata/goldens/packages/oxygen/versions/1.0.0/license.html b/app/test/task/testdata/goldens/packages/oxygen/versions/1.0.0/license.html index 8914894695..f2007604e8 100644 --- a/app/test/task/testdata/goldens/packages/oxygen/versions/1.0.0/license.html +++ b/app/test/task/testdata/goldens/packages/oxygen/versions/1.0.0/license.html @@ -157,12 +157,12 @@

-
diff --git a/app/test/task/testdata/goldens/packages/oxygen/versions/1.0.0/score.html b/app/test/task/testdata/goldens/packages/oxygen/versions/1.0.0/score.html index 3c367dd540..6c1a0b95c7 100644 --- a/app/test/task/testdata/goldens/packages/oxygen/versions/1.0.0/score.html +++ b/app/test/task/testdata/goldens/packages/oxygen/versions/1.0.0/score.html @@ -157,12 +157,12 @@

-
diff --git a/app/test/task/testdata/goldens/packages/oxygen/versions/2.0.0.html b/app/test/task/testdata/goldens/packages/oxygen/versions/2.0.0.html index f8ed0f947b..6245c89564 100644 --- a/app/test/task/testdata/goldens/packages/oxygen/versions/2.0.0.html +++ b/app/test/task/testdata/goldens/packages/oxygen/versions/2.0.0.html @@ -153,12 +153,12 @@

-
diff --git a/pkg/pub_integration/test/like_test.dart b/pkg/pub_integration/test/like_test.dart index a19899e48b..ac1a442c78 100644 --- a/pkg/pub_integration/test/like_test.dart +++ b/pkg/pub_integration/test/like_test.dart @@ -60,14 +60,15 @@ void main() { await user.withBrowserPage((page) async { Future> getCountLabels() async { - final buttonLabel = await page.$('.like-button-and-label--count'); - final viewLabel = - await page.$('.packages-score-like .packages-score-value-number'); + final buttonLabel = + await page.$OrNull('.like-button-and-label--count'); + final viewLabel = await page + .$OrNull('.packages-score-like .packages-score-value-number'); final keyScoreLabel = await page .$OrNull('.score-key-figure--likes .score-key-figure-value'); return [ - await buttonLabel.textContent(), - await viewLabel.textContent(), + (await buttonLabel?.textContent()) ?? '', + (await viewLabel?.textContent()) ?? '', (await keyScoreLabel?.textContent()) ?? '', ]; } @@ -83,7 +84,7 @@ void main() { expect(await getCountLabels(), ['0', '0', '']); await page.click('.like-button-and-label--button'); - await Future.delayed(Duration(seconds: 1)); + await Future.delayed(Duration(milliseconds: 200)); expect(await getCountLabels(), ['1', '1', '']); // checking search with my-liked packages - with the one liked package @@ -96,12 +97,32 @@ void main() { expect(await getCountLabels(), ['1', '1', '1']); await page.click('.like-button-and-label--button'); - await Future.delayed(Duration(seconds: 1)); + await Future.delayed(Duration(milliseconds: 200)); // checking it on the main package page too expect(await getCountLabels(), ['0', '0', '0']); await page.gotoOrigin('/packages/test_pkg'); expect(await getCountLabels(), ['0', '0', '']); + + // unlike on the is:liked-by-me page + { + await page.gotoOrigin('/packages/test_pkg'); + await page.click('.like-button-and-label--button'); + await Future.delayed(Duration(milliseconds: 200)); + expect(await getCountLabels(), ['1', '1', '']); + + await page.gotoOrigin('/packages?q=pkg+is:liked-by-me'); + final info = await listingPageInfo(page); + expect(info.packageNames.toSet(), {'test_pkg'}); + expect(await getCountLabels(), ['', '1', '']); + + await page.click('.like-button-and-label--button'); + await Future.delayed(Duration(milliseconds: 200)); + expect(await getCountLabels(), ['', '0', '']); + + await page.gotoOrigin('/packages/test_pkg'); + expect(await getCountLabels(), ['0', '0', '']); + } }); }); }); diff --git a/pkg/web_app/lib/src/likes.dart b/pkg/web_app/lib/src/likes.dart index 6e775dddec..53642d1049 100644 --- a/pkg/web_app/lib/src/likes.dart +++ b/pkg/web_app/lib/src/likes.dart @@ -48,21 +48,22 @@ void setupLikes() { for (final likeButton in document.querySelectorAll('.like-button-and-label--button')) { final package = likeButton.dataset['package']; - if (package == null || package.isEmpty) continue; + final originalCount = int.tryParse(likeButton.dataset['value'] ?? ''); - final countLabel = - likeButton.parent?.querySelector('.like-button-and-label--count'); - final originalCount = int.tryParse(countLabel?.dataset['value'] ?? ''); + if (package == null || package.isEmpty || originalCount == null) { + continue; + } var likesDelta = 0; void updateLabels() { - if (countLabel == null || originalCount == null) { - return; - } final likesCount = originalCount + likesDelta; - // keep in-sync with app/lib/frontend/templates/views/pkg/liked_package_list.dart - countLabel.innerText = formatWithSuffix(likesCount); + final countLabel = + likeButton.parent?.querySelector('.like-button-and-label--count'); + if (countLabel != null) { + // keep in-sync with app/lib/frontend/templates/views/pkg/liked_package_list.dart + countLabel.innerText = formatWithSuffix(likesCount); + } // keep in-sync with app/lib/frontend/templates/views/pkg/labeled_scores.dart final formatted = compactFormat(likesCount); diff --git a/pkg/web_css/lib/src/_list.scss b/pkg/web_css/lib/src/_list.scss index 7b9cde7f0d..f667841185 100644 --- a/pkg/web_css/lib/src/_list.scss +++ b/pkg/web_css/lib/src/_list.scss @@ -234,6 +234,11 @@ font-weight: 500; margin: 0; overflow-wrap: anywhere; + + .like-button-and-label--button img { + width: 18px; + height: 18px; + } } .packages-recent {