Skip to content
Merged
2 changes: 2 additions & 0 deletions .changeset/poor-lamps-share.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
---
---
19 changes: 19 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Project instructions

## Changesets

This repo uses [changesets](https://github.com/changesets/changesets), and a
changeset-bot check runs on every PR.

- If a PR changes a **published package** (anything under `modules/`), add a
changeset describing the change and its semver bump (`npx changeset`).
- If a PR's changes are confined to **non-published workspaces** (e.g. the
`example-app` in `apps/`, docs, CI config), no version bump is needed — but
the changeset check still requires a changeset to be present. In that case add
an **empty changeset** so the check passes without bumping any package:

```sh
npx changeset --empty
```

Commit the generated `.changeset/*.md` file along with the PR.
39 changes: 27 additions & 12 deletions apps/ExampleApp/app/screens/HomeScreen/HomeScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { observer } from "mobx-react-lite"
import { ViewStyle, FlatList, View } from "react-native"
import { NativeStackScreenProps } from "@react-navigation/native-stack"
import { AppStackScreenProps } from "app/navigators"
import { Text } from "app/components"
import { Screen, Text } from "app/components"
import { DEMO_LIST, DemoInfo } from "./demoInfo"
import { DemoListItem } from "./components/DemoListItem"
import { useTypedNavigation } from "../../navigators/useTypedNavigation"
Expand All @@ -27,22 +27,37 @@ export const HomeScreen: FC<HomeScreenProps> = observer(function HomeScreen() {
[navigation],
)

// Use a "fixed" preset so the FlatList does its own scrolling — a
// VirtualizedList must not be nested inside the ScrollView that the
// "scroll" preset would provide.
return (
<FlatList
ListHeaderComponent={
<View style={$shadowSpace}>
<View style={$titleContainer}>
<Text preset={"heading"} text={"Infinite Red AI"} />
<Screen
preset="fixed"
contentContainerStyle={$screenContentContainer}
safeAreaEdges={["top", "bottom"]}
>
<FlatList
ListHeaderComponent={
<View style={$shadowSpace}>
<View style={$titleContainer}>
<Text preset={"heading"} text={"Infinite Red AI"} />
</View>
</View>
</View>
}
data={DEMO_LIST}
renderItem={renderItem}
contentContainerStyle={$contentContainerStyle}
/>
}
data={DEMO_LIST}
renderItem={renderItem}
style={$list}
contentContainerStyle={$contentContainerStyle}
/>
</Screen>
)
})

// Let the inner container fill the screen so the FlatList can size itself.
const $screenContentContainer: ViewStyle = { flex: 1 }

const $list: ViewStyle = { flex: 1 }

const $shadowSpace: ViewStyle = {
paddingBottom: 4,
backgroundColor: "rgba(0,0,0,0)",
Expand Down
19 changes: 17 additions & 2 deletions apps/ExampleApp/app/utils/useExampleImage/useExampleImage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
ImagePickerOptions,
ImagePickerAsset,
useCameraPermissions,
UIImagePickerPresentationStyle,
} from "expo-image-picker"
import { useCallback, useState, useMemo } from "react"
import { useAssets, Asset } from "expo-asset"
Expand Down Expand Up @@ -61,6 +62,20 @@ const IMAGE_PICKER_OPTIONS: ImagePickerOptions = {
quality: 0.5,
}

// The photo library picker presents as a card sheet (iOS) instead of the
// default full-screen presentation, whose nav bar renders under the status
// bar / Dynamic Island.
const LIBRARY_PICKER_OPTIONS: ImagePickerOptions = {
...IMAGE_PICKER_OPTIONS,
presentationStyle: UIImagePickerPresentationStyle.PAGE_SHEET,
}

// The camera stays full-screen, which is the conventional capture experience.
const CAMERA_PICKER_OPTIONS: ImagePickerOptions = {
...IMAGE_PICKER_OPTIONS,
presentationStyle: UIImagePickerPresentationStyle.FULL_SCREEN,
}

export function useExampleImage(predicates?: {
filter?: ImageFilter
groupBy?: ImageGrouper
Expand Down Expand Up @@ -110,7 +125,7 @@ export function useExampleImage(predicates?: {

const selectPhoto = useCallback(async () => {
setStatus("selectingPhoto")
const result: ImagePickerResult = await launchImageLibraryAsync(IMAGE_PICKER_OPTIONS)
const result: ImagePickerResult = await launchImageLibraryAsync(LIBRARY_PICKER_OPTIONS)
if (result.assets?.[0]) {
setImage({ ...result.assets?.[0], localUri: result.assets?.[0].uri } as SelectedImage)
} else {
Expand All @@ -127,7 +142,7 @@ export function useExampleImage(predicates?: {
return
}
setStatus("takingPhoto")
const result: ImagePickerResult = await launchCameraAsync(IMAGE_PICKER_OPTIONS)
const result: ImagePickerResult = await launchCameraAsync(CAMERA_PICKER_OPTIONS)
if (result.assets?.[0]) {
setImage({ ...result.assets?.[0], localUri: result.assets?.[0].uri } as SelectedImage)
} else {
Expand Down
Loading