fix: infinite loop in notification title counter

Signed-off-by: Heikki Hellgren <heikki.hellgren@op.fi>
This commit is contained in:
Heikki Hellgren
2024-04-21 21:21:49 +03:00
parent 4bfb02ed70
commit e1c7d6e4b7
6 changed files with 48 additions and 20 deletions
@@ -96,11 +96,14 @@ export const NotificationsSidebarItem = (props?: {
useEffect(() => {
if (!loading && !error && value) {
setUnreadCount(value.unread);
if (titleCounterEnabled) {
setNotificationCount(value.unread);
}
}
}, [loading, error, value, titleCounterEnabled, setNotificationCount]);
}, [loading, error, value]);
useEffect(() => {
if (titleCounterEnabled) {
setNotificationCount(unreadCount);
}
}, [titleCounterEnabled, unreadCount, setNotificationCount]);
// TODO: Figure out if the count can be added to hasNotifications
return (
@@ -13,12 +13,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { useCallback, useEffect, useState } from 'react';
import { useCallback, useEffect, useRef, useState } from 'react';
/** @public */
export function useTitleCounter() {
const [title, setTitle] = useState(document.title);
const [count, setCount] = useState(0);
const titleTimer = useRef<undefined | number>(undefined);
const getPrefix = (value: number) => {
return value === 0 ? '' : `(${value}) `;
@@ -28,28 +29,43 @@ export function useTitleCounter() {
return currentTitle.replace(/^\(\d+\)\s/, '');
};
useEffect(() => {
document.title = title;
}, [title]);
useEffect(() => {
const baseTitle = cleanTitle(title);
setTitle(`${getPrefix(count)}${baseTitle}`);
const shownTitle = `${getPrefix(count)}${baseTitle}`;
if (document.title !== shownTitle) {
window.clearTimeout(titleTimer.current);
document.title = shownTitle;
// Need to do this in timeout as the React Helmet overrides the title after this effect
titleTimer.current = window.setTimeout(() => {
document.title = shownTitle;
}, 50);
}
return () => {
window.clearTimeout(titleTimer.current);
document.title = cleanTitle(title);
};
}, [title, count]);
const titleElement = document.querySelector('title');
if (titleElement) {
new MutationObserver(() => {
setTitle(document.title);
}).observe(titleElement, {
subtree: true,
characterData: true,
childList: true,
});
}
useEffect(() => {
const titleElement = document.querySelector('title');
let observer: MutationObserver | undefined;
if (titleElement) {
observer = new MutationObserver(mutations => {
if (mutations?.[0]?.target?.textContent) {
setTitle(mutations[0].target.textContent);
}
});
observer.observe(titleElement, {
characterData: true,
childList: true,
});
}
return () => {
if (observer) {
observer.disconnect();
}
};
}, []);
const setNotificationCount = useCallback(
(newCount: number) => setCount(newCount),