Skip to content
Merged
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 docs/pages/tutorial/gestures.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ Let's learn what the above code does:

In the previous step, we triggered the `onStart()` callback for the tap gesture chained to the `Gesture.Tap()` method. For the pan gesture, specify an `onChange()` callback, which runs when the gesture is active and moving.

1. Create a `drag` object to handle the pan gesture. The `onChange()` callback accepts `event` as a parameter. `changeX` and `changeY` properties hold the change in position since the last event. and update the values stored in `translateX` and `translateY`.
1. Create a `drag` object to handle the pan gesture. The `onChange()` callback accepts `event` as a parameter. `changeX` and `changeY` properties hold the change in position since the last event and update the values stored in `translateX` and `translateY`.
2. Define the `containerStyle` object using the `useAnimatedStyle()` hook. It will return an array of transforms. For the `<Animated.View>` component, we need to set the `transform` property to the `translateX` and `translateY` values. This will change the sticker's position when the gesture is active.

```tsx components/EmojiSticker.tsx
Expand Down
28 changes: 14 additions & 14 deletions docs/pages/versions/unversioned/sdk/audio.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import { PlatformTags } from '~/ui/components/Tag/PlatformTags';

The [Android media format support documentation](https://developer.android.com/media/media3/exoplayer/supported-formats) covers formats supported when using Expo Player on Android. The [iOS audio and video format documentation](https://developer.apple.com/documentation/coreaudiotypes/audio-format-identifiers) lists supported media formats for Apple devices.

Note that audio automatically stops if headphones/bluetooth audio devices are disconnected.
Note that audio automatically stops if headphones/Bluetooth audio devices are disconnected.

## Installation

Expand Down Expand Up @@ -195,7 +195,7 @@ const styles = StyleSheet.create({

</SnackInline>

### Playing audio in background
### Playing audio in the background

Background audio playback allows your app to continue playing audio when it moves to the background or when the device screen locks.

Expand Down Expand Up @@ -280,12 +280,12 @@ export default function AudioPlayerScreen() {

<PlatformTags platforms={['android']} />

- > **Note**: On Android, you have to enable the lockscreen controls with [`setActiveForLockScreen`](#setactiveforlockscreenactive-metadata-options) for sustained background playback. Otherwise, the audio will stop after approximately 3 minutes of background playback (OS limitation). Make sure to also appropriately [configure the config-plugin](#configuration-in-app-config)
> **Note**: On Android, you have to enable the lock screen controls with [`setActiveForLockScreen`](#setactiveforlockscreenactive-metadata-options) for sustained background playback. Otherwise, the audio will stop after approximately 3 minutes of background playback (OS limitation). Ensure to appropriately [configure the config plugin](#configuration-in-app-config).

* A media notification appears in the notification drawer with playback controls
* Audio continues playing indefinitely in the background
* Users can control playback from the lock screen and notification
* The foreground service keeps the playback alive during playback
- A media notification appears in the notification drawer with playback controls
- Audio continues playing indefinitely in the background
- Users can control playback from the lock screen and notification
- The foreground service keeps the playback alive during playback

<PlatformTags platforms={['ios']} />

Expand Down Expand Up @@ -325,7 +325,7 @@ If you're not using Continuous Native Generation ([CNG](/workflow/continuous-nat

</ConfigReactNative>

### Recording audio in background
### Recording audio in the background

> **warning** Background recording can significantly impact battery life. Only enable it when necessary for your app's functionality.

Expand All @@ -352,13 +352,13 @@ To enable background recording, use the config plugin in your [app config](/work
The above configuration automatically configures the required native settings:

- <PlatformTags platforms={['android']} /> Adds `FOREGROUND_SERVICE`,
`FOREGROUND_SERVICE_MICROPHONE` and `POST_NOTIFICATIONS` permissions. Also declares an audio
recording foreground service in app's `AndroidManifest.xml`.
`FOREGROUND_SERVICE_MICROPHONE`, and `POST_NOTIFICATIONS` permissions. Also declares an audio
recording foreground service in app's **AndroidManifest.xml**.
- <PlatformTags platforms={['ios']} /> Adds the `audio` `UIBackgroundMode` capability

<ConfigReactNative>

If you're not using Continuous Native Generation ([CNG](/workflow/continuous-native-generation/)) (you're using native **android** and **ios** projects manually), then you need to configure following permissions in your native projects:
If you're not using Continuous Native Generation ([CNG](/workflow/continuous-native-generation/)) (you're using native **android** and **ios** projects manually), then you need to configure the following permissions in your native projects:

- For Android, add to **android/app/src/main/AndroidManifest.xml**:

Expand Down Expand Up @@ -408,8 +408,8 @@ On iOS, background recording continues seamlessly when the app is in the backgro

### Using the AudioPlayer directly

In most cases, the [`useAudioPlayer`](#useaudioplayersource-options) hook should be used to create a `AudioPlayer` instance. It manages the player's lifecycle and ensures that it is properly disposed of when the component is unmounted. However, in some advanced use cases, it might be necessary to create a `AudioPlayer` that does not get automatically destroyed when the component is unmounted.
In those cases, the `AudioPlayer` can be created using the [`createAudioPlayer`](#audiocreateaudioplayersource-options) function. You need to be aware of the risks that come with this approach, as it is your responsibility to call the [`release()`](../sdk/expo/#release) method when the player is no longer needed. If not handled properly, this approach may lead to memory leaks.
In most cases, use the [`useAudioPlayer`](#useaudioplayersource-options) hook to create an `AudioPlayer` instance. It manages the player's lifecycle and ensures proper disposal when the component unmounts. However, in some advanced use cases, you may need to create an `AudioPlayer` that persists beyond the component's lifecycle.
In those cases, use the [`createAudioPlayer`](#audiocreateaudioplayersource-options) function. You need to be aware of the risks that come with this approach, as it is your responsibility to call the [`release()`](../sdk/expo/#release) method when the player is no longer needed. If not handled properly, this approach may lead to memory leaks.

```tsx
import { createAudioPlayer } from 'expo-audio';
Expand All @@ -419,7 +419,7 @@ const player = createAudioPlayer(audioSource);
### Notes on web usage

