about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorHailey <me@haileyok.com>2024-12-06 09:52:08 -0800
committerGitHub <noreply@github.com>2024-12-06 17:52:08 +0000
commit1f6acc11abec91972e6e04abd55e09b2a9dc1433 (patch)
tree3d6a9b1e8a3aa6f06a4700e9b40519439fcb37da /src
parent3ab6c435df5dc3d17fe3e2531231ccf012a4860c (diff)
downloadvoidsky-1f6acc11abec91972e6e04abd55e09b2a9dc1433.tar.zst
clean rn 0.76 upgrade (#6887)
* package upgrades

* upgrade system ui

* update patches

* rename patch

* rm

* use .set/.set

* resolve yarnlock

* fix accidentally removed package

* fix use permissions hook

* fix some type errors

* type fixes

* more tweaking

* clean

* Discard changes to src/screens/Onboarding/StepProfile/index.tsx

* oops

* fix splash

* use ios/android in config

* Fix tests

* add back patch

* add to rn patch

* fullscreen?

* Revert "add to rn patch"

This reverts commit 4716d2c643a29fc77b871ca8555d8d78cb4ac427.

* try this

* test with revert

* test

* maybe this

* fix config

* Bump @react-native-picker/picker

* Bump some packages

* Rm unused

* Update lockfile

* Rename expo-notifications+0.29.8.patch.md to expo-notifications+0.29.10.patch.md

* Update react-native+0.76.3.patch.md

* Update react-native+0.76.3.patch.md

* Inline splash configs

Jumping around the file is annoying and makes it harder to understand how this is structured.

* Start fixing Android splash

* Downgrade compressor

This version isn't building for me due to https://github.com/numandev1/react-native-compressor/issues/322.

* Make Android splash empty for now

* Work around a bug

* Bump the compressor

* Bump again

* Include splash fixes

* Try updating

* No custom Android splash

* Revert to using icons

* welp

* Fix sizes

* Make sizing work

* Bump size

---------

Co-authored-by: Dan Abramov <dan.abramov@gmail.com>
Diffstat (limited to 'src')
-rw-r--r--src/Splash.android.tsx17
-rw-r--r--src/alf/atoms.ts1
-rw-r--r--src/components/Button.tsx73
-rw-r--r--src/components/GradientFill.tsx10
-rw-r--r--src/components/LinearGradientBackground.tsx6
-rw-r--r--src/components/StarterPack/QrCode.tsx1
-rw-r--r--src/lib/hooks/useNotificationHandler.ts12
-rw-r--r--src/lib/hooks/usePermissions.ts4
-rw-r--r--src/view/com/composer/photos/Gallery.tsx6
-rw-r--r--src/view/com/util/forms/Button.tsx1
-rw-r--r--src/view/com/util/forms/DropdownButton.tsx2
-rw-r--r--src/view/com/util/forms/NativeDropdown.web.tsx1
12 files changed, 93 insertions, 41 deletions
diff --git a/src/Splash.android.tsx b/src/Splash.android.tsx
new file mode 100644
index 000000000..a12b52b8b
--- /dev/null
+++ b/src/Splash.android.tsx
@@ -0,0 +1,17 @@
+import {useEffect} from 'react'
+import * as SplashScreen from 'expo-splash-screen'
+
+type Props = {
+  isReady: boolean
+}
+
+export function Splash({isReady, children}: React.PropsWithChildren<Props>) {
+  useEffect(() => {
+    if (isReady) {
+      SplashScreen.hideAsync()
+    }
+  }, [isReady])
+  if (isReady) {
+    return children
+  }
+}
diff --git a/src/alf/atoms.ts b/src/alf/atoms.ts
index 0870c5767..ad4929ec8 100644
--- a/src/alf/atoms.ts
+++ b/src/alf/atoms.ts
@@ -68,6 +68,7 @@ export const atoms = {
    * Used for the outermost components on screens, to ensure that they can fill
    * the screen and extend beyond.
    */
+  // @ts-ignore - web only minHeight string
   util_screen_outer: [
     web({
       minHeight: '100vh',
diff --git a/src/components/Button.tsx b/src/components/Button.tsx
index 3329dca05..871c17ed5 100644
--- a/src/components/Button.tsx
+++ b/src/components/Button.tsx
@@ -405,37 +405,47 @@ export const Button = React.forwardRef<View, ButtonProps>(
       }
     }, [t, variant, color, size, shape, disabled])
 
-    const {gradientColors, gradientHoverColors, gradientLocations} =
-      React.useMemo(() => {
-        const colors: string[] = []
-        const hoverColors: string[] = []
-        const locations: number[] = []
-        const gradient = {
-          primary: tokens.gradients.sky,
-          secondary: tokens.gradients.sky,
-          secondary_inverted: tokens.gradients.sky,
-          negative: tokens.gradients.sky,
-          gradient_primary: tokens.gradients.primary,
-          gradient_sky: tokens.gradients.sky,
-          gradient_midnight: tokens.gradients.midnight,
-          gradient_sunrise: tokens.gradients.sunrise,
-          gradient_sunset: tokens.gradients.sunset,
-          gradient_nordic: tokens.gradients.nordic,
-          gradient_bonfire: tokens.gradients.bonfire,
-        }[color || 'primary']
-
-        if (variant === 'gradient') {
-          colors.push(...gradient.values.map(([_, color]) => color))
-          hoverColors.push(...gradient.values.map(_ => gradient.hover_value))
-          locations.push(...gradient.values.map(([location, _]) => location))
+    const gradientValues = React.useMemo(() => {
+      const gradient = {
+        primary: tokens.gradients.sky,
+        secondary: tokens.gradients.sky,
+        secondary_inverted: tokens.gradients.sky,
+        negative: tokens.gradients.sky,
+        gradient_primary: tokens.gradients.primary,
+        gradient_sky: tokens.gradients.sky,
+        gradient_midnight: tokens.gradients.midnight,
+        gradient_sunrise: tokens.gradients.sunrise,
+        gradient_sunset: tokens.gradients.sunset,
+        gradient_nordic: tokens.gradients.nordic,
+        gradient_bonfire: tokens.gradients.bonfire,
+      }[color || 'primary']
+
+      if (variant === 'gradient') {
+        if (gradient.values.length < 2) {
+          throw new Error(
+            'Gradient buttons must have at least two colors in the gradient',
+          )
         }
 
         return {
-          gradientColors: colors,
-          gradientHoverColors: hoverColors,
-          gradientLocations: locations,
+          colors: gradient.values.map(([_, color]) => color) as [
+            string,
+            string,
+            ...string[],
+          ],
+          hoverColors: gradient.values.map(_ => gradient.hover_value) as [
+            string,
+            string,
+            ...string[],
+          ],
+          locations: gradient.values.map(([location, _]) => location) as [
+            number,
+            number,
+            ...number[],
+          ],
         }
-      }, [variant, color])
+      }
+    }, [variant, color])
 
     const context = React.useMemo<ButtonContext>(
       () => ({
@@ -458,6 +468,7 @@ export const Button = React.forwardRef<View, ButtonProps>(
         // @ts-ignore - this will always be a pressable
         ref={ref}
         aria-label={label}
+        aria-pressed={state.pressed}
         accessibilityLabel={label}
         disabled={disabled || false}
         accessibilityState={{
@@ -478,7 +489,7 @@ export const Button = React.forwardRef<View, ButtonProps>(
         onHoverOut={onHoverOut}
         onFocus={onFocus}
         onBlur={onBlur}>
-        {variant === 'gradient' && (
+        {variant === 'gradient' && gradientValues && (
           <View
             style={[
               a.absolute,
@@ -489,10 +500,10 @@ export const Button = React.forwardRef<View, ButtonProps>(
             <LinearGradient
               colors={
                 state.hovered || state.pressed
-                  ? gradientHoverColors
-                  : gradientColors
+                  ? gradientValues.hoverColors
+                  : gradientValues.colors
               }
-              locations={gradientLocations}
+              locations={gradientValues.locations}
               start={{x: 0, y: 0}}
               end={{x: 1, y: 1}}
               style={[a.absolute, a.inset_0]}
diff --git a/src/components/GradientFill.tsx b/src/components/GradientFill.tsx
index fa39577d4..3dff404d7 100644
--- a/src/components/GradientFill.tsx
+++ b/src/components/GradientFill.tsx
@@ -14,10 +14,16 @@ export function GradientFill({
     | typeof tokens.gradients.summer
     | typeof tokens.gradients.nordic
 }) {
+  if (gradient.values.length < 2) {
+    throw new Error('Gradient must have at least 2 colors')
+  }
+
   return (
     <LinearGradient
-      colors={gradient.values.map(c => c[1])}
-      locations={gradient.values.map(c => c[0])}
+      colors={gradient.values.map(c => c[1]) as [string, string, ...string[]]}
+      locations={
+        gradient.values.map(c => c[0]) as [number, number, ...number[]]
+      }
       start={{x: 0, y: 0}}
       end={{x: 1, y: 1}}
       style={[a.absolute, a.inset_0]}
diff --git a/src/components/LinearGradientBackground.tsx b/src/components/LinearGradientBackground.tsx
index f516b19f5..724df43f3 100644
--- a/src/components/LinearGradientBackground.tsx
+++ b/src/components/LinearGradientBackground.tsx
@@ -13,7 +13,11 @@ export function LinearGradientBackground({
 }) {
   const gradient = gradients.sky.values.map(([_, color]) => {
     return color
-  })
+  }) as [string, string, ...string[]]
+
+  if (gradient.length < 2) {
+    throw new Error('Gradient must have at least 2 colors')
+  }
 
   return (
     <LinearGradient colors={gradient} style={style}>
diff --git a/src/components/StarterPack/QrCode.tsx b/src/components/StarterPack/QrCode.tsx
index c6408109b..515a9059a 100644
--- a/src/components/StarterPack/QrCode.tsx
+++ b/src/components/StarterPack/QrCode.tsx
@@ -1,5 +1,6 @@
 import React from 'react'
 import {View} from 'react-native'
+// @ts-expect-error missing types
 import QRCode from 'react-native-qrcode-styled'
 import type ViewShot from 'react-native-view-shot'
 import {AppBskyGraphDefs, AppBskyGraphStarterpack} from '@atproto/api'
diff --git a/src/lib/hooks/useNotificationHandler.ts b/src/lib/hooks/useNotificationHandler.ts
index 625ec9e6a..69ae536d0 100644
--- a/src/lib/hooks/useNotificationHandler.ts
+++ b/src/lib/hooks/useNotificationHandler.ts
@@ -177,7 +177,14 @@ export function useNotificationsHandler() {
 
     Notifications.setNotificationHandler({
       handleNotification: async e => {
-        if (e.request.trigger.type !== 'push') return DEFAULT_HANDLER_OPTIONS
+        if (
+          e.request.trigger == null ||
+          typeof e.request.trigger !== 'object' ||
+          !('type' in e.request.trigger) ||
+          e.request.trigger.type !== 'push'
+        ) {
+          return DEFAULT_HANDLER_OPTIONS
+        }
 
         logger.debug(
           'Notifications: received',
@@ -220,6 +227,9 @@ export function useNotificationsHandler() {
 
         if (
           e.actionIdentifier === Notifications.DEFAULT_ACTION_IDENTIFIER &&
+          e.notification.request.trigger != null &&
+          typeof e.notification.request.trigger === 'object' &&
+          'type' in e.notification.request.trigger &&
           e.notification.request.trigger.type === 'push'
         ) {
           logger.debug(
diff --git a/src/lib/hooks/usePermissions.ts b/src/lib/hooks/usePermissions.ts
index 6da14232f..af4358c78 100644
--- a/src/lib/hooks/usePermissions.ts
+++ b/src/lib/hooks/usePermissions.ts
@@ -1,5 +1,5 @@
 import {Linking} from 'react-native'
-import {Camera} from 'expo-camera/legacy' // TODO: Migrate to the new one.
+import {useCameraPermissions as useExpoCameraPermissions} from 'expo-camera'
 import * as MediaLibrary from 'expo-media-library'
 
 import {isWeb} from '#/platform/detection'
@@ -78,7 +78,7 @@ export function useVideoLibraryPermission() {
 }
 
 export function useCameraPermission() {
-  const [res, requestPermission] = Camera.useCameraPermissions()
+  const [res, requestPermission] = useExpoCameraPermissions()
 
   const requestCameraAccessIfNeeded = async () => {
     if (res?.granted) {
diff --git a/src/view/com/composer/photos/Gallery.tsx b/src/view/com/composer/photos/Gallery.tsx
index af784b4f6..bc18c81f1 100644
--- a/src/view/com/composer/photos/Gallery.tsx
+++ b/src/view/com/composer/photos/Gallery.tsx
@@ -124,7 +124,7 @@ type GalleryItemProps = {
   image: ComposerImage
   altTextControlStyle?: ViewStyle
   imageControlsStyle?: ViewStyle
-  imageStyle?: ViewStyle
+  imageStyle?: ImageStyle
   onChange: (next: ComposerImage) => void
   onRemove: () => void
 }
@@ -160,7 +160,7 @@ const GalleryItem = ({
 
   return (
     <View
-      style={imageStyle}
+      style={imageStyle as ViewStyle}
       // Fixes ALT and icons appearing with half opacity when the post is inactive
       renderToHardwareTextureAndroid>
       <TouchableOpacity
@@ -221,7 +221,7 @@ const GalleryItem = ({
 
       <Image
         testID="selectedPhotoImage"
-        style={[styles.image, imageStyle] as ImageStyle}
+        style={[styles.image, imageStyle]}
         source={{
           uri: (image.transformed ?? image.source).path,
         }}
diff --git a/src/view/com/util/forms/Button.tsx b/src/view/com/util/forms/Button.tsx
index 62ef2c4f1..96b49a003 100644
--- a/src/view/com/util/forms/Button.tsx
+++ b/src/view/com/util/forms/Button.tsx
@@ -31,6 +31,7 @@ export type ButtonType =
 // Augment type for react-native-web (see https://github.com/necolas/react-native-web/issues/1684#issuecomment-766451866)
 declare module 'react-native' {
   interface PressableStateCallbackType {
+    // @ts-ignore web only
     hovered?: boolean
     focused?: boolean
   }
diff --git a/src/view/com/util/forms/DropdownButton.tsx b/src/view/com/util/forms/DropdownButton.tsx
index f0751e45b..6cb4b9557 100644
--- a/src/view/com/util/forms/DropdownButton.tsx
+++ b/src/view/com/util/forms/DropdownButton.tsx
@@ -87,7 +87,7 @@ export function DropdownButton({
 }: PropsWithChildren<DropdownButtonProps>) {
   const {_} = useLingui()
 
-  const ref1 = useRef<TouchableOpacity>(null)
+  const ref1 = useRef<View>(null)
   const ref2 = useRef<View>(null)
 
   const onPress = (e: GestureResponderEvent) => {
diff --git a/src/view/com/util/forms/NativeDropdown.web.tsx b/src/view/com/util/forms/NativeDropdown.web.tsx
index 364e10d10..c1a0b8096 100644
--- a/src/view/com/util/forms/NativeDropdown.web.tsx
+++ b/src/view/com/util/forms/NativeDropdown.web.tsx
@@ -229,6 +229,7 @@ const getKey = (label: string, index: number, id?: string) => {
   return `${label}_${index}`
 }
 
+// @ts-expect-error - web only styles. the only style that should be broken here is `outline`
 const styles = StyleSheet.create({
   separator: {
     height: 1,