Merge pull request #2076 from PR0M3TH3AN/fix-hashtag-preferences-feed-update-17909862924383891447

Fix feed update consistency when modifying hashtag preferences
This commit is contained in:
thePR0M3TH3AN authored and GitHub committed 2026-02-02 21:36:34 -05:00
commit ccc93518d0
6 files changed
+45 -39

No files matched your search

+1 -1
View File
@@ -10,7 +10,7 @@
<div class="bv-modal-backdrop"></div>
<div
class="bv-modal__panel w-full max-w-2xl h-auto max-h-[90vh] rounded-xl border border-border/50 bg-surface shadow-2xl overflow-hidden flex flex-col"
class="bv-modal__panel w-full max-w-2xl h-auto max-h-screen my-8 rounded-xl border border-border/50 bg-surface shadow-2xl overflow-hidden flex flex-col"
tabindex="-1"
>
<!-- Modal Header -->
+10 -2
View File
@@ -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,
);
}
+24 -16
View File
@@ -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;
}
-10
View File
@@ -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 });
}
+5 -5
View File
@@ -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);
},
);
@@ -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 () => {