From 3418c7859c6b87791c565e61481f78aa30e75967 Mon Sep 17 00:00:00 2001 From: "whey.party" Date: Tue, 2 Dec 2025 14:11:36 +0700 Subject: [PATCH 1/2] prevent crash from opening appearance --- src/screens/Settings/AppIconSettings/useCurrentAppIcon.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/screens/Settings/AppIconSettings/useCurrentAppIcon.ts b/src/screens/Settings/AppIconSettings/useCurrentAppIcon.ts index 4bc9b665a..7a29ef2f2 100644 --- a/src/screens/Settings/AppIconSettings/useCurrentAppIcon.ts +++ b/src/screens/Settings/AppIconSettings/useCurrentAppIcon.ts @@ -20,7 +20,7 @@ export function useCurrentAppIcon() { return useMemo(() => { return ( appIconSets.defaults.find(i => i.id === currentAppIcon) ?? - appIconSets.core.find(i => i.id === currentAppIcon) ?? + //appIconSets.core.find(i => i.id === currentAppIcon) ?? appIconSets.defaults[0] ) }, [appIconSets, currentAppIcon]) -- 2.39.5 (Apple Git-154) From 11726a0f2a0fa27b67d94bff86baffb8fc725cc9 Mon Sep 17 00:00:00 2001 From: "whey.party" Date: Tue, 2 Dec 2025 14:11:47 +0700 Subject: [PATCH 2/2] replace culori with chroma-js --- package.json | 3 +- src/alf/index.tsx | 19 ++++-------- src/components/forms/Slider.tsx | 32 ++++++++++++++++++--- src/screens/Settings/AppearanceSettings.tsx | 1 + yarn.lock | 15 ++++++---- 5 files changed, 47 insertions(+), 23 deletions(-) diff --git a/package.json b/package.json index 90befd7c7..b824d22ac 100644 --- a/package.json +++ b/package.json @@ -126,7 +126,7 @@ "babel-plugin-transform-remove-console": "^6.9.4", "bcp-47": "^2.1.0", "bcp-47-match": "^2.0.3", - "culori": "^4.0.2", + "chroma-js": "^3.2.0", "date-fns": "^2.30.0", "email-validator": "^2.0.4", "emoji-mart": "^5.5.2", @@ -236,6 +236,7 @@ "@sentry/webpack-plugin": "^3.2.2", "@testing-library/jest-native": "^5.4.3", "@testing-library/react-native": "^13.2.0", + "@types/chroma-js": "^3.1.2", "@types/culori": "^4.0.1", "@types/jest": "29.5.14", "@types/lodash.chunk": "^4.2.7", diff --git a/src/alf/index.tsx b/src/alf/index.tsx index 2c6a9c316..0a1bf6807 100644 --- a/src/alf/index.tsx +++ b/src/alf/index.tsx @@ -1,6 +1,6 @@ import React from 'react' import {createTheme, type Theme, type ThemeName} from '@bsky.app/alf' -import {formatHex, modeOklch, useMode as utilMode} from 'culori' +import chroma from 'chroma-js' import {useThemePrefs} from '#/state/shell/color-mode' import { @@ -70,21 +70,14 @@ Context.displayName = 'AlfContext' export type SchemeType = typeof themes -function changeHue(color: string, hueShift: number) { - if (!hueShift || hueShift === 0) return color +export function changeHue(colorStr: string, hueShift: number) { + if (!hueShift || hueShift === 0) return colorStr - let lablch = utilMode(modeOklch) - const parsed = lablch(color) + const color = chroma(colorStr).oklch() - if (!parsed) return color + const newHue = (color[2] + hueShift + 360) % 360 - const {l, c, h} = parsed as {l: number; c: number; h: number | undefined} - - const currentHue = h || 0 - - const newHue = (currentHue + hueShift + 360) % 360 - - return formatHex({mode: 'oklch', l, c, h: newHue}) + return chroma.oklch(color[0], color[1], newHue).hex() } export function shiftPalette(palette: Palette, hueShift: number): Palette { diff --git a/src/components/forms/Slider.tsx b/src/components/forms/Slider.tsx index 237ef83b3..b7f912fac 100644 --- a/src/components/forms/Slider.tsx +++ b/src/components/forms/Slider.tsx @@ -1,7 +1,8 @@ +import {useEffect, useState} from 'react' import {type ViewStyle} from 'react-native' import {Slider as RNSlider} from '@miblanchard/react-native-slider' -import {useTheme} from '#/alf' +import {changeHue, useTheme} from '#/alf' interface SliderProps { value: number @@ -13,6 +14,7 @@ interface SliderProps { minimumTrackStyle?: ViewStyle thumbStyle?: ViewStyle thumbTouchSize?: {width: number; height: number} + debounceFull?: boolean } export function Slider({ @@ -25,13 +27,35 @@ export function Slider({ minimumTrackStyle, thumbStyle, thumbTouchSize = {width: 40, height: 40}, + debounceFull, }: SliderProps) { const t = useTheme() + // We need local state to handle visual updates while dragging if debounceFull is true + const [localValue, setLocalValue] = useState(value) + + // Sync local state if the parent updates the value prop externally + useEffect(() => { + setLocalValue(value) + }, [value]) return ( onValueChange(values[0])} + value={[localValue]} // Read from local state + onValueChange={values => { + const nextVal = values[0] + setLocalValue(nextVal) + + // If NOT debouncing, update parent immediately while dragging + if (!debounceFull) { + onValueChange(nextVal) + } + }} + onSlidingComplete={values => { + // If debouncing, update parent only when done dragging + if (debounceFull) { + onValueChange(values[0]) + } + }} minimumValue={minimumValue} maximumValue={maximumValue} step={step} @@ -44,7 +68,7 @@ export function Slider({ minimumTrackStyle={{ height: 4, borderRadius: 2, - backgroundColor: t.palette.primary_500, + backgroundColor: changeHue(t.palette.primary_500, localValue - value), ...minimumTrackStyle, }} thumbStyle={{ diff --git a/src/screens/Settings/AppearanceSettings.tsx b/src/screens/Settings/AppearanceSettings.tsx index 39f1fa299..393c54755 100644 --- a/src/screens/Settings/AppearanceSettings.tsx +++ b/src/screens/Settings/AppearanceSettings.tsx @@ -189,6 +189,7 @@ export function AppearanceSettingsScreen({}: Props) { minimumValue={0} maximumValue={360} step={1} + debounceFull={true} /> diff --git a/yarn.lock b/yarn.lock index 7e1954909..a6d1b2c7b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7427,6 +7427,11 @@ dependencies: "@types/node" "*" +"@types/chroma-js@^3.1.2": + version "3.1.2" + resolved "https://registry.yarnpkg.com/@types/chroma-js/-/chroma-js-3.1.2.tgz#29dd767ae46124c9d0cd3370bedad7364adcfd10" + integrity sha512-YBTQqArPN8A0niHXCwrO1z5x++a+6l0mLBykncUpr23oIPW7L4h39s6gokdK/bDrPmSh8+TjMmrhBPnyiaWPmQ== + "@types/connect-history-api-fallback@^1.3.5": version "1.5.0" resolved "https://registry.yarnpkg.com/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.0.tgz#9fd20b3974bdc2bcd4ac6567e2e0f6885cb2cf41" @@ -9331,6 +9336,11 @@ chownr@^3.0.0: resolved "https://registry.yarnpkg.com/chownr/-/chownr-3.0.0.tgz#9855e64ecd240a9cc4267ce8a4aa5d24a1da15e4" integrity sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g== +chroma-js@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/chroma-js/-/chroma-js-3.2.0.tgz#4e9e665290b9bbfece524fccf759d5120e351ff2" + integrity sha512-os/OippSlX1RlWWr+QDPcGUZs0uoqr32urfxESG9U93lhUfbnlyckte84Q8P1UQY/qth983AS1JONKmLS4T0nw== + chrome-launcher@^0.15.2: version "0.15.2" resolved "https://registry.yarnpkg.com/chrome-launcher/-/chrome-launcher-0.15.2.tgz#4e6404e32200095fdce7f6a1e1004f9bd36fa5da" @@ -9980,11 +9990,6 @@ csstype@^3.0.2: resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.2.tgz#1d4bf9d572f11c14031f0436e1c10bc1f571f50b" integrity sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ== -culori@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/culori/-/culori-4.0.2.tgz#fbb28dbeb8d13d0eeab7520191f74ab822a8ca71" - integrity sha512-1+BhOB8ahCn4O0cep0Sh2l9KCOfOdY+BXJnKMHFFzDEouSr/el18QwXEMRlOj9UY5nCeA8UN3a/82rUWRBeyBw== - data-urls@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-3.0.2.tgz#9cf24a477ae22bcef5cd5f6f0bfbc1d2d3be9143" -- 2.39.5 (Apple Git-154)