Skip to content
Open
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
9 changes: 9 additions & 0 deletions resources/css/app.css
Original file line number Diff line number Diff line change
Expand Up @@ -270,3 +270,12 @@ nav.docs-navigation > ul > li > ul {
.dark .prose code {
@apply bg-gray-800 text-purple-300;
}

.prose table {
@apply w-full;
}

.prose :where(table):not(:where([class~='not-prose'] *)) {
display: block;
overflow-x: auto;
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
id="mobile-dropdown"
>
<x-navbar.device-dropdown-item
href="/docs/mobile/1/getting-started/introduction"
href="/docs/mobile/2/getting-started/introduction"
title="Documentation"
subtitle="Get started with Mobile"
icon="docs"
Expand Down
10 changes: 10 additions & 0 deletions resources/views/docs/index.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@
1 => '1.x',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need context aware filtering in the algolia results. Once this is merged results from 4 versions will show up (desktop & mobile v1 + v2)

2 => '2.x'
]" />
@elseif($platform === 'mobile')
<livewire:version-switcher :versions="[
1 => '1.x',
2 => '2.x'
]" />
@endif

<x-docs.toc-and-sponsors :tableOfContents="$tableOfContents" />
Expand All @@ -30,6 +35,11 @@
1 => '1.x',
2 => '2.x'
]" />
@elseif($platform === 'mobile')
<livewire:version-switcher :versions="[
1 => '1.x',
2 => '2.x'
]" />
@endif

{{-- Copy as Markdown Button --}}
Expand Down
53 changes: 52 additions & 1 deletion resources/views/docs/mobile/1/apis/system.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ order: 800

## Overview

The System API provides access to basic system functions like flashlight control.
The System API provides access to basic system functions like flashlight control, platform detection, and network status monitoring.

```php
use Native\Mobile\Facades\System;
Expand Down Expand Up @@ -34,3 +34,54 @@ Determines if the current device is running iOS.
Determines if the current device is running Android.

**Returns:** `true` if Android, `false` otherwise

### `getNetworkStatus()`

Gets the current network connection status and details.

**Returns:** `?object` containing network information, or `null` if unavailable

```php
$status = System::getNetworkStatus();

if ($status) {
// Check if connected
if ($status->connected) {
echo "Connected via: " . $status->type; // "wifi", "cellular", "ethernet", or "unknown"

// Check if using expensive/metered connection
if ($status->isExpensive) {
echo "Using cellular data - consider limiting usage";
}

// Check if Low Data Mode is enabled (iOS only)
if ($status->isConstrained) {
echo "Low Data Mode is enabled";
}
} else {
echo "No network connection";
}
}
```

**Response Object Properties:**

- `connected` (bool) - Whether the device has network connectivity
- `type` (string) - Connection type: `"wifi"`, `"cellular"`, `"ethernet"`, or `"unknown"`
- `isExpensive` (bool) - Whether the connection is metered/cellular
- `isConstrained` (bool) - Whether Low Data Mode is enabled (iOS only, always `false` on Android)

**Configuration:**

Network state detection is enabled by default. You can disable it in `config/nativephp.php`:

```php
'permissions' => [
'network_state' => true, // Set to false to disable
],
```

**Platform Notes:**

- **iOS:** Uses `NWPathMonitor` from the Network framework. No additional permissions required.
- **Android:** Requires `ACCESS_NETWORK_STATE` permission (automatically added when enabled)
4 changes: 4 additions & 0 deletions resources/views/docs/mobile/2/_index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
---
title: Mobile
order: 1
---
4 changes: 4 additions & 0 deletions resources/views/docs/mobile/2/apis/_index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
---
title: APIs
order: 4
---
201 changes: 201 additions & 0 deletions resources/views/docs/mobile/2/apis/audio.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
---
title: Audio
order: 50
---

## Overview

The Audio API provides access to the device's microphone for recording audio. It offers a fluent interface for starting and managing recordings, tracking them with unique identifiers, and responding to completion events.

```php
use Native\Mobile\Facades\Audio;
```

## Methods

### `record()`

Start an audio recording. Returns a `PendingAudioRecorder` instance that controls the recording lifecycle.

```php
Audio::record()->start();
```

### `stop()`

Stop the current audio recording. This dispatches the `AudioRecorded` event with the recording file path.

```php
Audio::stop();
```

### `pause()`

Pause the current audio recording without ending it.

```php
Audio::pause();
```

### `resume()`

Resume a paused audio recording.

```php
Audio::resume();
```

### `getStatus()`

Get the current recording status.

**Returns:** `string` - One of: `"idle"`, `"recording"`, or `"paused"`

```php
$status = Audio::getStatus();

if ($status === 'recording') {
// A recording is in progress
}
```

### `getRecording()`

Get the file path to the last recorded audio file.

**Returns:** `string|null` - Path to the last recording, or `null` if none exists

```php
$path = Audio::getRecording();

