nicolium: replace react-helmet-async dependency with react 19 features

Signed-off-by: nicole mikołajczyk <git@mkljczk.pl>
This commit is contained in:
nicole mikołajczyk
2026-03-13 13:14:52 +01:00
parent c00a42e0b8
commit 389cbff281
6 changed files with 34 additions and 72 deletions

View File

@@ -111,7 +111,6 @@
"react-color": "^2.19.3",
"react-datepicker": "^9.1.0",
"react-dom": "^19.2.4",
"react-helmet-async": "^3.0.0",
"react-hot-toast": "^2.6.0",
"react-inlinesvg": "^4.2.0",
"react-intl": "^8.1.3",

View File

@@ -1,5 +1,4 @@
import React from 'react';
import { Helmet as ReactHelmet } from 'react-helmet-async';
import React, { useEffect } from 'react';
import { useStatContext } from '@/contexts/stat-context';
import { useInstance } from '@/hooks/use-instance';
@@ -12,10 +11,11 @@ import FaviconService from '@/utils/favicon-service';
FaviconService.initFaviconService();
interface IHelmet {
children: React.ReactNode;
title?: string;
children?: React.ReactNode;
}
const Helmet: React.FC<IHelmet> = ({ children }) => {
const Helmet: React.FC<IHelmet> = ({ title, children }) => {
const instance = useInstance();
const { unreadChatsCount } = useStatContext();
const { data: awaitingApprovalCount = 0 } = usePendingUsersCount();
@@ -33,26 +33,23 @@ const Helmet: React.FC<IHelmet> = ({ children }) => {
const addCounter = (string: string) =>
hasUnreadNotifications ? `(${unreadCount}) ${string}` : string;
const updateFaviconBadge = () => {
useEffect(() => {
if (hasUnreadNotifications) {
FaviconService.drawFaviconBadge();
} else {
FaviconService.clearFaviconBadge();
}
};
React.useEffect(() => {
updateFaviconBadge();
}, [unreadCount, demetricator]);
const formattedTitle = title
? addCounter(`${title} | ${instance.title}`)
: addCounter(instance.title);
return (
<ReactHelmet
titleTemplate={addCounter(`%s | ${instance.title}`)}
defaultTitle={addCounter(instance.title)}
defer={false}
>
<>
<title>{formattedTitle}</title>
{children}
</ReactHelmet>
</>
);
};

View File

@@ -106,12 +106,9 @@ const Column: React.FC<IColumn> = (props): React.JSX.Element => {
variant={transparent ? undefined : 'rounded'}
className={clsx('⁂-column', className)}
>
<Helmet>
<title>{label}</title>
<Helmet title={label}>
{frontendConfig.appleAppId && (
<meta
data-react-helmet='true'
name='apple-itunes-app'
content={`app-id=${frontendConfig.appleAppId}, app-argument=${location.href}`}
/>

View File

@@ -13,7 +13,7 @@ import { useSettings } from '@/stores/settings';
const Helmet = React.lazy(() => import('@/components/helmet'));
/** Injects metadata into site head with Helmet. */
/** Injects metadata into site head. */
const NicoliumHead = () => {
const locale = useLocale();
const direction = useLocaleDirection(locale);
@@ -70,6 +70,21 @@ const NicoliumHead = () => {
};
}, []);
useEffect(() => {
document.documentElement.lang = locale;
document.documentElement.className = clsx(`text-${themeSettings?.interfaceSize ?? 'md'}`, {
dark: theme === 'dark',
'black dark': theme === 'black',
'window-controls-overlay': wcoVisible,
'window-controls-overlay--right': wcoRight,
});
}, [locale, themeSettings?.interfaceSize, theme, wcoVisible, wcoRight]);
useEffect(() => {
document.body.className = bodyClass;
document.body.dir = direction;
}, [bodyClass, direction]);
const color = useMemo(() => {
if (wcoVisible) {
return window.getComputedStyle(document.body, null).getPropertyValue('background-color');
@@ -79,18 +94,7 @@ const NicoliumHead = () => {
return (
<>
<Helmet>
<html
lang={locale}
className={clsx(`text-${themeSettings?.interfaceSize ?? 'md'}`, {
dark: theme === 'dark',
'black dark': theme === 'black',
'window-controls-overlay': wcoVisible,
'window-controls-overlay--right': wcoRight,
})}
/>
<body className={bodyClass} dir={direction} />
</Helmet>
<Helmet />
<meta name='theme-color' content={color} />
<InlineStyle>{`:root { ${themeCss} }`}</InlineStyle>
{['dark', 'black'].includes(theme) && (

View File

@@ -1,6 +1,5 @@
import { QueryClientProvider } from '@tanstack/react-query';
import React from 'react';
import { HelmetProvider } from 'react-helmet-async';
import { Provider } from 'react-redux';
import { preload } from '@/actions/preload';
@@ -23,12 +22,10 @@ const Nicolium: React.FC = () => (
<QueryClientProvider client={queryClient}>
<DefaultCurrentAccountProvider>
<StatProvider>
<HelmetProvider>
<NicoliumHead />
<NicoliumLoad>
<NicoliumMount />
</NicoliumLoad>
</HelmetProvider>
<NicoliumHead />
<NicoliumLoad>
<NicoliumMount />
</NicoliumLoad>
</StatProvider>
</DefaultCurrentAccountProvider>
</QueryClientProvider>

32
pnpm-lock.yaml generated
View File

@@ -250,9 +250,6 @@ importers:
react-dom:
specifier: ^19.2.4
version: 19.2.4(react@19.2.4)
react-helmet-async:
specifier: ^3.0.0
version: 3.0.0(react@19.2.4)
react-hot-toast:
specifier: ^2.6.0
version: 2.6.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
@@ -5056,9 +5053,6 @@ packages:
intl-pluralrules@2.0.1:
resolution: {integrity: sha512-astxTLzIdXPeN0K9Rumi6LfMpm3rvNO0iJE+h/k8Kr/is+wPbRe4ikyDjlLr6VTh/mEfNv8RjN+gu3KwDiuhqg==}
invariant@2.2.4:
resolution: {integrity: sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==}
iron-webcrypto@1.2.1:
resolution: {integrity: sha512-feOM6FaSr6rEABp/eDfVseKyTMDt+KGpeB35SkVn9Tyn0CqvVsY3EwI0v5i8nMHyJnzCIQf7nsy3p41TPkJZhg==}
@@ -6468,19 +6462,11 @@ packages:
peerDependencies:
react: ^16.3.0
react-fast-compare@3.2.2:
resolution: {integrity: sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==}
react-from-dom@0.7.5:
resolution: {integrity: sha512-CO92PmMKo/23uYPm6OFvh5CtZbMgHs/Xn+o095Lz/TZj9t8DSDhGdSOMLxBxwWI4sr0MF17KUn9yJWc5Q00R/w==}
peerDependencies:
react: 16.8 - 19
react-helmet-async@3.0.0:
resolution: {integrity: sha512-nA3IEZfXiclgrz4KLxAhqJqIfFDuvzQwlKwpdmzZIuC1KNSghDEIXmyU0TKtbM+NafnkICcwx8CECFrZ/sL/1w==}
peerDependencies:
react: ^16.6.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
react-hot-toast@2.6.0:
resolution: {integrity: sha512-bH+2EBMZ4sdyou/DPrfgIouFpcRLCJ+HoCA32UoAYHn6T3Ur5yfcDCeSr5mwldl6pFOsiocmrXMuoCJ1vV8bWg==}
engines: {node: '>=10'}
@@ -7008,9 +6994,6 @@ packages:
shallow-equal@1.2.1:
resolution: {integrity: sha512-S4vJDjHHMBaiZuT9NPb616CSmLf618jawtv3sufLl6ivK8WocjAo58cXwbRV1cgqxH0Qbv+iUt6m05eqEa2IRA==}
shallowequal@1.1.0:
resolution: {integrity: sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==}
sharp@0.34.5:
resolution: {integrity: sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
@@ -12836,10 +12819,6 @@ snapshots:
intl-pluralrules@2.0.1: {}
invariant@2.2.4:
dependencies:
loose-envify: 1.4.0
iron-webcrypto@1.2.1: {}
is-absolute-url@4.0.1: {}
@@ -14496,19 +14475,10 @@ snapshots:
react: 19.2.4
warning: 4.0.3
react-fast-compare@3.2.2: {}
react-from-dom@0.7.5(react@19.2.4):
dependencies:
react: 19.2.4
react-helmet-async@3.0.0(react@19.2.4):
dependencies:
invariant: 2.2.4
react: 19.2.4
react-fast-compare: 3.2.2
shallowequal: 1.1.0
react-hot-toast@2.6.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4):
dependencies:
csstype: 3.2.3
@@ -15120,8 +15090,6 @@ snapshots:
shallow-equal@1.2.1: {}
shallowequal@1.1.0: {}
sharp@0.34.5:
dependencies:
'@img/colour': 1.1.0