mirror of
https://github.com/HabitRPG/habitica.git
synced 2026-03-13 08:41:14 +08:00
* fix: prevent duplicate streak achievement notifications (#13325) * fix(lint): whitespace also remove unnecessary file and comments --------- Co-authored-by: Kalista Payne <kalista@habitica.com>
This commit is contained in:
@@ -50,5 +50,59 @@ describe('UserNotification Model', () => {
|
||||
expect(safeNotifications[0].type).to.equal('NEW_CHAT_MESSAGE');
|
||||
expect(safeNotifications[0].id).to.equal('123');
|
||||
});
|
||||
|
||||
it('removes duplicate STREAK_ACHIEVEMENT notifications', () => {
|
||||
// Fixes issue #13325 - Users receiving duplicate streak achievement notifications
|
||||
const notifications = [
|
||||
new UserNotification({
|
||||
type: 'STREAK_ACHIEVEMENT',
|
||||
id: 123,
|
||||
data: {},
|
||||
}),
|
||||
new UserNotification({
|
||||
type: 'STREAK_ACHIEVEMENT',
|
||||
id: 456,
|
||||
data: {},
|
||||
}),
|
||||
new UserNotification({
|
||||
type: 'CRON',
|
||||
id: 789,
|
||||
data: {},
|
||||
}), // different type, should be kept
|
||||
];
|
||||
|
||||
const safeNotifications = UserNotification.cleanupCorruptData(notifications);
|
||||
expect(safeNotifications.length).to.equal(2);
|
||||
expect(safeNotifications[0].type).to.equal('STREAK_ACHIEVEMENT');
|
||||
expect(safeNotifications[0].id).to.equal('123');
|
||||
expect(safeNotifications[1].type).to.equal('CRON');
|
||||
expect(safeNotifications[1].id).to.equal('789');
|
||||
});
|
||||
|
||||
it('handles multiple STREAK_ACHIEVEMENT duplicates correctly', () => {
|
||||
// Test case: 3 duplicate STREAK_ACHIEVEMENT notifications
|
||||
const notifications = [
|
||||
new UserNotification({
|
||||
type: 'STREAK_ACHIEVEMENT',
|
||||
id: 111,
|
||||
data: {},
|
||||
}),
|
||||
new UserNotification({
|
||||
type: 'STREAK_ACHIEVEMENT',
|
||||
id: 222,
|
||||
data: {},
|
||||
}),
|
||||
new UserNotification({
|
||||
type: 'STREAK_ACHIEVEMENT',
|
||||
id: 333,
|
||||
data: {},
|
||||
}),
|
||||
];
|
||||
|
||||
const safeNotifications = UserNotification.cleanupCorruptData(notifications);
|
||||
expect(safeNotifications.length).to.equal(1);
|
||||
expect(safeNotifications[0].type).to.equal('STREAK_ACHIEVEMENT');
|
||||
expect(safeNotifications[0].id).to.equal('111'); // Keep first one
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -330,6 +330,7 @@ export default {
|
||||
handledNotifications,
|
||||
isInitialLoadComplete: false,
|
||||
pendingRebirthNotification: null,
|
||||
lastShownStreakCount: null, // Track last shown streak to prevent duplicates
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
@@ -737,6 +738,13 @@ export default {
|
||||
}
|
||||
break;
|
||||
case 'STREAK_ACHIEVEMENT':
|
||||
// Client-side deduplication: prevent showing duplicate streak achievements
|
||||
if (this.lastShownStreakCount === this.user.achievements.streak) {
|
||||
// Same streak already shown, skip this notification
|
||||
break;
|
||||
}
|
||||
this.lastShownStreakCount = this.user.achievements.streak;
|
||||
|
||||
this.text(`${this.$t('streaks')}: ${this.user.achievements.streak}`, () => {
|
||||
this.$root.$emit('bv::show::modal', 'streak');
|
||||
}, this.user.preferences.suppressModals.streak);
|
||||
|
||||
@@ -143,6 +143,16 @@ schema.statics.cleanupCorruptData = function cleanupCorruptNotificationsData (no
|
||||
return false;
|
||||
});
|
||||
|
||||
// Remove duplicate STREAK_ACHIEVEMENT notifications
|
||||
// Deduplicates by keeping only the first occurrence of STREAK_ACHIEVEMENT notification
|
||||
filteredNotifications = _.uniqWith(filteredNotifications, (val, otherVal) => {
|
||||
if (val.type === 'STREAK_ACHIEVEMENT' && val.type === otherVal.type) {
|
||||
// If both are streak achievements, they are duplicates
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
return filteredNotifications;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user