From 3f52a908a62b98601b2cbdc646bc3a67e75acf9c Mon Sep 17 00:00:00 2001 From: Sol Toder Date: Sat, 22 Feb 2025 09:14:57 -0500 Subject: [PATCH] Fix converting colors with alpha to hex RGB (#705) Convert negative integers to unsigned integers. Truncate the alpha from colors before passing them to the HTML color picker, since it doesn't allow alpha values (and they'd be in the wrong place if it did). --- src/app/Utils.ts | 13 +++++++++++++ src/app/components/ItemTooltip.tsx | 4 ++-- src/app/components/ItemTooltip1204.tsx | 4 ++-- src/app/components/generator/McdocRenderer.tsx | 6 +++--- 4 files changed, 20 insertions(+), 7 deletions(-) diff --git a/src/app/Utils.ts b/src/app/Utils.ts index 41d70eca..8e1189f4 100644 --- a/src/app/Utils.ts +++ b/src/app/Utils.ts @@ -51,6 +51,19 @@ export function generateColor() { return Math.floor(Math.random() * 16777215) } +function intToUnsigned(n: number) { + n |= 0; // Force to signed 32-bit integer + return n < 0 ? n + 0x100000000 : n; +} + +export function intToHexRgb(c: number | undefined) { + return c ? '#' + (c & 0xFFFFFF).toString(16).padStart(6, '0') : '#000000'; +} + +export function intToDisplayHexRgb(c: number | undefined) { + return c ? '#' + intToUnsigned(c).toString(16).toUpperCase().padStart(6, '0') : '#000000'; +} + export function htmlEncode(str: string) { return str.replace(/&/g, '&').replace(//g, '>') .replace(/"/g, '"').replace(/'/g, ''').replace(/\//g, '/') diff --git a/src/app/components/ItemTooltip.tsx b/src/app/components/ItemTooltip.tsx index 433ee63d..2342ca2f 100644 --- a/src/app/components/ItemTooltip.tsx +++ b/src/app/components/ItemTooltip.tsx @@ -2,7 +2,7 @@ import type { MobEffectInstance, NbtTag } from 'deepslate' import { ItemStack, NbtCompound, NbtList, PotionContents } from 'deepslate' import { Identifier } from 'deepslate/core' import type { ResolvedItem } from '../services/ResolvedItem.js' -import { makeDescriptionId, mergeTextComponentStyles } from '../Utils.js' +import { intToDisplayHexRgb, makeDescriptionId, mergeTextComponentStyles } from '../Utils.js' import { TextComponent } from './TextComponent.jsx' interface Props { @@ -107,7 +107,7 @@ export function ItemTooltip({ item, advanced, resolver }: Props) { tag)} /> )} {item.showInTooltip('dyed_color') && (advanced - ? tag.isCompound() ? tag.getNumber('rgb') : tag.getAsNumber())?.toString(16).padStart(6, '0')}`], color: 'gray' }} /> + ? tag.isCompound() ? tag.getNumber('rgb') : tag.getAsNumber()))], color: 'gray' }} /> : )} {item.getLore().map((component) => diff --git a/src/app/components/ItemTooltip1204.tsx b/src/app/components/ItemTooltip1204.tsx index ca7a0741..103da565 100644 --- a/src/app/components/ItemTooltip1204.tsx +++ b/src/app/components/ItemTooltip1204.tsx @@ -5,7 +5,7 @@ import { useLocale } from '../contexts/Locale.jsx' import { useVersion } from '../contexts/Version.jsx' import { useAsync } from '../hooks/useAsync.js' import { getLanguage, getTranslation } from '../services/Resources.js' -import { message } from '../Utils.js' +import { intToDisplayHexRgb, message } from '../Utils.js' import { TextComponent } from './TextComponent.jsx' interface Props { @@ -107,7 +107,7 @@ export function ItemTooltip1204({ item, advanced }: Props) { })} {item.tag.hasCompound('display') && <> {shouldShow(item, 'dye') && item.tag.getCompound('display').hasNumber('color') && (advanced - ? + ? : )} {lore.map((component) => )} } diff --git a/src/app/components/generator/McdocRenderer.tsx b/src/app/components/generator/McdocRenderer.tsx index b1b6f1e2..c69d3d1e 100644 --- a/src/app/components/generator/McdocRenderer.tsx +++ b/src/app/components/generator/McdocRenderer.tsx @@ -14,7 +14,7 @@ import { useCallback, useEffect, useMemo, useState } from 'preact/hooks' import config from '../../Config.js' import { useLocale } from '../../contexts/Locale.jsx' import { useFocus } from '../../hooks/useFocus.js' -import { generateColor, hexId, randomInt, randomSeed } from '../../Utils.js' +import { generateColor, hexId, intToHexRgb, randomInt, randomSeed } from '../../Utils.js' import { Btn } from '../Btn.jsx' import { ItemDisplay } from '../ItemDisplay.jsx' import { Octicon } from '../Octicon.jsx' @@ -196,7 +196,7 @@ function StringHead({ type, optional, excludeStrings, node, ctx }: Props { const color = generateColor() - onChangeValue('#' + (color.toString(16).padStart(6, '0') ?? '000000')) + onChangeValue(intToHexRgb(color)) }, [onChangeValue]) return <> @@ -341,7 +341,7 @@ function NumericHead({ type, node, ctx }: Props) { return <> setValue((e.target as HTMLInputElement).value)} onBlur={onCommitValue} onSubmit={onCommitValue} onKeyDown={(e) => {if (e.key === 'Enter') onCommitValue()}} /> {colorKind && <> - onChangeColor((e.target as HTMLInputElement).value)} /> + onChangeColor((e.target as HTMLInputElement).value)} /> } {random && <>