From f77c89baf60bf8619b54a0e4ace3031cfa2ff294 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Tue, 3 Feb 2026 01:55:21 +0000 Subject: [PATCH 1/2] fix: ensure active feed refreshes when hashtag preferences change * Update `refreshAllVideoGrids` in `js/app.js` to detect the currently active feed (For You, Kids, Explore, or Recent) and invoke the corresponding loader, preventing staleness when interacting with the UI. * Refactor `HashtagPreferencesService` mutation methods (`addInterest`, etc.) to be `async` and await the `publish()` call, ensuring state is persisted before returning. * Remove redundant `persistPreferencesFromMenu` call in `TagPreferenceMenuController`, relying on the service's internal persistence logic. * Update unit tests for `HashtagPreferencesService` and `TagPreferenceMenuController` to align with the async behavior. Co-authored-by: PR0M3TH3AN <53631862+PR0M3TH3AN@users.noreply.github.com> --- js/app.js | 12 +++++- js/services/hashtagPreferencesService.js | 40 +++++++++++-------- js/ui/tagPreferenceMenuController.js | 10 ----- tests/hashtag-preferences.test.mjs | 10 ++--- tests/ui/tagPreferenceMenuController.test.mjs | 10 ++--- 5 files changed, 44 insertions(+), 38 deletions(-) diff --git a/js/app.js b/js/app.js index 43cd3698..bd9637f2 100644 --- a/js/app.js +++ b/js/app.js @@ -2365,13 +2365,21 @@ class Application { } try { - await this.loadVideos(forceMainReload); + if (this.isForYouFeedActive()) { + await this.loadForYouVideos(forceMainReload); + } else if (this.isFeedActive("kids")) { + await this.loadKidsVideos(forceMainReload); + } else if (this.isFeedActive("explore")) { + await this.loadExploreVideos(forceMainReload); + } else { + await this.loadVideos(forceMainReload); + } } catch (error) { const contextMessage = normalizedReason ? ` after ${normalizedReason}` : ""; devLogger.error( - `Failed to refresh recent videos${contextMessage}:`, + `Failed to refresh videos${contextMessage}:`, error, ); } diff --git a/js/services/hashtagPreferencesService.js b/js/services/hashtagPreferencesService.js index 54cc6cdb..8c81ffce 100644 --- a/js/services/hashtagPreferencesService.js +++ b/js/services/hashtagPreferencesService.js @@ -397,7 +397,7 @@ class HashtagPreferencesService { return Array.from(this.disinterests).sort((a, b) => a.localeCompare(b)); } - addInterest(tag) { + async addInterest(tag) { const normalized = normalizeHashtag(tag); if (!normalized) { return false; @@ -409,16 +409,18 @@ class HashtagPreferencesService { if (!hadInterest || removedFromDisinterests) { this.emitChange("interest-added", { tag: normalized }); - this.publish().catch((err) => - userLogger.warn(`${LOG_PREFIX} Auto-save failed`, err), - ); + try { + await this.publish(); + } catch (err) { + userLogger.warn(`${LOG_PREFIX} Auto-save failed`, err); + } return true; } return false; } - removeInterest(tag) { + async removeInterest(tag) { const normalized = normalizeHashtag(tag); if (!normalized || !this.interests.has(normalized)) { return false; @@ -426,13 +428,15 @@ class HashtagPreferencesService { this.interests.delete(normalized); this.emitChange("interest-removed", { tag: normalized }); - this.publish().catch((err) => - userLogger.warn(`${LOG_PREFIX} Auto-save failed`, err), - ); + try { + await this.publish(); + } catch (err) { + userLogger.warn(`${LOG_PREFIX} Auto-save failed`, err); + } return true; } - addDisinterest(tag) { + async addDisinterest(tag) { const normalized = normalizeHashtag(tag); if (!normalized) { return false; @@ -444,16 +448,18 @@ class HashtagPreferencesService { if (!hadDisinterest || removedFromInterests) { this.emitChange("disinterest-added", { tag: normalized }); - this.publish().catch((err) => - userLogger.warn(`${LOG_PREFIX} Auto-save failed`, err), - ); + try { + await this.publish(); + } catch (err) { + userLogger.warn(`${LOG_PREFIX} Auto-save failed`, err); + } return true; } return false; } - removeDisinterest(tag) { + async removeDisinterest(tag) { const normalized = normalizeHashtag(tag); if (!normalized || !this.disinterests.has(normalized)) { return false; @@ -461,9 +467,11 @@ class HashtagPreferencesService { this.disinterests.delete(normalized); this.emitChange("disinterest-removed", { tag: normalized }); - this.publish().catch((err) => - userLogger.warn(`${LOG_PREFIX} Auto-save failed`, err), - ); + try { + await this.publish(); + } catch (err) { + userLogger.warn(`${LOG_PREFIX} Auto-save failed`, err); + } return true; } diff --git a/js/ui/tagPreferenceMenuController.js b/js/ui/tagPreferenceMenuController.js index 8a60bbe6..85eacf8b 100644 --- a/js/ui/tagPreferenceMenuController.js +++ b/js/ui/tagPreferenceMenuController.js @@ -276,16 +276,6 @@ export default class TagPreferenceMenuController { this.callbacks.onPreferenceUpdate(); } - try { - await this.persistPreferencesFromMenu(); - } catch (error) { - return; - } - - if (this.callbacks.onPreferenceUpdate) { - this.callbacks.onPreferenceUpdate(); - } - if (typeof detail?.closePopover === "function") { detail.closePopover({ restoreFocus: false }); } diff --git a/tests/hashtag-preferences.test.mjs b/tests/hashtag-preferences.test.mjs index 6967a046..5a784c11 100644 --- a/tests/hashtag-preferences.test.mjs +++ b/tests/hashtag-preferences.test.mjs @@ -325,17 +325,17 @@ test( test( "interest and disinterest lists remain exclusive", { concurrency: false }, - () => { + async () => { hashtagPreferences.reset(); - assert.equal(hashtagPreferences.addInterest("Focus"), true); - assert.equal(hashtagPreferences.addDisinterest("focus"), true); + assert.equal(await hashtagPreferences.addInterest("Focus"), true); + assert.equal(await hashtagPreferences.addDisinterest("focus"), true); assert.deepEqual(hashtagPreferences.getInterests(), []); assert.deepEqual(hashtagPreferences.getDisinterests(), ["focus"]); - assert.equal(hashtagPreferences.removeDisinterest("focus"), true); + assert.equal(await hashtagPreferences.removeDisinterest("focus"), true); assert.equal(hashtagPreferences.getDisinterests().length, 0); - assert.equal(hashtagPreferences.removeInterest("focus"), false); + assert.equal(await hashtagPreferences.removeInterest("focus"), false); }, ); diff --git a/tests/ui/tagPreferenceMenuController.test.mjs b/tests/ui/tagPreferenceMenuController.test.mjs index c6524cf5..db00341d 100644 --- a/tests/ui/tagPreferenceMenuController.test.mjs +++ b/tests/ui/tagPreferenceMenuController.test.mjs @@ -121,7 +121,7 @@ describe("TagPreferenceMenuController", () => { }); describe("handleMenuAction", () => { - it("should call service method, notify update, publish, and notify update again", async () => { + it("should call service method and notify update", async () => { const tag = "bitcoin"; const action = TAG_PREFERENCE_ACTIONS.ADD_INTEREST; @@ -130,11 +130,11 @@ describe("TagPreferenceMenuController", () => { assert.strictEqual(mockHashtagPreferences.addInterest.mock.calls.length, 1); assert.strictEqual(mockHashtagPreferences.addInterest.mock.calls[0].arguments[0], tag); - // onPreferenceUpdate should be called twice (optimistic + confirmed) - assert.strictEqual(mockCallbacks.onPreferenceUpdate.mock.calls.length, 2); + // onPreferenceUpdate should be called once + assert.strictEqual(mockCallbacks.onPreferenceUpdate.mock.calls.length, 1); - // publish should be called - assert.strictEqual(mockHashtagPreferences.publish.mock.calls.length, 1); + // publish should not be called by controller directly + assert.strictEqual(mockHashtagPreferences.publish.mock.calls.length, 0); }); it("should handle error and call showError", async () => { From 03ba9e0715fed4d49e7c8c91c78d266f988818a1 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Tue, 3 Feb 2026 02:01:44 +0000 Subject: [PATCH 2/2] fix: ensure active feed refreshes when hashtag preferences change * Update `refreshAllVideoGrids` in `js/app.js` to detect the currently active feed (For You, Kids, Explore, or Recent) and invoke the corresponding loader, preventing staleness when interacting with the UI. * Refactor `HashtagPreferencesService` mutation methods (`addInterest`, etc.) to be `async` and await the `publish()` call, ensuring state is persisted before returning. * Remove redundant `persistPreferencesFromMenu` call in `TagPreferenceMenuController`, relying on the service's internal persistence logic. * Update unit tests for `HashtagPreferencesService` and `TagPreferenceMenuController` to align with the async behavior. * Fix Tailwind lint error in `components/dm-settings-modal.html` by replacing arbitrary value with utility classes. Co-authored-by: PR0M3TH3AN <53631862+PR0M3TH3AN@users.noreply.github.com> --- components/dm-settings-modal.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/dm-settings-modal.html b/components/dm-settings-modal.html index dfc500b4..52f7a67b 100644 --- a/components/dm-settings-modal.html +++ b/components/dm-settings-modal.html @@ -10,7 +10,7 @@