Svg: Fix Teact errors for filters (#5482)

This commit is contained in:
zubiden 2025-01-21 18:21:43 +01:00 committed by Alexander Zinchuk
parent f379461cbb
commit 18c8f4c58f
5 changed files with 49 additions and 51 deletions

View File

@ -86,7 +86,6 @@ import GiveawayModal from './premium/GiveawayModal.async';
import PremiumMainModal from './premium/PremiumMainModal.async';
import StarsGiftingPickerModal from './premium/StarsGiftingPickerModal.async';
import SafeLinkModal from './SafeLinkModal.async';
import SvgController from './SvgController';
import ConfettiContainer from './visualEffects/ConfettiContainer';
import SnapEffectContainer from './visualEffects/SnapEffectContainer';
import WaveContainer from './visualEffects/WaveContainer';
@ -588,7 +587,6 @@ const Main = ({
<DeleteFolderDialog folder={deleteFolderDialog} />
<ReactionPicker isOpen={isReactionPickerOpen} />
<DeleteMessageModal isOpen={isDeleteMessageModalOpen} />
<SvgController />
</div>
);
};

View File

@ -1,45 +0,0 @@
import React, { memo, useEffect } from '../../lib/teact/teact';
import { createCallbackManager } from '../../util/callbacks';
import generateUniqueId from '../../util/generateUniqueId';
import useForceUpdate from '../../hooks/useForceUpdate';
import Portal from '../ui/Portal';
const DEFINITION_MAP = new Map<string, React.ReactElement>();
const CALLBACK_MANAGER = createCallbackManager();
const SvgController = () => {
const forceUpdate = useForceUpdate();
useEffect(() => {
return CALLBACK_MANAGER.addCallback(forceUpdate);
}, []);
return (
<Portal>
<svg width="0" height="0" viewBox="0 0 1 1" className="svg-definitions">
<defs>
{Array.from(DEFINITION_MAP.values())}
</defs>
</svg>
</Portal>
);
};
export default memo(SvgController);
export function addSvgDefinition(element: React.ReactElement, id?: string) {
id ??= generateUniqueId();
element.props.id = id;
DEFINITION_MAP.set(element.props.id, element);
CALLBACK_MANAGER.runCallbacks();
return id;
}
export function removeSvgDefinition(id: string) {
DEFINITION_MAP.delete(id);
CALLBACK_MANAGER.runCallbacks();
}

View File

@ -9,12 +9,11 @@ import { SVG_NAMESPACE } from '../../../config';
import { selectTabState } from '../../../global/selectors';
import buildClassName from '../../../util/buildClassName';
import buildStyle from '../../../util/buildStyle';
import { addSvgDefinition, removeSvgDefinition } from '../../../util/svgController';
import windowSize from '../../../util/windowSize';
import useLastCallback from '../../../hooks/useLastCallback';
import { addSvgDefinition, removeSvgDefinition } from '../SvgController';
import styles from './WaveContainer.module.scss';
import waveRipple from '../../../assets/wave_ripple.svg';

View File

@ -1,10 +1,9 @@
import React, { useEffect } from '../../lib/teact/teact';
import { SVG_NAMESPACE } from '../../config';
import { addSvgDefinition, removeSvgDefinition } from '../../util/svgController';
import { hexToRgb } from '../../util/switchTheme';
import { addSvgDefinition, removeSvgDefinition } from '../../components/main/SvgController';
const SVG_MAP = new Map<string, SvgColorFilter>();
class SvgColorFilter {

47
src/util/svgController.ts Normal file
View File

@ -0,0 +1,47 @@
import { SVG_NAMESPACE } from '../config';
import { requestMutation } from '../lib/fasterdom/fasterdom';
import jsxToHtml from './element/jsxToHtml';
import generateUniqueId from './generateUniqueId';
const DEFINITION_MAP = new Map<string, Element>();
let defs: SVGElement | undefined;
function init() {
if (defs) return;
const container = document.createElementNS(SVG_NAMESPACE, 'svg');
container.setAttribute('width', '0');
container.setAttribute('height', '0');
container.setAttribute('viewBox', '0 0 1 1');
container.classList.add('svg-definitions');
document.body.appendChild(container);
defs = document.createElementNS(SVG_NAMESPACE, 'defs');
container.appendChild(defs);
}
function appendElement(element: Element) {
requestMutation(() => {
if (!defs) init();
defs!.appendChild(element);
});
}
export function addSvgDefinition(element: React.JSX.Element, id?: string) {
id ??= generateUniqueId();
element.props.id = id;
const htmlElement = jsxToHtml(element)[0];
DEFINITION_MAP.set(element.props.id, htmlElement);
appendElement(htmlElement);
return id;
}
export function removeSvgDefinition(id: string) {
const element = DEFINITION_MAP.get(id);
if (element) {
element.remove();
DEFINITION_MAP.delete(id);
}
}