- prevent crash from opening appearance
- replace culori with chroma-js
+1
-1
src/screens/Settings/AppIconSettings/useCurrentAppIcon.ts
+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
+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
+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
+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
+1
src/screens/Settings/AppearanceSettings.tsx
+10
-5
yarn.lock
+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"