if ($path) {
// Process the recording file
}
```

## PendingAudioRecorder

The `PendingAudioRecorder` provides a fluent interface for configuring and starting audio recordings. Most methods return `$this` for method chaining.

### `id(string $id)`

Set a unique identifier for this recording. This ID will be included in the `AudioRecorded` event, allowing you to correlate recordings with completion events.

```php
$recorderId = 'message-recording-' . $this->id;

Audio::record()
->id($recorderId)
->start();
```

### `getId()`

Get the recorder's unique identifier. If no ID was set, one is automatically generated (UUID v4).

```php
$recorder = Audio::record()
->id('my-recording');

$id = $recorder->getId(); // 'my-recording'
```

### `event(string $eventClass)`

Set a custom event class to dispatch when recording completes. By default, `AudioRecorded` is used.

**Throws:** `InvalidArgumentException` if the event class does not exist

```php
use App\Events\VoiceMessageRecorded;

Audio::record()
->event(VoiceMessageRecorded::class)
->start();
```

### `remember()`

Store the recorder's ID in the session for later retrieval. This is useful when the recording completes on the next request.

```php
Audio::record()
->id('voice-note')
->remember()
->start();
```

### `lastId()`

Retrieve the last remembered audio recorder ID from the session. Use this in event listeners to correlate recordings.

```php
use Livewire\Attributes\On;
use Native\Mobile\Events\Audio\AudioRecorded;

#[On('native:'.AudioRecorded::class)]
public function handleAudioRecorded(string $path, string $mimeType, ?string $id)
{
// For comparing with remembered IDs
if ($id === Audio::record()->lastId()) {
$this->saveRecording($path);
}
}
```

### `start()`

Explicitly start the audio recording. This is optional - recordings auto-start if you don't call this method.

**Returns:** `bool` - `true` if recording started successfully, `false` if it failed or was already started

```php
$recorder = Audio::record()->id('my-recording');

if ($recorder->start()) {
// Recording started
} else {
// Recording failed - likely due to permission denial
}
```

## Events

### `AudioRecorded`

Dispatched when an audio recording completes. The event includes the file path and recording ID.

**Payload:**
- `string $path` - File path to the recorded audio
- `string $mimeType` - MIME type of the audio (default: `'audio/m4a'`)
- `?string $id` - The recorder's ID, if one was set

```php
use Livewire\Attributes\On;
use Native\Mobile\Events\Audio\AudioRecorded;

#[On('native:'.AudioRecorded::class)]
public function handleAudioRecorded(string $path, string $mimeType, ?string $id)
{
// Store or process the recording
$this->recordings[] = [
'path' => $path,
'mimeType' => $mimeType,
'id' => $id,
];
}
```

## Notes

- **Microphone Permission:** The first time your app requests microphone access, users will be prompted for permission. If denied, recording functions will fail silently.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see the permissions/entitlements on the bottom of every page where a api needs it.

It makes sense to me to place any required entitlements way up top. So the user adds the entitlement before attempting to play with the feature. We should not bury critical steps to make the thing work

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

perhaps a callout even makes sense here


- **File Format:** Recordings are stored as M4A/AAC audio files (`.m4a`). This format is optimized for small file sizes while maintaining quality.

- **Storage Location:**
- **Android:** Recordings are stored in the app's cache directory (`context.cacheDir/audio_{timestamp}.m4a`). These are temporary files and may be deleted by the system.
- **iOS:** Recordings are stored persistently in `~/Library/Application Support/Audio/NativePHP_{timestamp}.m4a` and are excluded from iCloud backup.

- **Recording State:** Only one recording can be active at a time. Calling `start()` while a recording is in progress will return `false`.

- **Auto-Start Behavior:** If you don't explicitly call `start()`, the recording will automatically start when the `PendingAudioRecorder` is destroyed. This maintains backward compatibility with earlier versions.
61 changes: 61 additions & 0 deletions resources/views/docs/mobile/2/apis/biometrics.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
---
title: Biometrics
order: 100
---

## Overview

The Biometrics API allows you to authenticate users using their device's biometric sensors like Face ID, Touch ID, or
fingerprint scanners.

```php
use Native\Mobile\Facades\Biometrics;
```

## Methods

### `prompt()`

Prompts the user for biometric authentication.

```php
use Native\Mobile\Facades\Biometrics;

Biometrics::prompt();
```

## Events

### `Completed`

Fired when biometric authentication completes (success or failure).

```php
use Livewire\Attributes\On;
use Native\Mobile\Events\Biometric\Completed;

#[On('native:'.Completed::class)]
public function handle(Completed $event)
{
if ($event->success) {
// User authenticated successfully
$this->unlockSecureFeature();
} else {
// Authentication failed
$this->showErrorMessage();
}
}
```

## Platform Support

- **iOS:** Face ID, Touch ID
- **Android:** Fingerprint, Face unlock, other biometric methods
- **Fallback:** System authentication (PIN, password, pattern)

## Security Notes

- Biometric authentication provides **convenience**, not absolute security
- Always combine with other authentication factors for sensitive operations
- Consider implementing session timeouts for unlocked states
- Users can potentially bypass biometrics if their device is compromised
Loading
Loading