mirror of
https://github.com/owncast/owncast.git
synced 2024-10-10 19:16:02 +00:00
fix: Prevent color selector from closing on choosing a color (#2783)
* improv: wrap ColorPicker in memo to prevent unnecessary rerenders * improv appearance: wrap updateColor in useCallback to prevent unnecessary rerenders due to changing reference to the func * improv: define ColorCollection Component as top level, and modify it to prevent unnecessary rerenders
This commit is contained in:
parent
108eda0a6a
commit
e80db09ab1
@ -1,4 +1,4 @@
|
|||||||
import React, { FC, useContext, useEffect, useState } from 'react';
|
import React, { FC, useContext, useCallback, useEffect, useState } from 'react';
|
||||||
|
|
||||||
import { Button, Col, Collapse, Row, Slider, Space } from 'antd';
|
import { Button, Col, Collapse, Row, Slider, Space } from 'antd';
|
||||||
import Paragraph from 'antd/lib/typography/Paragraph';
|
import Paragraph from 'antd/lib/typography/Paragraph';
|
||||||
@ -24,6 +24,11 @@ interface AppearanceVariable {
|
|||||||
description: string;
|
description: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ColorCollectionProps = {
|
||||||
|
variables: { name; description; value }[];
|
||||||
|
updateColor: (variable: string, color: string, description: string) => void;
|
||||||
|
};
|
||||||
|
|
||||||
const chatColorVariables = [
|
const chatColorVariables = [
|
||||||
{ name: 'theme-color-users-0', description: '' },
|
{ name: 'theme-color-users-0', description: '' },
|
||||||
{ name: 'theme-color-users-1', description: '' },
|
{ name: 'theme-color-users-1', description: '' },
|
||||||
@ -70,18 +75,18 @@ const allAvailableValues = [...componentColorVariables, ...chatColorVariables, .
|
|||||||
);
|
);
|
||||||
|
|
||||||
// eslint-disable-next-line react/function-component-definition
|
// eslint-disable-next-line react/function-component-definition
|
||||||
function ColorPicker({
|
const ColorPicker = React.memo(
|
||||||
|
({
|
||||||
value,
|
value,
|
||||||
name,
|
name,
|
||||||
description,
|
description,
|
||||||
onChange,
|
onChange,
|
||||||
}: {
|
}: {
|
||||||
value: string;
|
value: string;
|
||||||
name: string;
|
name: string;
|
||||||
description: string;
|
description: string;
|
||||||
onChange: (name: string, value: string, description: string) => void;
|
onChange: (name: string, value: string, description: string) => void;
|
||||||
}) {
|
}) => (
|
||||||
return (
|
|
||||||
<Col span={3} key={name}>
|
<Col span={3} key={name}>
|
||||||
<input
|
<input
|
||||||
type="color"
|
type="color"
|
||||||
@ -94,8 +99,26 @@ function ColorPicker({
|
|||||||
/>
|
/>
|
||||||
<div style={{ padding: '2px' }}>{description}</div>
|
<div style={{ padding: '2px' }}>{description}</div>
|
||||||
</Col>
|
</Col>
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
const ColorCollection: FC<ColorCollectionProps> = ({ variables, updateColor }) => {
|
||||||
|
const cc = variables.map(colorVar => {
|
||||||
|
const { name, description, value } = colorVar;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ColorPicker
|
||||||
|
key={name}
|
||||||
|
value={value}
|
||||||
|
name={name}
|
||||||
|
description={description}
|
||||||
|
onChange={updateColor}
|
||||||
|
/>
|
||||||
);
|
);
|
||||||
}
|
});
|
||||||
|
// eslint-disable-next-line react/jsx-no-useless-fragment
|
||||||
|
return <>{cc}</>;
|
||||||
|
};
|
||||||
|
|
||||||
// eslint-disable-next-line react/function-component-definition
|
// eslint-disable-next-line react/function-component-definition
|
||||||
export default function Appearance() {
|
export default function Appearance() {
|
||||||
@ -144,12 +167,12 @@ export default function Appearance() {
|
|||||||
setCustomValues(c);
|
setCustomValues(c);
|
||||||
}, [appearanceVariables]);
|
}, [appearanceVariables]);
|
||||||
|
|
||||||
const updateColor = (variable: string, color: string, description: string) => {
|
const updateColor = useCallback((variable: string, color: string, description: string) => {
|
||||||
setCustomValues({
|
setCustomValues(oldCustomValues => ({
|
||||||
...customValues,
|
...oldCustomValues,
|
||||||
[variable]: { value: color, description },
|
[variable]: { value: color, description },
|
||||||
});
|
}));
|
||||||
};
|
}, []);
|
||||||
|
|
||||||
const reset = async () => {
|
const reset = async () => {
|
||||||
await postConfigUpdateToAPI({
|
await postConfigUpdateToAPI({
|
||||||
@ -193,34 +216,18 @@ export default function Appearance() {
|
|||||||
updateColor(variableName, `${value.toString()}px`, '');
|
updateColor(variableName, `${value.toString()}px`, '');
|
||||||
};
|
};
|
||||||
|
|
||||||
type ColorCollectionProps = {
|
|
||||||
variables: { name; description }[];
|
|
||||||
};
|
|
||||||
// eslint-disable-next-line react/no-unstable-nested-components
|
|
||||||
const ColorCollection: FC<ColorCollectionProps> = ({ variables }) => {
|
|
||||||
const cc = variables.map(colorVar => {
|
|
||||||
const source = customValues?.[colorVar.name] ? customValues : defaultValues;
|
|
||||||
const { name, description } = colorVar;
|
|
||||||
const { value } = source[name];
|
|
||||||
|
|
||||||
return (
|
|
||||||
<ColorPicker
|
|
||||||
key={name}
|
|
||||||
value={value}
|
|
||||||
name={name}
|
|
||||||
description={description}
|
|
||||||
onChange={updateColor}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
// eslint-disable-next-line react/jsx-no-useless-fragment
|
|
||||||
return <>{cc}</>;
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!defaultValues) {
|
if (!defaultValues) {
|
||||||
return <div>Loading...</div>;
|
return <div>Loading...</div>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const transformToColorMap = variables =>
|
||||||
|
variables.map(colorVar => {
|
||||||
|
const source = customValues?.[colorVar.name] ? customValues : defaultValues;
|
||||||
|
const { name, description } = colorVar;
|
||||||
|
const { value } = source[name];
|
||||||
|
return { name, description, value };
|
||||||
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Space direction="vertical">
|
<Space direction="vertical">
|
||||||
<Title>Customize Appearance</Title>
|
<Title>Customize Appearance</Title>
|
||||||
@ -232,15 +239,20 @@ export default function Appearance() {
|
|||||||
Certain sections of the interface can be customized by selecting new colors for them.
|
Certain sections of the interface can be customized by selecting new colors for them.
|
||||||
</p>
|
</p>
|
||||||
<Row gutter={[16, 16]}>
|
<Row gutter={[16, 16]}>
|
||||||
<ColorCollection variables={componentColorVariables} />
|
<ColorCollection
|
||||||
|
variables={transformToColorMap(componentColorVariables)}
|
||||||
|
updateColor={updateColor}
|
||||||
|
/>
|
||||||
</Row>
|
</Row>
|
||||||
</Panel>
|
</Panel>
|
||||||
<Panel header={<Title level={3}>Chat User Colors</Title>} key="2">
|
<Panel header={<Title level={3}>Chat User Colors</Title>} key="2">
|
||||||
<Row gutter={[16, 16]}>
|
<Row gutter={[16, 16]}>
|
||||||
<ColorCollection variables={chatColorVariables} />
|
<ColorCollection
|
||||||
|
variables={transformToColorMap(chatColorVariables)}
|
||||||
|
updateColor={updateColor}
|
||||||
|
/>
|
||||||
</Row>
|
</Row>
|
||||||
</Panel>
|
</Panel>
|
||||||
|
|
||||||
<Panel header={<Title level={3}>Other Settings</Title>} key="4">
|
<Panel header={<Title level={3}>Other Settings</Title>} key="4">
|
||||||
How rounded should corners be?
|
How rounded should corners be?
|
||||||
<Row gutter={[16, 16]}>
|
<Row gutter={[16, 16]}>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user