- A MediaRecorder issue on Chrome produces WebM files missing the duration metadata. [See the open Chromium issue](https://bugs.chromium.org/p/chromium/issues/detail?id=642012).
- MediaRecorder encoding options and other configurations are inconsistent across browsers, utilizing a Polyfill such as [kbumsik/opus-media-recorder](https://github.com/kbumsik/opus-media-recorder) or [ai/audio-recorder-polyfill](https://github.com/ai/audio-recorder-polyfill) in your application will improve your experience. Any options passed to `prepareToRecordAsync` will be passed directly to the MediaRecorder API and as such the polyfill.
- MediaRecorder encoding options and other configurations are inconsistent across browsers. Using a polyfill such as [kbumsik/opus-media-recorder](https://github.com/kbumsik/opus-media-recorder) or [ai/audio-recorder-polyfill](https://github.com/ai/audio-recorder-polyfill) in your application will improve your experience. Any options passed to `prepareToRecordAsync` will be passed directly to the MediaRecorder API and as such the polyfill.
- Web browsers require sites to be served securely for them to listen to a mic. See [MediaDevices `getUserMedia()` security](https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia#security) for more details.

## API
Expand Down
68 changes: 64 additions & 4 deletions docs/pages/versions/unversioned/sdk/ui/swift-ui/host.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,14 @@ Since the `Host` component is a React Native [`View`](https://reactnative.dev/do

## Usage

```tsx Wrapping Button in Host
### Match contents sizing

Use `matchContents` to let the `Host` automatically size itself to fit its SwiftUI content, instead of requiring explicit dimensions.

```tsx MatchContentsExample.tsx
import { Button, Host } from '@expo/ui/swift-ui';

function Example() {
export default function MatchContentsExample() {
return (
<Host matchContents>
<Button
Expand All @@ -36,10 +40,14 @@ function Example() {
}
```

```tsx Host with flexbox and VStack
### Explicit sizing with style

Use `style` to set explicit sizes on the `Host`, such as filling the available space with `flex: 1`.

```tsx ExplicitSizingExample.tsx
import { Button, Host, VStack, Text } from '@expo/ui/swift-ui';

function Example() {
export default function ExplicitSizingExample() {
return (
<Host style={{ flex: 1 }}>
<VStack spacing={8}>
Expand All @@ -56,6 +64,58 @@ function Example() {
}
```

### Ignoring keyboard safe area

Use `ignoreSafeArea="keyboard"` when React Native is already handling keyboard avoidance (for example, with `react-native-keyboard-controller`), to prevent the SwiftUI host from applying its own keyboard inset.

```tsx IgnoreKeyboardExample.tsx
import { Host, TextField } from '@expo/ui/swift-ui';
import { KeyboardProvider, KeyboardStickyView } from 'react-native-keyboard-controller';
import { View } from 'react-native';

export default function IgnoreKeyboardExample() {
return (
<KeyboardProvider>
<View style={{ flex: 1, backgroundColor: 'black' }}>
<KeyboardStickyView
style={{
position: 'absolute',
bottom: 0,
left: 0,
right: 0,
padding: 16,
backgroundColor: 'green',
}}>
<Host matchContents ignoreSafeArea="keyboard" style={{ backgroundColor: 'red' }}>
<TextField placeholder="Enter text" multiline />
</Host>
</KeyboardStickyView>
</View>
</KeyboardProvider>
);
}
```

### Ignoring all safe areas

Use `ignoreSafeArea="all"` when you want SwiftUI content to extend behind the status bar, useful for full-screen overlays or backgrounds.

```tsx IgnoreAllSafeAreasExample.tsx
import { Host, Text, VStack } from '@expo/ui/swift-ui';

export default function IgnoreAllSafeAreasExample() {
return (
<Host
ignoreSafeArea="all"
style={{ position: 'absolute', top: 0, left: 0, right: 0, bottom: 0 }}>
<VStack>
<Text>This content extends behind the status bar and home indicator.</Text>
</VStack>
</Host>
);
}
```

## API

```tsx
Expand Down
14 changes: 7 additions & 7 deletions docs/pages/versions/v55.0.0/sdk/audio.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import { PlatformTags } from '~/ui/components/Tag/PlatformTags';

The [Android media format support documentation](https://developer.android.com/media/media3/exoplayer/supported-formats) covers formats supported when using Expo Player on Android. The [iOS audio and video format documentation](https://developer.apple.com/documentation/coreaudiotypes/audio-format-identifiers) lists supported media formats for Apple devices.

Note that audio automatically stops if headphones/bluetooth audio devices are disconnected.
Note that audio automatically stops if headphones/Bluetooth audio devices are disconnected.

## Installation

Expand Down Expand Up @@ -187,7 +187,7 @@ const styles = StyleSheet.create({

</SnackInline>

### Playing audio in background&ensp;<PlatformTags platforms={['ios']} />
### Playing audio in the background&ensp;<PlatformTags platforms={['ios']} />

On iOS, audio playback and recording in background is only available in standalone apps, and it requires some extra configuration.
On iOS, each background feature requires a special key in `UIBackgroundModes` array in your **Info.plist** file.
Expand All @@ -212,7 +212,7 @@ See an example of **app.json** that enables audio playback in background:
}
```

### Recording audio in background
### Recording audio in the background

> **warning** Background recording can significantly impact battery life. Only enable it when necessary for your app's functionality.

Expand Down Expand Up @@ -244,7 +244,7 @@ The above configuration automatically configures the required native settings:

<ConfigReactNative>

If you're not using Continuous Native Generation ([CNG](/workflow/continuous-native-generation/)) (you're using native **android** and **ios** projects manually), then you need to configure following permissions in your native projects:
If you're not using Continuous Native Generation ([CNG](/workflow/continuous-native-generation/)) (you're using native **android** and **ios** projects manually), then you need to configure the following permissions in your native projects:

- For Android, add to **android/app/src/main/AndroidManifest.xml**:

Expand Down Expand Up @@ -294,8 +294,8 @@ On iOS, background recording continues seamlessly when the app is in the backgro

### Using the AudioPlayer directly

In most cases, the [`useAudioPlayer`](#useaudioplayersource-options) hook should be used to create a `AudioPlayer` instance. It manages the player's lifecycle and ensures that it is properly disposed of when the component is unmounted. However, in some advanced use cases, it might be necessary to create a `AudioPlayer` that does not get automatically destroyed when the component is unmounted.
In those cases, the `AudioPlayer` can be created using the [`createAudioPlayer`](#audiocreateaudioplayersource-options) function. You need to be aware of the risks that come with this approach, as it is your responsibility to call the [`release()`](../sdk/expo/#release) method when the player is no longer needed. If not handled properly, this approach may lead to memory leaks.
In most cases, use the [`useAudioPlayer`](#useaudioplayersource-options) hook to create an `AudioPlayer` instance. It manages the player's lifecycle and ensures proper disposal when the component unmounts. However, in some advanced use cases, you may need to create an `AudioPlayer` that persists beyond the component's lifecycle.
In those cases, use the [`createAudioPlayer`](#audiocreateaudioplayersource-options) function. You need to be aware of the risks that come with this approach, as it is your responsibility to call the [`release()`](../sdk/expo/#release) method when the player is no longer needed. If not handled properly, this approach may lead to memory leaks.

```tsx
import { createAudioPlayer } from 'expo-audio';
Expand All @@ -305,7 +305,7 @@ const player = createAudioPlayer(audioSource);
### Notes on web usage

- A MediaRecorder issue on Chrome produces WebM files missing the duration metadata. [See the open Chromium issue](https://bugs.chromium.org/p/chromium/issues/detail?id=642012).
- MediaRecorder encoding options and other configurations are inconsistent across browsers, utilizing a Polyfill such as [kbumsik/opus-media-recorder](https://github.com/kbumsik/opus-media-recorder) or [ai/audio-recorder-polyfill](https://github.com/ai/audio-recorder-polyfill) in your application will improve your experience. Any options passed to `prepareToRecordAsync` will be passed directly to the MediaRecorder API and as such the polyfill.
- MediaRecorder encoding options and other configurations are inconsistent across browsers. Using a polyfill such as [kbumsik/opus-media-recorder](https://github.com/kbumsik/opus-media-recorder) or [ai/audio-recorder-polyfill](https://github.com/ai/audio-recorder-polyfill) in your application will improve your experience. Any options passed to `prepareToRecordAsync` will be passed directly to the MediaRecorder API and as such the polyfill.
- Web browsers require sites to be served securely for them to listen to a mic. See [MediaDevices `getUserMedia()` security](https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia#security) for more details.

## API
Expand Down
68 changes: 64 additions & 4 deletions docs/pages/versions/v55.0.0/sdk/ui/swift-ui/host.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,14 @@ Since the `Host` component is a React Native [`View`](https://reactnative.dev/do

## Usage

```tsx Wrapping Button in Host
### Match contents sizing

Use `matchContents` to let the `Host` automatically size itself to fit its SwiftUI content, instead of requiring explicit dimensions.

```tsx MatchContentsExample.tsx
import { Button, Host } from '@expo/ui/swift-ui';

function Example() {
export default function MatchContentsExample() {
return (
<Host matchContents>
<Button
Expand All @@ -36,10 +40,14 @@ function Example() {
}
```

```tsx Host with flexbox and VStack
### Explicit sizing with style

Use `style` to set explicit sizes on the `Host`, such as filling the available space with `flex: 1`.

```tsx ExplicitSizingExample.tsx
import { Button, Host, VStack, Text } from '@expo/ui/swift-ui';

function Example() {
export default function ExplicitSizingExample() {
return (
<Host style={{ flex: 1 }}>
<VStack spacing={8}>
Expand All @@ -56,6 +64,58 @@ function Example() {
}
```

### Ignoring keyboard safe area

Use `ignoreSafeArea="keyboard"` when React Native is already handling keyboard avoidance (for example, with `react-native-keyboard-controller`), to prevent the SwiftUI host from applying its own keyboard inset.

```tsx IgnoreKeyboardExample.tsx
import { Host, TextField } from '@expo/ui/swift-ui';
import { KeyboardProvider, KeyboardStickyView } from 'react-native-keyboard-controller';
import { View } from 'react-native';

export default function IgnoreKeyboardExample() {
return (
<KeyboardProvider>
<View style={{ flex: 1, backgroundColor: 'black' }}>
<KeyboardStickyView
style={{
position: 'absolute',
bottom: 0,
left: 0,
right: 0,
padding: 16,
backgroundColor: 'green',
}}>
<Host matchContents ignoreSafeArea="keyboard" style={{ backgroundColor: 'red' }}>
<TextField placeholder="Enter text" multiline />
</Host>
</KeyboardStickyView>
</View>
</KeyboardProvider>
);
}
```

### Ignoring all safe areas

Use `ignoreSafeArea="all"` when you want SwiftUI content to extend behind the status bar, useful for full-screen overlays or backgrounds.

```tsx IgnoreAllSafeAreasExample.tsx
import { Host, Text, VStack } from '@expo/ui/swift-ui';

export default function IgnoreAllSafeAreasExample() {
return (
<Host
ignoreSafeArea="all"
style={{ position: 'absolute', top: 0, left: 0, right: 0, bottom: 0 }}>
<VStack>
<Text>This content extends behind the status bar and home indicator.</Text>
</VStack>
</Host>
);
}
```

## API

```tsx
Expand Down
2 changes: 1 addition & 1 deletion docs/public/static/data/unversioned/expo-audio.json

Large diffs are not rendered by default.

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion docs/public/static/data/v55.0.0/expo-audio.json

Large diffs are not rendered by default.

Loading
Loading