Teact: Store last rendered namespace for components (#6570)
This commit is contained in:
parent
d14da19bd8
commit
4819cf02b3
@ -24,7 +24,7 @@ import usePrevious from '../hooks/usePrevious';
|
|||||||
import { useSignalEffect } from '../hooks/useSignalEffect';
|
import { useSignalEffect } from '../hooks/useSignalEffect';
|
||||||
import { getIsInBackground } from '../hooks/window/useBackgroundMode';
|
import { getIsInBackground } from '../hooks/window/useBackgroundMode';
|
||||||
|
|
||||||
// import Test from './test/TestLocale';
|
// import Test from './test/TestSvg';
|
||||||
import Auth from './auth/Auth';
|
import Auth from './auth/Auth';
|
||||||
import Notifications from './common/Notifications';
|
import Notifications from './common/Notifications';
|
||||||
import UiLoader from './common/UiLoader';
|
import UiLoader from './common/UiLoader';
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
import { useState } from '../../lib/teact/teact';
|
import { useState } from '../../lib/teact/teact';
|
||||||
|
|
||||||
|
import useInterval from '../../hooks/schedulers/useInterval';
|
||||||
|
|
||||||
export function App() {
|
export function App() {
|
||||||
const [stateValue, setStateValue] = useState(false);
|
const [stateValue, setStateValue] = useState(false);
|
||||||
|
|
||||||
@ -43,9 +45,33 @@ export function App() {
|
|||||||
stroke-width="10"
|
stroke-width="10"
|
||||||
fill="none"
|
fill="none"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<NestedSvg />
|
||||||
|
|
||||||
|
<>
|
||||||
|
<rect x="0" y="0" width="50" height="50" fill="blue" />
|
||||||
|
<rect x="50" y="0" width="50" height="50" fill={stateValue ? 'red' : 'green'} />
|
||||||
|
</>
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function NestedSvg() {
|
||||||
|
const [stateValue, setStateValue] = useState(false);
|
||||||
|
|
||||||
|
useInterval(() => {
|
||||||
|
setStateValue((current) => !current);
|
||||||
|
}, 1000);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<circle
|
||||||
|
cx="60"
|
||||||
|
cy="60"
|
||||||
|
r="10"
|
||||||
|
fill={stateValue ? 'red' : 'blue'}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
export default App;
|
export default App;
|
||||||
|
|||||||
@ -84,6 +84,14 @@ function render($element: VirtualElement | undefined, parentEl: HTMLElement) {
|
|||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface RenderWithVirtualOptions {
|
||||||
|
skipComponentUpdate?: boolean;
|
||||||
|
nextSibling?: ChildNode;
|
||||||
|
forceMoveToEnd?: boolean;
|
||||||
|
fragment?: DocumentFragment;
|
||||||
|
namespace?: string;
|
||||||
|
}
|
||||||
|
|
||||||
function renderWithVirtual<T extends VirtualElement | undefined>(
|
function renderWithVirtual<T extends VirtualElement | undefined>(
|
||||||
parentEl: DOMElement,
|
parentEl: DOMElement,
|
||||||
$current: VirtualElement | undefined,
|
$current: VirtualElement | undefined,
|
||||||
@ -91,13 +99,7 @@ function renderWithVirtual<T extends VirtualElement | undefined>(
|
|||||||
$parent: VirtualElementParent | VirtualDomHead,
|
$parent: VirtualElementParent | VirtualDomHead,
|
||||||
currentContext: CurrentContext,
|
currentContext: CurrentContext,
|
||||||
index: number,
|
index: number,
|
||||||
options: {
|
options: RenderWithVirtualOptions = {},
|
||||||
skipComponentUpdate?: boolean;
|
|
||||||
nextSibling?: ChildNode;
|
|
||||||
forceMoveToEnd?: boolean;
|
|
||||||
fragment?: DocumentFragment;
|
|
||||||
namespace?: string;
|
|
||||||
} = {},
|
|
||||||
): T {
|
): T {
|
||||||
const { skipComponentUpdate, fragment } = options;
|
const { skipComponentUpdate, fragment } = options;
|
||||||
let { nextSibling, namespace } = options;
|
let { nextSibling, namespace } = options;
|
||||||
@ -114,6 +116,10 @@ function renderWithVirtual<T extends VirtualElement | undefined>(
|
|||||||
if ($new.props.xmlns) namespace = $new.props.xmlns;
|
if ($new.props.xmlns) namespace = $new.props.xmlns;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($new?.type === VirtualType.Component) {
|
||||||
|
$new.componentInstance.lastMountNamespace = namespace;
|
||||||
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
!skipComponentUpdate
|
!skipComponentUpdate
|
||||||
&& isCurrentComponent && isNewComponent
|
&& isCurrentComponent && isNewComponent
|
||||||
@ -215,6 +221,7 @@ function renderWithVirtual<T extends VirtualElement | undefined>(
|
|||||||
parentEl,
|
parentEl,
|
||||||
nextSibling,
|
nextSibling,
|
||||||
options.forceMoveToEnd,
|
options.forceMoveToEnd,
|
||||||
|
namespace,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
const $currentAsReal = $current as VirtualElementReal;
|
const $currentAsReal = $current as VirtualElementReal;
|
||||||
@ -288,7 +295,10 @@ function setupComponentUpdateListener(
|
|||||||
$parent,
|
$parent,
|
||||||
currentContext,
|
currentContext,
|
||||||
index,
|
index,
|
||||||
{ skipComponentUpdate: true },
|
{
|
||||||
|
skipComponentUpdate: true,
|
||||||
|
namespace: componentInstance.lastMountNamespace,
|
||||||
|
},
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -461,7 +471,7 @@ function renderChildren(
|
|||||||
namespace?: string,
|
namespace?: string,
|
||||||
) {
|
) {
|
||||||
if (('props' in $new) && $new.props.teactFastList) {
|
if (('props' in $new) && $new.props.teactFastList) {
|
||||||
renderFastListChildren($current, $new, currentContext, currentEl);
|
renderFastListChildren($current, $new, currentContext, currentEl, namespace);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -524,7 +534,11 @@ function renderChildren(
|
|||||||
// This function allows to prepend/append a bunch of new DOM nodes to the top/bottom of preserved ones.
|
// This function allows to prepend/append a bunch of new DOM nodes to the top/bottom of preserved ones.
|
||||||
// It also allows to selectively move particular preserved nodes within their DOM list.
|
// It also allows to selectively move particular preserved nodes within their DOM list.
|
||||||
function renderFastListChildren(
|
function renderFastListChildren(
|
||||||
$current: VirtualElementParent, $new: VirtualElementParent, currentContext: CurrentContext, currentEl: DOMElement,
|
$current: VirtualElementParent,
|
||||||
|
$new: VirtualElementParent,
|
||||||
|
currentContext: CurrentContext,
|
||||||
|
currentEl: DOMElement,
|
||||||
|
namespace?: string,
|
||||||
) {
|
) {
|
||||||
const currentChildren = $current.children;
|
const currentChildren = $current.children;
|
||||||
const newChildren = $new.children;
|
const newChildren = $new.children;
|
||||||
@ -586,7 +600,7 @@ function renderFastListChildren(
|
|||||||
|
|
||||||
// This prepends new children to the top
|
// This prepends new children to the top
|
||||||
if (fragmentSize) {
|
if (fragmentSize) {
|
||||||
renderFragment(fragmentIndex!, fragmentSize, currentEl, $new, currentContext);
|
renderFragment(fragmentIndex!, fragmentSize, currentEl, $new, currentContext, namespace);
|
||||||
fragmentSize = undefined;
|
fragmentSize = undefined;
|
||||||
fragmentIndex = undefined;
|
fragmentIndex = undefined;
|
||||||
}
|
}
|
||||||
@ -604,7 +618,14 @@ function renderFastListChildren(
|
|||||||
}
|
}
|
||||||
|
|
||||||
const nextSibling = currentEl.childNodes[isMovingDown ? i + 1 : i];
|
const nextSibling = currentEl.childNodes[isMovingDown ? i + 1 : i];
|
||||||
const options = shouldMoveNode ? (nextSibling ? { nextSibling } : { forceMoveToEnd: true }) : undefined;
|
const options: RenderWithVirtualOptions = { namespace };
|
||||||
|
if (shouldMoveNode) {
|
||||||
|
if (nextSibling) {
|
||||||
|
options.nextSibling = nextSibling;
|
||||||
|
} else {
|
||||||
|
options.forceMoveToEnd = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const $renderedChild = renderWithVirtual(
|
const $renderedChild = renderWithVirtual(
|
||||||
currentEl, currentChildInfo.$element, $newChild, $new, currentContext, i, options,
|
currentEl, currentChildInfo.$element, $newChild, $new, currentContext, i, options,
|
||||||
@ -616,7 +637,7 @@ function renderFastListChildren(
|
|||||||
|
|
||||||
// This appends new children to the bottom
|
// This appends new children to the bottom
|
||||||
if (fragmentSize) {
|
if (fragmentSize) {
|
||||||
renderFragment(fragmentIndex!, fragmentSize, currentEl, $new, currentContext);
|
renderFragment(fragmentIndex!, fragmentSize, currentEl, $new, currentContext, namespace);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -626,13 +647,14 @@ function renderFragment(
|
|||||||
parentEl: DOMElement,
|
parentEl: DOMElement,
|
||||||
$parent: VirtualElementParent,
|
$parent: VirtualElementParent,
|
||||||
currentContext: CurrentContext,
|
currentContext: CurrentContext,
|
||||||
|
namespace?: string,
|
||||||
) {
|
) {
|
||||||
const nextSibling = parentEl.childNodes[fragmentIndex];
|
const nextSibling = parentEl.childNodes[fragmentIndex];
|
||||||
|
|
||||||
if (fragmentSize === 1) {
|
if (fragmentSize === 1) {
|
||||||
const $child = $parent.children[fragmentIndex];
|
const $child = $parent.children[fragmentIndex];
|
||||||
const $renderedChild = renderWithVirtual(
|
const $renderedChild = renderWithVirtual(
|
||||||
parentEl, undefined, $child, $parent, currentContext, fragmentIndex, { nextSibling },
|
parentEl, undefined, $child, $parent, currentContext, fragmentIndex, { nextSibling, namespace },
|
||||||
);
|
);
|
||||||
if ($renderedChild !== $child) {
|
if ($renderedChild !== $child) {
|
||||||
$parent.children[fragmentIndex] = $renderedChild;
|
$parent.children[fragmentIndex] = $renderedChild;
|
||||||
@ -645,7 +667,9 @@ function renderFragment(
|
|||||||
|
|
||||||
for (let i = fragmentIndex; i < fragmentIndex + fragmentSize; i++) {
|
for (let i = fragmentIndex; i < fragmentIndex + fragmentSize; i++) {
|
||||||
const $child = $parent.children[i];
|
const $child = $parent.children[i];
|
||||||
const $renderedChild = renderWithVirtual(parentEl, undefined, $child, $parent, currentContext, i, { fragment });
|
const $renderedChild = renderWithVirtual(
|
||||||
|
parentEl, undefined, $child, $parent, currentContext, i, { fragment, namespace },
|
||||||
|
);
|
||||||
if ($renderedChild !== $child) {
|
if ($renderedChild !== $child) {
|
||||||
$parent.children[i] = $renderedChild;
|
$parent.children[i] = $renderedChild;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -80,6 +80,7 @@ interface ComponentInstance {
|
|||||||
name: string;
|
name: string;
|
||||||
props: Props;
|
props: Props;
|
||||||
renderedValue?: any;
|
renderedValue?: any;
|
||||||
|
lastMountNamespace?: string;
|
||||||
mountState: MountState;
|
mountState: MountState;
|
||||||
context?: Record<string, Signal<unknown>>;
|
context?: Record<string, Signal<unknown>>;
|
||||||
hooks?: {
|
hooks?: {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user