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
···
return useMemo(() => {
return (
appIconSets.defaults.find(i => i.id === currentAppIcon) ??
-
appIconSets.core.find(i => i.id === currentAppIcon) ??
appIconSets.defaults[0]
)
}, [appIconSets, currentAppIcon])
···
return useMemo(() => {
return (
appIconSets.defaults.find(i => i.id === currentAppIcon) ??
+
//appIconSets.core.find(i => i.id === currentAppIcon) ??
appIconSets.defaults[0]
)
}, [appIconSets, currentAppIcon])
+2 -1
package.json
···
"babel-plugin-transform-remove-console": "^6.9.4",
"bcp-47": "^2.1.0",
"bcp-47-match": "^2.0.3",
-
"culori": "^4.0.2",
"date-fns": "^2.30.0",
"email-validator": "^2.0.4",
"emoji-mart": "^5.5.2",
···
"@sentry/webpack-plugin": "^3.2.2",
"@testing-library/jest-native": "^5.4.3",
"@testing-library/react-native": "^13.2.0",
"@types/culori": "^4.0.1",
"@types/jest": "29.5.14",
"@types/lodash.chunk": "^4.2.7",
···
"babel-plugin-transform-remove-console": "^6.9.4",
"bcp-47": "^2.1.0",
"bcp-47-match": "^2.0.3",
+
"chroma-js": "^3.2.0",
"date-fns": "^2.30.0",
"email-validator": "^2.0.4",
"emoji-mart": "^5.5.2",
···
"@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",
+6 -13
src/alf/index.tsx
···
import React from 'react'
import {createTheme, type Theme, type ThemeName} from '@bsky.app/alf'
-
import {formatHex, modeOklch, useMode as utilMode} from 'culori'
import {useThemePrefs} from '#/state/shell/color-mode'
import {
···
export type SchemeType = typeof themes
-
function changeHue(color: string, hueShift: number) {
-
if (!hueShift || hueShift === 0) return color
-
let lablch = utilMode(modeOklch)
-
const parsed = lablch(color)
-
if (!parsed) return color
-
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})
}
export function shiftPalette(palette: Palette, hueShift: number): Palette {
···
import React from 'react'
import {createTheme, type Theme, type ThemeName} from '@bsky.app/alf'
+
import chroma from 'chroma-js'
import {useThemePrefs} from '#/state/shell/color-mode'
import {
···
export type SchemeType = typeof themes
+
export function changeHue(colorStr: string, hueShift: number) {
+
if (!hueShift || hueShift === 0) return colorStr
+
const color = chroma(colorStr).oklch()
+
const newHue = (color[2] + hueShift + 360) % 360
+
return chroma.oklch(color[0], color[1], newHue).hex()
}
export function shiftPalette(palette: Palette, hueShift: number): Palette {
+28 -4
src/components/forms/Slider.tsx
···
import {type ViewStyle} from 'react-native'
import {Slider as RNSlider} from '@miblanchard/react-native-slider'
-
import {useTheme} from '#/alf'
interface SliderProps {
value: number
···
minimumTrackStyle?: ViewStyle
thumbStyle?: ViewStyle
thumbTouchSize?: {width: number; height: number}
}
export function Slider({
···
minimumTrackStyle,
thumbStyle,
thumbTouchSize = {width: 40, height: 40},
}: SliderProps) {
const t = useTheme()
return (
<RNSlider
-
value={[value]} // always an array
-
onValueChange={values => onValueChange(values[0])}
minimumValue={minimumValue}
maximumValue={maximumValue}
step={step}
···
minimumTrackStyle={{
height: 4,
borderRadius: 2,
-
backgroundColor: t.palette.primary_500,
...minimumTrackStyle,
}}
thumbStyle={{
···
+
import {useEffect, useState} from 'react'
import {type ViewStyle} from 'react-native'
import {Slider as RNSlider} from '@miblanchard/react-native-slider'
+
import {changeHue, useTheme} from '#/alf'
interface SliderProps {
value: number
···
minimumTrackStyle?: ViewStyle
thumbStyle?: ViewStyle
thumbTouchSize?: {width: number; height: number}
+
debounceFull?: boolean
}
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 (
<RNSlider
+
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}
···
minimumTrackStyle={{
height: 4,
borderRadius: 2,
+
backgroundColor: changeHue(t.palette.primary_500, localValue - value),
...minimumTrackStyle,
}}
thumbStyle={{
+1
src/screens/Settings/AppearanceSettings.tsx
···
minimumValue={0}
maximumValue={360}
step={1}
/>
</View>
</SettingsList.Group>
···
minimumValue={0}
maximumValue={360}
step={1}
+
debounceFull={true}
/>
</View>
</SettingsList.Group>
+10 -5
yarn.lock
···
dependencies:
"@types/node" "*"
"@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"
···
resolved "https://registry.yarnpkg.com/chownr/-/chownr-3.0.0.tgz#9855e64ecd240a9cc4267ce8a4aa5d24a1da15e4"
integrity sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==
chrome-launcher@^0.15.2:
version "0.15.2"
resolved "https://registry.yarnpkg.com/chrome-launcher/-/chrome-launcher-0.15.2.tgz#4e6404e32200095fdce7f6a1e1004f9bd36fa5da"
···
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"
···
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"
···
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"
···
resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.2.tgz#1d4bf9d572f11c14031f0436e1c10bc1f571f50b"
integrity sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==
data-urls@^3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-3.0.2.tgz#9cf24a477ae22bcef5cd5f6f0bfbc1d2d3be9143"