Skip to content

Deploy #1453

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
May 6, 2025
Merged

Deploy #1453

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .node-version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
v20.18.0
v20.19.1
21 changes: 21 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,27 @@ It is acceptable to vary styles to avoid making too many changes at once.

Assume the style is enforced by a linter and formatter.

### Platform-Specific Code

This project uses a platform-specific extension pattern to handle web vs. native differences:

1. **File naming convention**:
- Base component: `ComponentName.tsx` - shared logic or web-specific implementation
- Native override: `ComponentName.native.tsx` - React Native specific implementation

2. **When to create platform-specific files**:
- When UI components need different native implementations
- When using platform-specific APIs or components
- When optimizing for different platform performance characteristics
- When handling platform-specific UX patterns

3. **Example pattern** (TokenActivityFeed):
- Web version uses RecyclerList (virtualized web list)
- Native version uses FlatList (React Native's optimized list)
- Components maintain the same API while using platform-optimized implementations

When developing new features, consider whether platform-specific implementations are needed and follow this established pattern.

### Comments

Focus comments solely on explaining the code's functionality and design choices, not the history of how the code was changed during our session. Ensure final code does not contain comments related to the debugging steps or conversational edits.
Expand Down
4 changes: 2 additions & 2 deletions apps/distributor/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,15 @@
"@supabase/supabase-js": "2.44.2",
"@wagmi/core": "^2.16.7",
"app": "workspace:*",
"express": "^4.19.2",
"express": "^4.20.0",
"pino": "^8.16.1",
"viem": "^2.27.2"
},
"devDependencies": {
"@types/bun": "^1.1.6",
"@types/express": "^4",
"@types/supertest": "^2.0.16",
"debug": "^4.3.6",
"debug": "^4.3.7",
"dotenv-cli": "^7.3.0",
"supertest": "^6.3.3",
"typescript": "^5.8.3"
Expand Down
278 changes: 140 additions & 138 deletions apps/expo/PLAN.md

Large diffs are not rendered by default.

29 changes: 26 additions & 3 deletions apps/expo/app/(auth)/_layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,13 @@ import { Anchor, Container, ScrollView, YStack } from '@my/ui'
import { useLink } from 'solito/link'
import { IconSendLogo } from 'app/components/icons'
import { Slot, Stack } from 'expo-router'
import { useSafeAreaInsets } from 'react-native-safe-area-context'
import { useHeaderHeight } from '@react-navigation/elements'

export default function AuthLayout() {
const { top } = useSafeAreaInsets()
const headerHeight = useHeaderHeight()

return (
<>
<Stack.Screen options={{ headerShown: false }} />
Expand All @@ -16,11 +21,29 @@ export default function AuthLayout() {
}}
flex={1}
>
<YStack ai="center" f={1} position="relative">
<Anchor {...useLink({ href: '/' })} mx="auto" position="absolute" top={'$4'}>
<YStack ai="center" f={1} position="relative" px="$4">
<Anchor
{...useLink({ href: '/' })}
mx="auto"
my="$4"
position="absolute"
top={headerHeight || top || '$4'}
>
<IconSendLogo size={'$4'} color={'$color12'} />
</Anchor>
<ScrollView pt="$2" mt="$14" f={1} contentContainerStyle={{ flexGrow: 1 }}>
<ScrollView
pt="$2"
mt="$14"
f={1}
w="100%"
showsVerticalScrollIndicator={false}
contentContainerStyle={{
flexGrow: 1,
paddingTop: 60, // Space for logo
justifyContent: 'center',
width: '100%',
}}
>
<Slot />
</ScrollView>
</YStack>
Expand Down
2 changes: 1 addition & 1 deletion apps/expo/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
"remove-xcode-env-local-file": "rm ios/.xcode.env.local"
},
"dependencies": {
"@babel/runtime": "^7.18.9",
"@babel/runtime": "^7.26.10",
"@my/ui": "workspace:*",
"@react-native-async-storage/async-storage": "^2.0.0",
"@react-native-community/netinfo": "11.4.1",
Expand Down
2 changes: 1 addition & 1 deletion apps/next/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
"@trpc/server": "^11.1.0",
"app": "workspace:*",
"expo-sharing": "13.0.1",
"next": "15.1.6",
"next": "15.2.4",
"plaiceholder": "^3.0.0",
"raf": "^3.4.1",
"react": "^18.3.1",
Expand Down
186 changes: 186 additions & 0 deletions docs/scroll-direction-provider.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
# ScrollDirectionProvider

The `ScrollDirectionProvider` provides scroll direction tracking and scroll position information for React Native and Next.js applications. It detects whether users are scrolling up or down, and also tracks if they've reached the end of scrollable content.

## Overview

This provider creates a React context that exposes:

1. Current scroll direction (up/down/null)
2. Whether the user has scrolled to the end of content
3. Scroll event handlers to attach to scrollable components
4. A ref for ScrollView (when needed)

## Use Cases

- Show/hide UI elements based on scroll direction (e.g., navigation bars)
- Load more content when user scrolls to the end (infinite scrolling)
- Persist scroll position between route changes (web only)
- Track scroll positions for analytics or user experience improvements

## Basic Usage

### Setup

The provider should be included in your app's provider tree:

```tsx
import { ScrollDirectionProvider } from 'app/provider/scroll'

function App() {
return (
<ScrollDirectionProvider>
{/* Your app components */}
</ScrollDirectionProvider>
)
}
```

### Using the hook

Use the `useScrollDirection` hook to access scroll information:

```tsx
import { useScrollDirection } from 'app/provider/scroll'

function MyComponent() {
const { direction, isAtEnd, onScroll, onContentSizeChange, ref } = useScrollDirection()

// Hide navigation when scrolling down
useEffect(() => {
if (direction === 'down') {
// Hide navigation
} else if (direction === 'up') {
// Show navigation
}
}, [direction])

// Load more content when reaching the end
useEffect(() => {
if (isAtEnd) {
loadMoreContent()
}
}, [isAtEnd])

return (
<ScrollView
ref={ref}
onScroll={onScroll}
onContentSizeChange={onContentSizeChange}
scrollEventThrottle={16} // Recommended for smooth tracking
>
{/* Scrollable content */}
</ScrollView>
)
}
```

## API Reference

### ScrollDirectionProvider

```tsx
<ScrollDirectionProvider>
{children}
</ScrollDirectionProvider>
```

Wraps your application to provide scroll direction context.

### useScrollDirection

```tsx
const {
direction,
isAtEnd,
onScroll,
onContentSizeChange,
ref
} = useScrollDirection()
```

Returns:

| Property | Type | Description |
|----------|------|-------------|
| `direction` | `'up'` \| `'down'` \| `null` | Current scroll direction or `null` if not scrolling |
| `isAtEnd` | `boolean` | `true` if user has scrolled to the end of content |
| `onScroll` | `ScrollViewProps['onScroll']` | Event handler to attach to ScrollView |
| `onContentSizeChange` | `ScrollViewProps['onContentSizeChange']` | Event handler to attach to ScrollView |
| `ref` | `React.RefObject<ScrollView>` | Ref to attach to ScrollView |

## Platform-Specific Behavior

### Web (Next.js)

On web, the provider also:
- Tracks scroll positions by route
- Restores scroll position when navigating between routes
- Uses Next.js router for route tracking

### Native (React Native)

On native, the provider:
- Tracks current scroll direction
- Detects when user has reached end of content
- Does not persist scroll positions between screens (navigation handled differently)

## Examples

### Hiding Bottom Navigation on Scroll

```tsx
import { useScrollDirection } from 'app/provider/scroll'
import { XStack } from 'tamagui'

export const BottomNavBar = () => {
const { direction } = useScrollDirection()

return (
<XStack
bottom={direction === 'down' ? -80 : 0} // Hide when scrolling down
animation="200ms"
animateOnly={['bottom']}
// Other styling props
>
{/* Navigation content */}
</XStack>
)
}
```

### Infinite Scroll Implementation

```tsx
import { useScrollDirection } from 'app/provider/scroll'
import { FlatList } from 'react-native'

export const InfiniteList = ({ fetchNextPage, hasNextPage, isFetchingNextPage, data }) => {
const { isAtEnd } = useScrollDirection()

useEffect(() => {
if (isAtEnd && hasNextPage && !isFetchingNextPage) {
fetchNextPage()
}
}, [isAtEnd, hasNextPage, fetchNextPage, isFetchingNextPage])

return (
<FlatList
data={data}
renderItem={({ item }) => (
// Render items
)}
ListFooterComponent={
isFetchingNextPage ? <LoadingIndicator /> : null
}
/>
)
}
```

## Implementation Notes

- A scroll threshold (default: 50px) determines when to trigger direction changes
- Both component dimensions and scroll offsets are tracked to determine end-of-content
- Performance optimized with refs for frequently changing values
- Context value is memoized to prevent unnecessary re-renders
38 changes: 16 additions & 22 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@
in {
formatter = pkgs.alejandra;

devShells.default = pkgs.mkShell {
devShells.default = pkgs.llvmPackages_17.libcxxStdenv.mkDerivation {
name = "sendapp-dev";
nativeBuildInputs =
[
pkgs.foundry
Expand All @@ -64,30 +65,23 @@
pkgs.unstable.bun
pkgs.unstable.tilt
pkgs.unstable.temporal-cli
]
# macOS-specific tools
pkgs.unstable.ripgrep
] # macOS-specific tools
++ (pkgs.lib.optionals pkgs.stdenv.isDarwin [
pkgs.darwin.apple_sdk.frameworks.CoreServices
pkgs.darwin.apple_sdk.frameworks.CoreFoundation
pkgs.unstable.darwin.xcode_16_3
pkgs.unstable.apple-sdk
pkgs.unstable.darwin.apple_sdk.frameworks.CoreServices
pkgs.unstable.darwin.apple_sdk.frameworks.CoreFoundation
pkgs.unstable.darwin.apple_sdk.frameworks.SystemConfiguration
]);

# For C++ development
buildInputs = [
pkgs.unstable.llvmPackages_17.libcxxStdenv
pkgs.unstable.llvmPackages_17.libcxxClang
pkgs.unstable.llvmPackages_17.compiler-rt
pkgs.unstable.llvmPackages_17.libcxx
];
shellHook = ''
${
if pkgs.stdenv.isDarwin
then ''
# Force using host Xcode instead of Nix-provided one
export PATH=$(echo $PATH | tr ":" "\n" | grep -v "${pkgs.xcbuild or "xcbuild"}/bin" | tr "\n" ":")
unset DEVELOPER_DIR

# Add host tools with higher priority
export PATH=/usr/bin:$PATH

echo "Using host Xcode installation"
''
else ''
# silence is golden
''
}
eval "$(fnm env --use-on-cd --corepack-enabled --shell bash)"
echo "Welcome to the Send.app development environment!"
'';
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
"istanbul-lib-coverage@npm:^3.2.2": "patch:istanbul-lib-coverage@npm%3A3.2.2#~/.yarn/patches/istanbul-lib-coverage-npm-3.2.2-5c0526e059.patch"
},
"dependencies": {
"@babel/runtime": "^7.18.9",
"@babel/runtime": "^7.26.10",
"@manypkg/cli": "^0.19.1",
"@nderscore/tamagui-typescript-plugin": "^0.6.0",
"check-dependency-version-consistency": "^3.0.3",
Expand Down
2 changes: 1 addition & 1 deletion packages/api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
"@trpc/server": "^11.1.0",
"@wagmi/core": "^2.16.7",
"app": "workspace:*",
"debug": "^4.3.6",
"debug": "^4.3.7",
"jsonwebtoken": "^9.0.2",
"ms": "^2.1.3",
"p-queue": "^8.0.1",
Expand Down
6 changes: 3 additions & 3 deletions packages/app/components/icons/IconUSDC.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { ColorTokens } from '@my/ui'
import { type IconProps, themed } from '@tamagui/helpers-icon'
import { memo } from 'react'
import { Defs, G, Path, Rect, Svg } from 'react-native-svg'
import { Defs, G, Path, Rect, Svg, ClipPath } from 'react-native-svg'

const Usdc = (props) => {
const { size, color, ...rest } = props
Expand All @@ -28,9 +28,9 @@ const Usdc = (props) => {
/>
</G>
<Defs>
<clipPath id="clip0_265_2602">
<ClipPath id="clip0_265_2602">
<Rect width="32" height="32" fill="white" />
</clipPath>
</ClipPath>
</Defs>
</Svg>
)
Expand Down
Loading
Loading