From 18c8f4c58fbf304e691eb3a7167756057fd1566d Mon Sep 17 00:00:00 2001
From: zubiden <19638254+zubiden@users.noreply.github.com>
Date: Tue, 21 Jan 2025 18:21:43 +0100
Subject: [PATCH] Svg: Fix Teact errors for filters (#5482)
---
src/components/main/Main.tsx | 2 -
src/components/main/SvgController.tsx | 45 ------------------
.../main/visualEffects/WaveContainer.tsx | 3 +-
src/hooks/stickers/useColorFilter.tsx | 3 +-
src/util/svgController.ts | 47 +++++++++++++++++++
5 files changed, 49 insertions(+), 51 deletions(-)
delete mode 100644 src/components/main/SvgController.tsx
create mode 100644 src/util/svgController.ts
diff --git a/src/components/main/Main.tsx b/src/components/main/Main.tsx
index 4ac2680fa..b212045e6 100644
--- a/src/components/main/Main.tsx
+++ b/src/components/main/Main.tsx
@@ -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 = ({
-
);
};
diff --git a/src/components/main/SvgController.tsx b/src/components/main/SvgController.tsx
deleted file mode 100644
index 725c77aa6..000000000
--- a/src/components/main/SvgController.tsx
+++ /dev/null
@@ -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();
-const CALLBACK_MANAGER = createCallbackManager();
-
-const SvgController = () => {
- const forceUpdate = useForceUpdate();
-
- useEffect(() => {
- return CALLBACK_MANAGER.addCallback(forceUpdate);
- }, []);
-
- return (
-
-
-
- );
-};
-
-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();
-}
diff --git a/src/components/main/visualEffects/WaveContainer.tsx b/src/components/main/visualEffects/WaveContainer.tsx
index 15623c1ac..3c62ac6ee 100644
--- a/src/components/main/visualEffects/WaveContainer.tsx
+++ b/src/components/main/visualEffects/WaveContainer.tsx
@@ -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';
diff --git a/src/hooks/stickers/useColorFilter.tsx b/src/hooks/stickers/useColorFilter.tsx
index e4ec3075e..f789263e6 100644
--- a/src/hooks/stickers/useColorFilter.tsx
+++ b/src/hooks/stickers/useColorFilter.tsx
@@ -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();
class SvgColorFilter {
diff --git a/src/util/svgController.ts b/src/util/svgController.ts
new file mode 100644
index 000000000..8068232c4
--- /dev/null
+++ b/src/util/svgController.ts
@@ -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();
+
+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);
+ }
+}