fix appearance crashes #18

merged
opened by whey.party targeting main
  1. prevent crash from opening appearance
  2. replace culori with chroma-js
Changed files
+48 -24
src
alf
components
forms
screens
Settings
+1 -1
src/screens/Settings/AppIconSettings/useCurrentAppIcon.ts
··· 20 20 return useMemo(() => { 21 21 return ( 22 22 appIconSets.defaults.find(i => i.id === currentAppIcon) ?? 23 - appIconSets.core.find(i => i.id === currentAppIcon) ?? 23 + //appIconSets.core.find(i => i.id === currentAppIcon) ?? 24 24 appIconSets.defaults[0] 25 25 ) 26 26 }, [appIconSets, currentAppIcon])
+2 -1
package.json
··· 126 126 "babel-plugin-transform-remove-console": "^6.9.4", 127 127 "bcp-47": "^2.1.0", 128 128 "bcp-47-match": "^2.0.3", 129 - "culori": "^4.0.2", 129 + "chroma-js": "^3.2.0", 130 130 "date-fns": "^2.30.0", 131 131 "email-validator": "^2.0.4", 132 132 "emoji-mart": "^5.5.2", ··· 236 236 "@sentry/webpack-plugin": "^3.2.2", 237 237 "@testing-library/jest-native": "^5.4.3", 238 238 "@testing-library/react-native": "^13.2.0", 239 + "@types/chroma-js": "^3.1.2", 239 240 "@types/culori": "^4.0.1", 240 241 "@types/jest": "29.5.14", 241 242 "@types/lodash.chunk": "^4.2.7",
+6 -13
src/alf/index.tsx
··· 1 1 import React from 'react' 2 2 import {createTheme, type Theme, type ThemeName} from '@bsky.app/alf' 3 - import {formatHex, modeOklch, useMode as utilMode} from 'culori' 3 + import chroma from 'chroma-js' 4 4 5 5 import {useThemePrefs} from '#/state/shell/color-mode' 6 6 import { ··· 70 70 71 71 export type SchemeType = typeof themes 72 72 73 - function changeHue(color: string, hueShift: number) { 74 - if (!hueShift || hueShift === 0) return color 73 + export function changeHue(colorStr: string, hueShift: number) { 74 + if (!hueShift || hueShift === 0) return colorStr 75 75 76 - let lablch = utilMode(modeOklch) 77 - const parsed = lablch(color) 76 + const color = chroma(colorStr).oklch() 78 77 79 - if (!parsed) return color 78 + const newHue = (color[2] + hueShift + 360) % 360 80 79 81 - const {l, c, h} = parsed as {l: number; c: number; h: number | undefined} 82 - 83 - const currentHue = h || 0 84 - 85 - const newHue = (currentHue + hueShift + 360) % 360 86 - 87 - return formatHex({mode: 'oklch', l, c, h: newHue}) 80 + return chroma.oklch(color[0], color[1], newHue).hex() 88 81 } 89 82 90 83 export function shiftPalette(palette: Palette, hueShift: number): Palette {
+28 -4
src/components/forms/Slider.tsx
··· 1 + import {useEffect, useState} from 'react' 1 2 import {type ViewStyle} from 'react-native' 2 3 import {Slider as RNSlider} from '@miblanchard/react-native-slider' 3 4 4 - import {useTheme} from '#/alf' 5 + import {changeHue, useTheme} from '#/alf' 5 6 6 7 interface SliderProps { 7 8 value: number ··· 13 14 minimumTrackStyle?: ViewStyle 14 15 thumbStyle?: ViewStyle 15 16 thumbTouchSize?: {width: number; height: number} 17 + debounceFull?: boolean 16 18 } 17 19 18 20 export function Slider({ ··· 25 27 minimumTrackStyle, 26 28 thumbStyle, 27 29 thumbTouchSize = {width: 40, height: 40}, 30 + debounceFull, 28 31 }: SliderProps) { 29 32 const t = useTheme() 33 + // We need local state to handle visual updates while dragging if debounceFull is true 34 + const [localValue, setLocalValue] = useState(value) 35 + 36 + // Sync local state if the parent updates the value prop externally 37 + useEffect(() => { 38 + setLocalValue(value) 39 + }, [value]) 30 40 31 41 return ( 32 42 <RNSlider 33 - value={[value]} // always an array 34 - onValueChange={values => onValueChange(values[0])} 43 + value={[localValue]} // Read from local state 44 + onValueChange={values => { 45 + const nextVal = values[0] 46 + setLocalValue(nextVal) 47 + 48 + // If NOT debouncing, update parent immediately while dragging 49 + if (!debounceFull) { 50 + onValueChange(nextVal) 51 + } 52 + }} 53 + onSlidingComplete={values => { 54 + // If debouncing, update parent only when done dragging 55 + if (debounceFull) { 56 + onValueChange(values[0]) 57 + } 58 + }} 35 59 minimumValue={minimumValue} 36 60 maximumValue={maximumValue} 37 61 step={step} ··· 44 68 minimumTrackStyle={{ 45 69 height: 4, 46 70 borderRadius: 2, 47 - backgroundColor: t.palette.primary_500, 71 + backgroundColor: changeHue(t.palette.primary_500, localValue - value), 48 72 ...minimumTrackStyle, 49 73 }} 50 74 thumbStyle={{
+1
src/screens/Settings/AppearanceSettings.tsx
··· 189 189 minimumValue={0} 190 190 maximumValue={360} 191 191 step={1} 192 + debounceFull={true} 192 193 /> 193 194 </View> 194 195 </SettingsList.Group>
+10 -5
yarn.lock
··· 7427 7427 dependencies: 7428 7428 "@types/node" "*" 7429 7429 7430 + "@types/chroma-js@^3.1.2": 7431 + version "3.1.2" 7432 + resolved "https://registry.yarnpkg.com/@types/chroma-js/-/chroma-js-3.1.2.tgz#29dd767ae46124c9d0cd3370bedad7364adcfd10" 7433 + integrity sha512-YBTQqArPN8A0niHXCwrO1z5x++a+6l0mLBykncUpr23oIPW7L4h39s6gokdK/bDrPmSh8+TjMmrhBPnyiaWPmQ== 7434 + 7430 7435 "@types/connect-history-api-fallback@^1.3.5": 7431 7436 version "1.5.0" 7432 7437 resolved "https://registry.yarnpkg.com/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.0.tgz#9fd20b3974bdc2bcd4ac6567e2e0f6885cb2cf41" ··· 9331 9336 resolved "https://registry.yarnpkg.com/chownr/-/chownr-3.0.0.tgz#9855e64ecd240a9cc4267ce8a4aa5d24a1da15e4" 9332 9337 integrity sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g== 9333 9338 9339 + chroma-js@^3.2.0: 9340 + version "3.2.0" 9341 + resolved "https://registry.yarnpkg.com/chroma-js/-/chroma-js-3.2.0.tgz#4e9e665290b9bbfece524fccf759d5120e351ff2" 9342 + integrity sha512-os/OippSlX1RlWWr+QDPcGUZs0uoqr32urfxESG9U93lhUfbnlyckte84Q8P1UQY/qth983AS1JONKmLS4T0nw== 9343 + 9334 9344 chrome-launcher@^0.15.2: 9335 9345 version "0.15.2" 9336 9346 resolved "https://registry.yarnpkg.com/chrome-launcher/-/chrome-launcher-0.15.2.tgz#4e6404e32200095fdce7f6a1e1004f9bd36fa5da" ··· 9980 9990 resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.2.tgz#1d4bf9d572f11c14031f0436e1c10bc1f571f50b" 9981 9991 integrity sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ== 9982 9992 9983 - culori@^4.0.2: 9984 - version "4.0.2" 9985 - resolved "https://registry.yarnpkg.com/culori/-/culori-4.0.2.tgz#fbb28dbeb8d13d0eeab7520191f74ab822a8ca71" 9986 - integrity sha512-1+BhOB8ahCn4O0cep0Sh2l9KCOfOdY+BXJnKMHFFzDEouSr/el18QwXEMRlOj9UY5nCeA8UN3a/82rUWRBeyBw== 9987 - 9988 9993 data-urls@^3.0.2: 9989 9994 version "3.0.2" 9990 9995 resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-3.0.2.tgz#9cf24a477ae22bcef5cd5f6f0bfbc1d2d3be9143"