From cc915dff368512eb348db33f12cc204b366ac473 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viktor=20R=C3=A5dberg?= Date: Sun, 28 Jan 2024 11:54:37 +0100 Subject: [PATCH 1/9] better color picker --- package.json | 1 + src/Components/Buttons/LoseButton.tsx | 2 +- src/Components/Player/PlayerMenu.tsx | 87 +++++++++++++++------------ yarn.lock | 5 ++ 4 files changed, 55 insertions(+), 40 deletions(-) diff --git a/package.json b/package.json index d22f40c..98b58c0 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,7 @@ "firebase": "^10.3.0", "ga-4-react": "^0.1.281", "react": "^18.2.0", + "react-colorful": "^5.6.1", "react-dom": "^18.2.0", "react-screen-wake-lock": "^3.0.2", "react-swipeable": "^7.0.1", diff --git a/src/Components/Buttons/LoseButton.tsx b/src/Components/Buttons/LoseButton.tsx index 8a2f039..c405dda 100644 --- a/src/Components/Buttons/LoseButton.tsx +++ b/src/Components/Buttons/LoseButton.tsx @@ -7,7 +7,7 @@ const LoseButton = twc.div((props) => [ 'absolute flex-grow border-none outline-none cursor-pointer bg-interface-loseButton-background rounded-lg select-none z-[1] webkit-user-select-none py-2 px-4 ', props.$rotation === Rotation.SideFlipped || props.$rotation === Rotation.Side - ? `left-[19%]` + ? `left-[21%]` : 'top-[21%]', ]); diff --git a/src/Components/Player/PlayerMenu.tsx b/src/Components/Player/PlayerMenu.tsx index efbf039..4fad7c2 100644 --- a/src/Components/Player/PlayerMenu.tsx +++ b/src/Components/Player/PlayerMenu.tsx @@ -5,6 +5,7 @@ import { theme } from '../../Data/theme'; import { useGlobalSettings } from '../../Hooks/useGlobalSettings'; import { usePlayers } from '../../Hooks/usePlayers'; import { useSafeRotate } from '../../Hooks/useSafeRotate'; +import { HexColorPicker } from 'react-colorful'; import { Energy, Exit, @@ -65,17 +66,12 @@ const ButtonsSections = twc.div` flex-wrap `; -const ColorPicker = twc.input` +const ColorPicker = twc.button` h-[8vmax] w-[8vmax] max-h-12 - max-w-11 - border-none - outline-none - cursor-pointer - bg-transparent - user-select-none - text-common-white + max-w-12 + rounded-full `; const SettingsContainer = twc.div((props) => [ @@ -97,7 +93,8 @@ const PlayerMenu = ({ isShown, }: PlayerMenuProps) => { const settingsContainerRef = useRef(null); - const dialogRef = useRef(null); + const resetGameDialogRef = useRef(null); + const colorPickerDialogRef = useRef(null); const { isSide } = useSafeRotate({ rotation: player.settings.rotation, @@ -107,8 +104,8 @@ const PlayerMenu = ({ const { fullscreen, wakeLock, goToStart } = useGlobalSettings(); const { updatePlayer, resetCurrentGame } = usePlayers(); - const handleColorChange = (event: React.ChangeEvent) => { - const updatedPlayer = { ...player, color: event.target.value }; + const handleColorChange = (newColor: string) => { + const updatedPlayer = { ...player, color: newColor }; updatePlayer(updatedPlayer); }; @@ -162,12 +159,11 @@ const PlayerMenu = ({ colorPickerDialogRef.current?.show()} aria-label="Color picker" /> + {/* */} {player.settings.useCommanderDamage && ( )} - - - dialogRef.current?.show()} + onClick={() => resetGameDialogRef.current?.show()} role="checkbox" aria-checked={wakeLock.active} aria-label="Reset Game" @@ -341,30 +334,46 @@ const PlayerMenu = ({ resetGameDialogRef.current?.close()} > -
-

Reset Game?

-
- - +
+
+

Reset Game?

+
+ + +
+ colorPickerDialogRef.current?.close()} + > +
+ +
+
); diff --git a/yarn.lock b/yarn.lock index 2deaaa0..10d7908 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7102,6 +7102,11 @@ re2@^1.17.7: nan "^2.18.0" node-gyp "^10.0.1" +react-colorful@^5.6.1: + version "5.6.1" + resolved "https://registry.yarnpkg.com/react-colorful/-/react-colorful-5.6.1.tgz#7dc2aed2d7c72fac89694e834d179e32f3da563b" + integrity sha512-1exovf0uGTGyq5mXQT0zgQ80uvj2PCwvF8zY1RN9/vbJVSjSo3fsB/4L3ObbF7u70NduSiK4xu4Y6q1MHoUGEw== + react-dom@^18.2.0: version "18.2.0" resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.2.0.tgz#22aaf38708db2674ed9ada224ca4aa708d821e3d" From 8b33a2a38a17fe231ee9ca5be4af1652446a95ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viktor=20R=C3=A5dberg?= Date: Sun, 28 Jan 2024 17:04:30 +0100 Subject: [PATCH 2/9] wip --- src/Components/ColorPicker.tsx | 123 +++++++++++++++++++ src/Components/Counters/ExtraCountersBar.tsx | 53 +++++++- src/Components/Player/PlayerMenu.tsx | 18 +-- src/Utils/checkContrast.ts | 87 +++++++++++++ tailwind.config.ts | 4 + 5 files changed, 273 insertions(+), 12 deletions(-) create mode 100644 src/Components/ColorPicker.tsx create mode 100644 src/Utils/checkContrast.ts diff --git a/src/Components/ColorPicker.tsx b/src/Components/ColorPicker.tsx new file mode 100644 index 0000000..a95b1d5 --- /dev/null +++ b/src/Components/ColorPicker.tsx @@ -0,0 +1,123 @@ +import React, { useRef, useEffect, useState, FC } from 'react'; + +type ColorPickerProps = { + onChange: (color: string) => void; +}; + +export const ColorPicker: FC = ({ onChange }) => { + const canvasRef = useRef(null); + const [context, setContext] = useState(null); + const [dragging, setDragging] = useState(false); + const [cursorPosition, setCursorPosition] = useState<{ + x: number; + y: number; + }>({ x: 0, y: 0 }); + + useEffect(() => { + const canvas = canvasRef.current; + if (canvas) { + const ctx = canvas.getContext('2d'); + if (ctx) { + setContext(ctx); + drawColorWheel(ctx); + } + } + }, []); + + useEffect(() => { + if (context) { + drawCursor(context, cursorPosition); + } + }, [context, cursorPosition]); + + const drawColorWheel = (ctx: CanvasRenderingContext2D) => { + const width = ctx.canvas.width; + const height = ctx.canvas.height; + const centerX = width / 2; + const centerY = height / 2; + const radius = Math.min(centerX, centerY); + + for (let angle = 0; angle <= 360; angle += 1) { + const gradient = ctx.createLinearGradient( + centerX, + centerY, + centerX + radius * Math.cos((angle * Math.PI) / 180), + centerY + radius * Math.sin((angle * Math.PI) / 180) + ); + gradient.addColorStop(0, `hsl(${angle}, 100%, 50%)`); + gradient.addColorStop(1, `hsl(${angle + 1}, 100%, 50%)`); + + ctx.beginPath(); + ctx.moveTo(centerX, centerY); + ctx.arc( + centerX, + centerY, + radius, + ((angle - 0.5) * Math.PI) / 180, + ((angle + 0.5) * Math.PI) / 180 + ); + ctx.fillStyle = gradient; + ctx.fill(); + ctx.closePath(); + } + }; + + const drawCursor = ( + ctx: CanvasRenderingContext2D, + position: { x: number; y: number } + ) => { + ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height); + drawColorWheel(ctx); + const radius = 5; + ctx.beginPath(); + ctx.arc(position.x, position.y, radius, 0, 2 * Math.PI); + ctx.strokeStyle = '#fff'; + ctx.lineWidth = 2; + ctx.stroke(); + ctx.closePath(); + }; + + const handleMouseDown = ( + event: React.MouseEvent + ) => { + setDragging(true); + handleMouseMove(event); + }; + + const handleMouseMove = ( + event: React.MouseEvent + ) => { + if (dragging && context) { + const canvas = canvasRef.current; + if (canvas) { + const rect = canvas.getBoundingClientRect(); + const x = event.clientX - rect.left; + const y = event.clientY - rect.top; + const imageData = context.getImageData(x, y, 1, 1); + const pixel = imageData.data; + const color = rgbToHex(pixel[0], pixel[1], pixel[2]); + onChange(color); + setCursorPosition({ x, y }); + } + } + }; + + const handleMouseUp = () => { + setDragging(false); + }; + + const rgbToHex = (r: number, g: number, b: number): string => { + return `#${((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1)}`; + }; + + return ( + + ); +}; diff --git a/src/Components/Counters/ExtraCountersBar.tsx b/src/Components/Counters/ExtraCountersBar.tsx index d63890c..ed04244 100644 --- a/src/Components/Counters/ExtraCountersBar.tsx +++ b/src/Components/Counters/ExtraCountersBar.tsx @@ -10,6 +10,8 @@ import { import { CounterType, Player, Rotation } from '../../Types/Player'; import { RotationDivProps } from '../Buttons/CommanderDamage'; import ExtraCounter from '../Buttons/ExtraCounter'; +import { useEffect, useState } from 'react'; +import { checkContrast } from '../../Utils/checkContrast'; const Container = twc.div((props) => [ 'flex', @@ -31,6 +33,17 @@ type ExtraCountersBarProps = { const ExtraCountersBar = ({ player }: ExtraCountersBarProps) => { const { updatePlayer } = usePlayers(); + const [iconColor, setIconColor] = useState<'dark' | 'light'>('dark'); + + useEffect(() => { + const contrast = checkContrast(player.color, '#00000080'); + + if (contrast === 'Fail') { + setIconColor('light'); + } else { + setIconColor('dark'); + } + }, [player.color]); const handleCounterChange = ( updatedCounterTotal: number, @@ -93,7 +106,13 @@ const ExtraCountersBar = ({ player }: ExtraCountersBarProps) => { {useCommanderDamage && ( } + Icon={ + + } type={CounterType.CommanderTax} counterTotal={ player.extraCounters?.find( @@ -108,7 +127,13 @@ const ExtraCountersBar = ({ player }: ExtraCountersBarProps) => { {Boolean(useCommanderDamage && usePartner) && ( } + Icon={ + + } type={CounterType.PartnerTax} counterTotal={ player.extraCounters?.find( @@ -123,7 +148,13 @@ const ExtraCountersBar = ({ player }: ExtraCountersBarProps) => { {usePoison && ( } + Icon={ + + } type={CounterType.Poison} counterTotal={ player.extraCounters?.find((counter) => counter.type === 'poison') @@ -137,7 +168,13 @@ const ExtraCountersBar = ({ player }: ExtraCountersBarProps) => { {useEnergy && ( } + Icon={ + + } type={CounterType.Energy} counterTotal={ player.extraCounters?.find((counter) => counter.type === 'energy') @@ -151,7 +188,13 @@ const ExtraCountersBar = ({ player }: ExtraCountersBarProps) => { {useExperience && ( } + Icon={ + + } type={CounterType.Experience} counterTotal={ player.extraCounters?.find( diff --git a/src/Components/Player/PlayerMenu.tsx b/src/Components/Player/PlayerMenu.tsx index 4fad7c2..8bc942a 100644 --- a/src/Components/Player/PlayerMenu.tsx +++ b/src/Components/Player/PlayerMenu.tsx @@ -5,7 +5,6 @@ import { theme } from '../../Data/theme'; import { useGlobalSettings } from '../../Hooks/useGlobalSettings'; import { usePlayers } from '../../Hooks/usePlayers'; import { useSafeRotate } from '../../Hooks/useSafeRotate'; -import { HexColorPicker } from 'react-colorful'; import { Energy, Exit, @@ -18,6 +17,7 @@ import { } from '../../Icons/generated'; import { Player, Rotation } from '../../Types/Player'; import { RotationDivProps } from '../Buttons/CommanderDamage'; +import { ColorPicker } from '../ColorPicker'; const CheckboxContainer = twc.div``; @@ -66,7 +66,7 @@ const ButtonsSections = twc.div` flex-wrap `; -const ColorPicker = twc.button` +const ColorPickerButton = twc.button` h-[8vmax] w-[8vmax] max-h-12 @@ -158,12 +158,11 @@ const PlayerMenu = ({ > - colorPickerDialogRef.current?.show()} aria-label="Color picker" /> - {/* */} {player.settings.useCommanderDamage && ( + colorPickerDialogRef.current?.close()} >
- + style={{ + height: '80%', + width: '60%', + }} + /> */} +
diff --git a/src/Utils/checkContrast.ts b/src/Utils/checkContrast.ts new file mode 100644 index 0000000..4a39c4f --- /dev/null +++ b/src/Utils/checkContrast.ts @@ -0,0 +1,87 @@ +type RGBA = { + red: number; + green: number; + blue: number; + alpha: number; +}; + +export const hexToRgb = (hex: string): RGBA => { + hex = hex.replace(/^#/, ''); + let alpha = 255; + + if (hex.length === 8) { + alpha = parseInt(hex.slice(6, 8), 16); + hex = hex.substring(0, 6); + } + + if (hex.length === 4) { + alpha = parseInt(hex.slice(3, 4).repeat(2), 16); + hex = hex.substring(0, 3); + } + + if (hex.length === 3) { + hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2]; + } + + const num = parseInt(hex, 16); + const red = num >> 16; + const green = (num >> 8) & 255; + const blue = num & 255; + + return { red, green, blue, alpha }; +}; + +export const luminance = (a: number, b: number) => { + const l1 = Math.max(a, b); + const l2 = Math.min(a, b); + return (l1 + 0.05) / (l2 + 0.05); +}; + +export const rgbContrast = (a: RGBA, b: RGBA) => { + return luminance(relativeLuminance(a), relativeLuminance(b)); +}; + +// calculate the color contrast ratio +export const checkContrast = (hexC1: string, hexC2: string) => { + const color1rgb = hexToRgb(hexC1); + const color2rgb = hexToRgb(hexC2); + + const contrast = rgbContrast(color1rgb, color2rgb); + + if (contrast >= 7) { + return 'AAA'; + } + + if (contrast >= 4.5) { + return 'AA'; + } + + if (contrast >= 3) { + return 'AA Large'; + } + + return 'Fail'; +}; + +// red, green, and blue coefficients +const rc = 0.2126; +const gc = 0.7152; +const bc = 0.0722; +// low-gamma adjust coefficient +const lowc = 1 / 12.92; + +function adjustGamma(_) { + return Math.pow((_ + 0.055) / 1.055, 2.4); +} + +export const relativeLuminance = (rgb: RGBA) => { + const rsrgb = rgb.red / 255; + const gsrgb = rgb.green / 255; + const bsrgb = rgb.blue / 255; + + const r = rsrgb <= 0.03928 ? rsrgb * lowc : adjustGamma(rsrgb); + const g = gsrgb <= 0.03928 ? gsrgb * lowc : adjustGamma(gsrgb); + const b = bsrgb <= 0.03928 ? bsrgb * lowc : adjustGamma(bsrgb); + + return r * rc + g * gc + b * bc; +}; diff --git a/tailwind.config.ts b/tailwind.config.ts index 714d343..44b0e56 100644 --- a/tailwind.config.ts +++ b/tailwind.config.ts @@ -54,6 +54,10 @@ export default { backdrop: 'rgba(0, 0, 0, 0.3)', settings: 'rgba(20, 20, 0, 0.9)', }, + icons: { + dark: '#000000', + light: '#FFFFFF', + }, text: { primary: '#F5F5F5', secondary: '#76A6A5', From 664e2e568831789dd8e80bb12f67bcb7fab63256 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viktor=20R=C3=A5dberg?= Date: Mon, 19 Feb 2024 07:38:17 +0100 Subject: [PATCH 3/9] round color picker --- src/Components/Player/PlayerMenu.tsx | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/Components/Player/PlayerMenu.tsx b/src/Components/Player/PlayerMenu.tsx index ba2d99c..42eb198 100644 --- a/src/Components/Player/PlayerMenu.tsx +++ b/src/Components/Player/PlayerMenu.tsx @@ -67,12 +67,15 @@ const ButtonsSections = twc.div` flex-wrap `; -const ColorPickerButton = twc.button` +const ColorPickerButton = twc.div` h-[8vmax] w-[8vmax] + relative max-h-12 max-w-12 rounded-full + cursor-pointer + overflow-hidden `; const SettingsContainer = twc.div((props) => [ @@ -159,11 +162,13 @@ const PlayerMenu = ({ > - colorPickerDialogRef.current?.show()} - aria-label="Color picker" - /> + + + {player.settings.useCommanderDamage && ( Date: Sat, 16 Mar 2024 09:31:59 +0100 Subject: [PATCH 4/9] use normal picker again --- src/Components/ColorPicker.tsx | 123 --------------------------- src/Components/Player/PlayerMenu.tsx | 25 +----- 2 files changed, 3 insertions(+), 145 deletions(-) delete mode 100644 src/Components/ColorPicker.tsx diff --git a/src/Components/ColorPicker.tsx b/src/Components/ColorPicker.tsx deleted file mode 100644 index a95b1d5..0000000 --- a/src/Components/ColorPicker.tsx +++ /dev/null @@ -1,123 +0,0 @@ -import React, { useRef, useEffect, useState, FC } from 'react'; - -type ColorPickerProps = { - onChange: (color: string) => void; -}; - -export const ColorPicker: FC = ({ onChange }) => { - const canvasRef = useRef(null); - const [context, setContext] = useState(null); - const [dragging, setDragging] = useState(false); - const [cursorPosition, setCursorPosition] = useState<{ - x: number; - y: number; - }>({ x: 0, y: 0 }); - - useEffect(() => { - const canvas = canvasRef.current; - if (canvas) { - const ctx = canvas.getContext('2d'); - if (ctx) { - setContext(ctx); - drawColorWheel(ctx); - } - } - }, []); - - useEffect(() => { - if (context) { - drawCursor(context, cursorPosition); - } - }, [context, cursorPosition]); - - const drawColorWheel = (ctx: CanvasRenderingContext2D) => { - const width = ctx.canvas.width; - const height = ctx.canvas.height; - const centerX = width / 2; - const centerY = height / 2; - const radius = Math.min(centerX, centerY); - - for (let angle = 0; angle <= 360; angle += 1) { - const gradient = ctx.createLinearGradient( - centerX, - centerY, - centerX + radius * Math.cos((angle * Math.PI) / 180), - centerY + radius * Math.sin((angle * Math.PI) / 180) - ); - gradient.addColorStop(0, `hsl(${angle}, 100%, 50%)`); - gradient.addColorStop(1, `hsl(${angle + 1}, 100%, 50%)`); - - ctx.beginPath(); - ctx.moveTo(centerX, centerY); - ctx.arc( - centerX, - centerY, - radius, - ((angle - 0.5) * Math.PI) / 180, - ((angle + 0.5) * Math.PI) / 180 - ); - ctx.fillStyle = gradient; - ctx.fill(); - ctx.closePath(); - } - }; - - const drawCursor = ( - ctx: CanvasRenderingContext2D, - position: { x: number; y: number } - ) => { - ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height); - drawColorWheel(ctx); - const radius = 5; - ctx.beginPath(); - ctx.arc(position.x, position.y, radius, 0, 2 * Math.PI); - ctx.strokeStyle = '#fff'; - ctx.lineWidth = 2; - ctx.stroke(); - ctx.closePath(); - }; - - const handleMouseDown = ( - event: React.MouseEvent - ) => { - setDragging(true); - handleMouseMove(event); - }; - - const handleMouseMove = ( - event: React.MouseEvent - ) => { - if (dragging && context) { - const canvas = canvasRef.current; - if (canvas) { - const rect = canvas.getBoundingClientRect(); - const x = event.clientX - rect.left; - const y = event.clientY - rect.top; - const imageData = context.getImageData(x, y, 1, 1); - const pixel = imageData.data; - const color = rgbToHex(pixel[0], pixel[1], pixel[2]); - onChange(color); - setCursorPosition({ x, y }); - } - } - }; - - const handleMouseUp = () => { - setDragging(false); - }; - - const rgbToHex = (r: number, g: number, b: number): string => { - return `#${((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1)}`; - }; - - return ( - - ); -}; diff --git a/src/Components/Player/PlayerMenu.tsx b/src/Components/Player/PlayerMenu.tsx index 42eb198..87d5d49 100644 --- a/src/Components/Player/PlayerMenu.tsx +++ b/src/Components/Player/PlayerMenu.tsx @@ -17,7 +17,6 @@ import { } from '../../Icons/generated'; import { Player, Rotation } from '../../Types/Player'; import { RotationDivProps } from '../Buttons/CommanderDamage'; -import { ColorPicker } from '../ColorPicker'; const CheckboxContainer = twc.div``; @@ -98,7 +97,6 @@ const PlayerMenu = ({ }: PlayerMenuProps) => { const settingsContainerRef = useRef(null); const resetGameDialogRef = useRef(null); - const colorPickerDialogRef = useRef(null); const { isSide } = useSafeRotate({ rotation: player.settings.rotation, @@ -108,8 +106,8 @@ const PlayerMenu = ({ const { fullscreen, wakeLock, goToStart } = useGlobalSettings(); const { updatePlayer, resetCurrentGame } = usePlayers(); - const handleColorChange = (newColor: string) => { - const updatedPlayer = { ...player, color: newColor }; + const handleColorChange = (event: React.ChangeEvent) => { + const updatedPlayer = { ...player, color: event.target.value }; updatePlayer(updatedPlayer); }; @@ -164,6 +162,7 @@ const PlayerMenu = ({ - - colorPickerDialogRef.current?.close()} - > -
- {/* */} - -
-
); From 7852520f8e03a76b7eb4fbfec2c2c9f7d5312c26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viktor=20R=C3=A5dberg?= Date: Sat, 16 Mar 2024 09:59:40 +0100 Subject: [PATCH 5/9] minus plus icon color --- src/Components/Buttons/LifeCounterButton.tsx | 34 ++++++++++++++------ src/Components/LifeCounter/Health.tsx | 6 ++-- tailwind.config.ts | 4 +-- 3 files changed, 28 insertions(+), 16 deletions(-) diff --git a/src/Components/Buttons/LifeCounterButton.tsx b/src/Components/Buttons/LifeCounterButton.tsx index 007da84..a5743f5 100644 --- a/src/Components/Buttons/LifeCounterButton.tsx +++ b/src/Components/Buttons/LifeCounterButton.tsx @@ -1,8 +1,9 @@ -import { useRef, useState } from 'react'; +import { useEffect, useRef, useState } from 'react'; import { TwcComponentProps, twc } from 'react-twc'; import { lifeLongPressMultiplier } from '../../Data/constants'; -import { Rotation } from '../../Types/Player'; +import { Player, Rotation } from '../../Types/Player'; import { MAX_TAP_MOVE_DISTANCE } from './CommanderDamage'; +import { checkContrast } from '../../Utils/checkContrast'; type RotationButtonProps = TwcComponentProps<'div'> & { $align?: string; @@ -13,7 +14,6 @@ const LifeCounterButtonTwc = twc.button` h-full w-full flex - text-lifeCounter-text font-semibold bg-transparent border-none @@ -40,17 +40,15 @@ const TextContainer = twc.div((props) => [ ]); type LifeCounterButtonProps = { - lifeTotal: number; + player: Player; setLifeTotal: (lifeTotal: number) => void; - rotation: number; operation: 'add' | 'subtract'; increment: number; }; const LifeCounterButton = ({ - lifeTotal, + player, setLifeTotal, - rotation, operation, increment, }: LifeCounterButtonProps) => { @@ -59,8 +57,20 @@ const LifeCounterButton = ({ const [hasPressedDown, setHasPressedDown] = useState(false); const downPositionRef = useRef({ x: 0, y: 0 }); + const [iconColor, setIconColor] = useState<'dark' | 'light'>('dark'); + + useEffect(() => { + const contrast = checkContrast(player.color, '#00000080'); + + if (contrast === 'Fail') { + setIconColor('light'); + } else { + setIconColor('dark'); + } + }, [player.color]); + const handleLifeChange = (increment: number) => { - setLifeTotal(lifeTotal + increment); + setLifeTotal(player.lifeTotal + increment); }; const handleDownInput = (event: React.PointerEvent) => { @@ -102,7 +112,8 @@ const LifeCounterButton = ({ }; const fontSize = - rotation === Rotation.SideFlipped || rotation === Rotation.Side + player.settings.rotation === Rotation.SideFlipped || + player.settings.rotation === Rotation.Side ? '8vmax' : '12vmin'; @@ -118,8 +129,11 @@ const LifeCounterButton = ({ aria-label={`${operation === 'add' ? 'Add' : 'Subtract'} life`} > {operation === 'add' ? '\u002B' : '\u2212'} diff --git a/src/Components/LifeCounter/Health.tsx b/src/Components/LifeCounter/Health.tsx index a3b1e2b..2128776 100644 --- a/src/Components/LifeCounter/Health.tsx +++ b/src/Components/LifeCounter/Health.tsx @@ -118,9 +118,8 @@ const Health = ({ return ( @@ -148,9 +147,8 @@ const Health = ({ diff --git a/tailwind.config.ts b/tailwind.config.ts index 44b0e56..df02515 100644 --- a/tailwind.config.ts +++ b/tailwind.config.ts @@ -55,8 +55,8 @@ export default { settings: 'rgba(20, 20, 0, 0.9)', }, icons: { - dark: '#000000', - light: '#FFFFFF', + dark: '#00000080', + light: '#ffffff4f', }, text: { primary: '#F5F5F5', From 1bff41bc1058e7f6de536ef802db70169df28f3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viktor=20R=C3=A5dberg?= Date: Sat, 16 Mar 2024 10:04:35 +0100 Subject: [PATCH 6/9] remove colorful --- package.json | 1 - yarn.lock | 5 ----- 2 files changed, 6 deletions(-) diff --git a/package.json b/package.json index f147db9..4371640 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,6 @@ "firebase": "^10.3.0", "ga-4-react": "^0.1.281", "react": "^18.2.0", - "react-colorful": "^5.6.1", "react-dom": "^18.2.0", "react-screen-wake-lock": "^3.0.2", "react-swipeable": "^7.0.1", diff --git a/yarn.lock b/yarn.lock index 10d7908..2deaaa0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7102,11 +7102,6 @@ re2@^1.17.7: nan "^2.18.0" node-gyp "^10.0.1" -react-colorful@^5.6.1: - version "5.6.1" - resolved "https://registry.yarnpkg.com/react-colorful/-/react-colorful-5.6.1.tgz#7dc2aed2d7c72fac89694e834d179e32f3da563b" - integrity sha512-1exovf0uGTGyq5mXQT0zgQ80uvj2PCwvF8zY1RN9/vbJVSjSo3fsB/4L3ObbF7u70NduSiK4xu4Y6q1MHoUGEw== - react-dom@^18.2.0: version "18.2.0" resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.2.0.tgz#22aaf38708db2674ed9ada224ca4aa708d821e3d" From 677fd79bee59e05870ec115b1c87fbffd07c4683 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viktor=20R=C3=A5dberg?= Date: Sat, 16 Mar 2024 10:23:15 +0100 Subject: [PATCH 7/9] fix long press down --- src/Components/Buttons/CommanderDamage.tsx | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/Components/Buttons/CommanderDamage.tsx b/src/Components/Buttons/CommanderDamage.tsx index e72aa23..1ea9d9b 100644 --- a/src/Components/Buttons/CommanderDamage.tsx +++ b/src/Components/Buttons/CommanderDamage.tsx @@ -66,8 +66,7 @@ export const CommanderDamage = ({ }: CommanderDamageButtonComponentProps) => { const { updatePlayer } = usePlayers(); const timeoutRef = useRef(undefined); - const [timeoutFinished, setTimeoutFinished] = useState(false); - const [hasPressedDown, setHasPressedDown] = useState(false); + const [downLongPressed, setDownLongPressed] = useState(false); const downPositionRef = useRef({ x: 0, y: 0 }); const handleCommanderDamageChange = ( @@ -109,16 +108,16 @@ export const CommanderDamage = ({ const handleDownInput = ({ opponentIndex, isPartner, event }: InputProps) => { downPositionRef.current = { x: event.clientX, y: event.clientY }; - setTimeoutFinished(false); - setHasPressedDown(true); + setDownLongPressed(false); + timeoutRef.current = setTimeout(() => { - setTimeoutFinished(true); + setDownLongPressed(true); handleCommanderDamageChange(opponentIndex, -1, isPartner); }, decrementTimeoutMs); }; const handleUpInput = ({ opponentIndex, isPartner, event }: InputProps) => { - if (!(hasPressedDown && !timeoutFinished)) { + if (downLongPressed) { return; } @@ -134,14 +133,14 @@ export const CommanderDamage = ({ return; } + clearTimeout(timeoutRef.current); + handleCommanderDamageChange(opponentIndex, 1, isPartner); - setHasPressedDown(false); }; const handleLeaveInput = () => { - setTimeoutFinished(true); + setDownLongPressed(true); clearTimeout(timeoutRef.current); - setHasPressedDown(false); }; const opponentIndex = opponent.index; From 71e5614f52f2fa50d58fc9a27873252ab005643a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viktor=20R=C3=A5dberg?= Date: Sat, 16 Mar 2024 10:38:23 +0100 Subject: [PATCH 8/9] bump to new version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4371640..8001815 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "life-trinket", "private": true, - "version": "0.6.4", + "version": "0.6.5", "type": "commonjs", "engines": { "node": ">=18", From efbfb7719c38b2a5fd843006021a924037ffcec1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viktor=20R=C3=A5dberg?= Date: Sat, 16 Mar 2024 10:40:18 +0100 Subject: [PATCH 9/9] tsc --- src/Utils/checkContrast.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Utils/checkContrast.ts b/src/Utils/checkContrast.ts index 4a39c4f..549b0ad 100644 --- a/src/Utils/checkContrast.ts +++ b/src/Utils/checkContrast.ts @@ -70,8 +70,8 @@ const bc = 0.0722; // low-gamma adjust coefficient const lowc = 1 / 12.92; -function adjustGamma(_) { - return Math.pow((_ + 0.055) / 1.055, 2.4); +function adjustGamma(input: number) { + return Math.pow((input + 0.055) / 1.055, 2.4); } export const relativeLuminance = (rgb: RGBA) => {