Skip to content

Commit

Permalink
Refactor color functionality (#2905)
Browse files Browse the repository at this point in the history
* Fix hex color parsing

* Refactor color functionality

* Revert workaround
  • Loading branch information
RunDevelopment committed May 23, 2024
1 parent df5475a commit 3f8c402
Show file tree
Hide file tree
Showing 10 changed files with 266 additions and 225 deletions.
5 changes: 2 additions & 3 deletions src/renderer/colors.scss
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
/* stylelint-disable color-hex-length */
@use 'sass:color';
@use 'sass:map';

Expand Down Expand Up @@ -32,7 +31,7 @@
--type-color-number: #3182ce;
--type-color-string: #10b52c;
--type-color-bool: #319795;
--type-color-color: #ffffff;
--type-color-color: #fff;
--type-color-torch: #dd6b20;
--type-color-onnx: #63b3ed;
--type-color-ncnn: #ed64a6;
Expand Down Expand Up @@ -165,7 +164,7 @@
--controls-bg: var(--theme-300-a75);
--controls-bg-hover: var(--theme-400);

--type-color-color: #000000;
--type-color-color: #000;
}

// Default theme (copied from Chakra UI)
Expand Down
16 changes: 6 additions & 10 deletions src/renderer/components/inputs/ColorInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import {
VStack,
} from '@chakra-ui/react';
import { ReactNode, memo, useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { RgbColor } from 'react-colorful';
import { useContext } from 'use-context-selector';
import { toCssColor, toKind, toRgb } from '../../../common/color-json-util';
import {
Expand All @@ -25,6 +24,7 @@ import {
} from '../../../common/common-types';
import { log } from '../../../common/log';
import { InputContext } from '../../contexts/InputContext';
import { Color } from '../../helpers/color';
import { useColorModels } from '../../hooks/useColorModels';
import { TypeTags } from '../TypeTag';
import { ColorBoxButton } from './elements/ColorBoxButton';
Expand All @@ -41,21 +41,17 @@ const ALL_KINDS: ReadonlySet<ColorKind> = new Set<ColorKind>(['grayscale', 'rgb'
const KIND_SELECTOR_HEIGHT = '2rem';
const COMPARE_BUTTON_HEIGHT = '3rem';

const toRgbColor = (color: ColorJson): RgbColor => {
const toRgbColor = (color: ColorJson): Color => {
if (color.kind === 'grayscale') {
const l = Math.round(color.values[0] * 255);
return { r: l, g: l, b: l };
return new Color(l, l, l);
}
const [r, g, b] = color.values;
return {
r: Math.round(r * 255),
g: Math.round(g * 255),
b: Math.round(b * 255),
};
return new Color(Math.round(r * 255), Math.round(g * 255), Math.round(b * 255));
};

interface RgbOrRgbaPickerProps extends Omit<PickerFor<ColorJson>, 'onChange'> {
onChange: (color: RgbColor) => void;
onChange: (color: Color) => void;
alpha?: ReactNode;
}
const RgbOrRgbaPicker = memo(
Expand Down Expand Up @@ -168,7 +164,7 @@ const RgbaPicker = memo(
const originalAlpha = color.values[3];

const onChangeRgb = useCallback(
({ r, g, b }: RgbColor): void => {
({ r, g, b }: Color): void => {
if (originalAlpha !== undefined) {
onChange({ kind: 'rgba', values: [r / 255, g / 255, b / 255, originalAlpha] });
} else {
Expand Down
14 changes: 6 additions & 8 deletions src/renderer/components/inputs/elements/ColorPicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,15 @@ import { memo, useMemo, useRef } from 'react';
import {
HsvColorPicker as BuggedHsvColorPicker,
RgbColorPicker as BuggedRgbColorPicker,
HsvColor,
RgbColor,
} from 'react-colorful';
import { hsvColorId, rgbColorId } from '../../../helpers/colorUtil';
import { Color, HsvColor } from '../../../helpers/color';

interface PickerProps<T> {
color: T;
onChange: (value: T) => void;
}

export const RgbColorPicker = memo(({ color, onChange }: PickerProps<RgbColor>) => {
export const RgbColorPicker = memo(({ color, onChange }: PickerProps<Color>) => {
// The react-colorful color picker has a pretty major bug: rounding.
// It uses HSV internally to represent color, but it seems to round those values.
// This results in the picker sometimes immediately changing the given input color.
Expand All @@ -24,7 +22,7 @@ export const RgbColorPicker = memo(({ color, onChange }: PickerProps<RgbColor>)
const pickerLastSet = useRef(0);

// eslint-disable-next-line react-hooks/exhaustive-deps
const lastColorChange = useMemo(Date.now, [rgbColorId(color)]);
const lastColorChange = useMemo(Date.now, [color.id]);

return (
<Box
Expand All @@ -42,7 +40,7 @@ export const RgbColorPicker = memo(({ color, onChange }: PickerProps<RgbColor>)
(sinceLastSet < 200 || sinceLastChange > 200)
) {
pickerLastSet.current = Date.now();
onChange(value);
onChange(Color.from(value));
}
}}
/>
Expand All @@ -61,7 +59,7 @@ export const HsvColorPicker = memo(({ color, onChange }: PickerProps<HsvColor>)
const pickerLastSet = useRef(0);

// eslint-disable-next-line react-hooks/exhaustive-deps
const lastColorChange = useMemo(Date.now, [hsvColorId(color)]);
const lastColorChange = useMemo(Date.now, [color.id]);

return (
<Box
Expand All @@ -79,7 +77,7 @@ export const HsvColorPicker = memo(({ color, onChange }: PickerProps<HsvColor>)
(sinceLastSet < 200 || sinceLastChange > 200)
) {
pickerLastSet.current = Date.now();
onChange(value);
onChange(HsvColor.from(value));
}
}}
/>
Expand Down
49 changes: 20 additions & 29 deletions src/renderer/components/inputs/elements/ColorSlider.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { HStack, Text } from '@chakra-ui/react';
import { memo, useEffect, useState } from 'react';
import { HsvColor, RgbColor } from 'react-colorful';
import { hsvToRgb, rgbToHex } from '../../../helpers/colorUtil';
import { Color, HsvColor } from '../../../helpers/color';
import { LINEAR_SCALE } from '../../../helpers/sliderScale';
import { AdvancedNumberInput } from './AdvanceNumberInput';
import { SliderStyle, StyledSlider } from './StyledSlider';
Expand Down Expand Up @@ -78,13 +77,13 @@ export const ColorSlider = memo(
}
);

const getRgbStyle = (color0: RgbColor, color255: RgbColor): SliderStyle => {
return { type: 'gradient', gradient: [rgbToHex(color0), rgbToHex(color255)] };
const getRgbStyle = (color0: Color, color255: Color): SliderStyle => {
return { type: 'gradient', gradient: [color0.hex(), color255.hex()] };
};

interface RgbSlidersProps {
rgb: RgbColor;
onChange: (value: RgbColor) => void;
rgb: Color;
onChange: (value: Color) => void;
}
export const RgbSliders = memo(({ rgb, onChange }: RgbSlidersProps) => {
return (
Expand All @@ -94,32 +93,36 @@ export const RgbSliders = memo(({ rgb, onChange }: RgbSlidersProps) => {
label="R"
max={255}
min={0}
style={getRgbStyle({ ...rgb, r: 0 }, { ...rgb, r: 255 })}
style={getRgbStyle(rgb.with({ r: 0 }), rgb.with({ r: 255 }))}
value={rgb.r}
onChange={(r) => onChange({ ...rgb, r })}
onChange={(r) => onChange(rgb.with({ r }))}
/>
<ColorSlider
def={128}
label="G"
max={255}
min={0}
style={getRgbStyle({ ...rgb, g: 0 }, { ...rgb, g: 255 })}
style={getRgbStyle(rgb.with({ g: 0 }), rgb.with({ g: 255 }))}
value={rgb.g}
onChange={(g) => onChange({ ...rgb, g })}
onChange={(g) => onChange(rgb.with({ g }))}
/>
<ColorSlider
def={128}
label="B"
max={255}
min={0}
style={getRgbStyle({ ...rgb, b: 0 }, { ...rgb, b: 255 })}
style={getRgbStyle(rgb.with({ b: 0 }), rgb.with({ b: 255 }))}
value={rgb.b}
onChange={(b) => onChange({ ...rgb, b })}
onChange={(b) => onChange(rgb.with({ b }))}
/>
</>
);
});

const getSvStyle = (color0: HsvColor, color255: HsvColor): SliderStyle => {
return { type: 'gradient', gradient: [color0.rgb().hex(), color255.rgb().hex()] };
};

interface HsvSlidersProps {
hsv: HsvColor;
onChange: (value: HsvColor) => void;
Expand All @@ -145,37 +148,25 @@ export const HsvSliders = memo(({ hsv, onChange }: HsvSlidersProps) => {
],
}}
value={hsv.h}
onChange={(h) => onChange({ ...hsv, h })}
onChange={(h) => onChange(hsv.with({ h }))}
/>
<ColorSlider
def={0}
label="S"
max={100}
min={0}
style={{
type: 'gradient',
gradient: [
rgbToHex(hsvToRgb({ ...hsv, s: 0 })),
rgbToHex(hsvToRgb({ ...hsv, s: 100 })),
],
}}
style={getSvStyle(hsv.with({ s: 0 }), hsv.with({ s: 100 }))}
value={hsv.s}
onChange={(s) => onChange({ ...hsv, s })}
onChange={(s) => onChange(hsv.with({ s }))}
/>
<ColorSlider
def={50}
label="V"
max={100}
min={0}
style={{
type: 'gradient',
gradient: [
rgbToHex(hsvToRgb({ ...hsv, v: 0 })),
rgbToHex(hsvToRgb({ ...hsv, v: 100 })),
],
}}
style={getSvStyle(hsv.with({ v: 0 }), hsv.with({ v: 100 }))}
value={hsv.v}
onChange={(v) => onChange({ ...hsv, v })}
onChange={(v) => onChange(hsv.with({ v }))}
/>
</>
);
Expand Down
31 changes: 19 additions & 12 deletions src/renderer/components/inputs/elements/RgbHexInput.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,24 @@
import { HStack, Input, Spacer, Text } from '@chakra-ui/react';
import { memo, useEffect, useState } from 'react';
import { RgbColor } from 'react-colorful';
import { parseRgbHex, rgbToHex } from '../../../helpers/colorUtil';
import { Color } from '../../../helpers/color';

interface RgbHexInputProps {
rgb: RgbColor;
onChange: (value: RgbColor) => void;
rgb: Color;
onChange: (value: Color) => void;
}
export const RgbHexInput = memo(({ rgb, onChange }: RgbHexInputProps) => {
const currentHex = rgbToHex(rgb);
const currentHex = rgb.hex();

const [inputString, setInputString] = useState(currentHex);
const [inputString, setInputString] = useState<string>(currentHex);
useEffect(() => {
setInputString((old) => {
const parsed = parseRgbHex(old);
if (parsed && rgbToHex(parsed) === currentHex) {
return old;
try {
const parsed = Color.fromHex(old);
if (parsed.hex() === currentHex) {
return old;
}
} catch {
// ignore error
}
return currentHex;
});
Expand All @@ -24,9 +27,13 @@ export const RgbHexInput = memo(({ rgb, onChange }: RgbHexInputProps) => {
const changeInputString = (s: string) => {
setInputString(s);

const parsed = parseRgbHex(s);
if (parsed && rgbToHex(parsed) !== currentHex) {
onChange(parsed);
try {
const parsed = Color.fromHex(s);
if (parsed.hex() !== currentHex) {
onChange(parsed);
}
} catch {
// ignore error
}
};

Expand Down
3 changes: 1 addition & 2 deletions src/renderer/components/node/Node.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ import {
} from '../../contexts/ExecutionContext';
import { GlobalContext, GlobalVolatileContext } from '../../contexts/GlobalNodeState';
import { getCategoryAccentColor, getTypeAccentColors } from '../../helpers/accentColors';
import { shadeColor } from '../../helpers/colorTools';
import { getSingleFileWithExtension } from '../../helpers/dataTransfer';
import { NodeState, useNodeStateFromData } from '../../helpers/nodeState';
import { NO_DISABLED, UseDisabled, useDisabled } from '../../hooks/useDisabled';
Expand Down Expand Up @@ -105,7 +104,7 @@ export const NodeView = memo(
const finalBorderColor = useMemo(() => {
if (borderColor) return borderColor;
const regularBorderColor = 'var(--node-border-color)';
return selected ? shadeColor(accentColor, 0) : regularBorderColor;
return selected ? accentColor : regularBorderColor;
}, [selected, accentColor, borderColor]);

const isEnabled = disable.status === DisabledStatus.Enabled;
Expand Down

0 comments on commit 3f8c402

Please sign in to comment.