# Browser Compatibility and Device Handling

This guide covers browser support, mobile considerations, and device handling for applications built with Hiyve SDK.

---

## Supported Browsers

Hiyve SDK works in any modern browser that supports WebRTC (`getUserMedia` and `RTCPeerConnection`).

| Browser | Desktop | Mobile | Notes |
|---------|---------|--------|-------|
| Chrome | Full support | Full support | Recommended for development and production |
| Edge (Chromium) | Full support | Full support | Same engine as Chrome |
| Firefox | Full support | Full support | -- |
| Safari | Full support | iOS only | No audio output selection; no screen share on iOS |
| Brave | Full support | Full support | Privacy-aware device handling built in |
| Opera | Full support | Full support | -- |
| Samsung Internet | N/A | Full support | -- |

**Minimum requirement:** WebRTC support (`getUserMedia`, `RTCPeerConnection`).

**Not supported:** Internet Explorer, Edge Legacy (non-Chromium).

---

## Mobile Considerations

### iOS

- **Screen sharing is not available** on iOS Safari. The SDK detects this automatically.
- **Audio output device selection** (`setSinkId`) is not supported in Safari on any platform, including iOS. The `DeviceSelector` component hides the output dropdown automatically.
- **Device label access** may be unreliable on iOS -- the SDK handles this gracefully with fallback labels.
- **Orientation changes** are handled automatically. When a user rotates their device, the SDK replaces the video track without recreating the media producer, so other participants see the orientation update seamlessly.
- **iPad detection:** iPadOS 13+ identifies itself as `"MacIntel"` in the user agent. The SDK detects iPads using `navigator.maxTouchPoints` to apply the correct mobile behavior.

### Android

- Full feature support on Chrome, Edge, Samsung Internet, and Brave.
- Device permission prompts may take slightly longer on mobile browsers compared to desktop.

---

## Device Permissions

The SDK handles camera and microphone permissions automatically with browser-specific strategies. Consumers do not need to write permission-handling code.

### How it works

When your application requests media access (for example, when a user joins a room or opens the device preview), the SDK:

1. Detects the browser and applies the optimal permission request order:
   - **Chrome / Edge / Brave / Opera:** Requests video first, then audio.
   - **Firefox:** Requests video first, then audio (same approach as Chrome).
   - **Safari:** Uses conservative timing with longer delays between requests.

2. If device access fails with the requested constraints, the SDK progressively relaxes them:
   1. Try original constraints (e.g., 1280x720, 30fps).
   2. Convert `exact` constraints to `ideal` (allows the browser to pick the closest match).
   3. Remove strict constraints (aspect ratio, frame rate).
   4. Fall back to minimal constraints (only `deviceId` if one was specified, otherwise `{ video: true, audio: true }`).

3. If constraints were downgraded, the `CONSTRAINTS_RELAXED` event fires internally for debugging. This event is logged by the SDK but not surfaced through `useLocalMedia()`. If you need to detect constraint relaxation, use `useClient()` to access the raw RTC client and listen for the event directly.

### Best practices

- Use `<DevicePreview>` and `<DeviceSelector>` from `@hiyve/react-ui` for device selection UX. These components handle device enumeration, selection, and persistence automatically.
- Check `useLocalMedia()` for the current device state before and after joining.
- Handle the case where no camera or microphone is available by showing an appropriate message. A user without a camera can still join audio-only.

```tsx
import { useLocalMedia } from '@hiyve/react';

function DeviceStatus() {
  const { isAudioMuted, isVideoMuted } = useLocalMedia();

  return (
    <p>
      Camera: {isVideoMuted ? 'off' : 'on'} | Mic: {isAudioMuted ? 'off' : 'on'}
    </p>
  );
}
```

---

## Screen Sharing

| Browser | Support |
|---------|---------|
| Chrome | Yes |
| Edge (Chromium) | Yes |
| Firefox | Yes |
| Safari (desktop) | Yes |
| Brave | Yes |
| Opera | Yes |
| Safari (iOS) | No |
| Android browsers | Limited |

The SDK calls `getDisplayMedia()` to start screen sharing. If the browser does not support it, the screen share option should be hidden.

The `ControlBar` component from `@hiyve/react-ui` shows the screen share button when `showScreenShare` is `true` (the default). If you need to hide it on unsupported browsers (e.g., iOS Safari), detect support and pass the prop:

```tsx
import { ControlBar } from '@hiyve/react-ui';

const screenShareSupported =
  typeof navigator.mediaDevices?.getDisplayMedia === 'function';

<ControlBar showScreenShare={screenShareSupported} />
```

---

## Audio Output Selection

The `setSinkId` API allows users to choose which speaker or headphone to use for audio output.

| Browser | Support |
|---------|---------|
| Chrome | Yes |
| Edge (Chromium) | Yes |
| Firefox | Yes |
| Brave | Yes |
| Opera | Yes |
| Safari (desktop) | No |
| Safari (iOS) | No |

The `DeviceSelector` component from `@hiyve/react-ui` automatically detects `setSinkId` support and hides the output device dropdown on unsupported browsers. No action is needed from consumers.

---

## Private / Incognito Mode

The SDK detects private browsing mode and adjusts its behavior automatically:

- **Extra retry attempts** for Chrome device permission requests in incognito mode (5 attempts instead of 3).
- **Longer delays** between Chrome permission prompts to account for stricter incognito behavior.
- **Ultra-basic constraints** used as a last resort in Chrome incognito if all other constraint levels fail.
- **localStorage may be unavailable** -- device selection persistence is disabled gracefully on all browsers.

No action is needed from consumers. The SDK handles all of this internally.

---

## WebView / Embedded Browsers

In-app browsers and WebViews (such as those in social media apps or email clients) have limited and inconsistent WebRTC support. The SDK accounts for this with longer timeouts for all permission operations, but some features may not work reliably:

- Screen sharing is typically unavailable.
- Device selection may be limited to a single camera and microphone.
- Audio output selection is generally not supported.

**Recommendation:** If your application detects a WebView environment, display a message directing users to open the link in their default browser for the best experience.

```tsx
function WebViewWarning() {
  const isWebView =
    /(wv|WebView)/i.test(navigator.userAgent) ||
    /FBAN|FBAV|Instagram|Line|Twitter/i.test(navigator.userAgent);

  if (!isWebView) return null;

  return (
    <div>
      For the best experience, open this link in Chrome, Safari, or your
      default browser.
    </div>
  );
}
```

---

## Feature Support Summary

| Feature | Chrome | Firefox | Safari (desktop) | Safari (iOS) | Android |
|---------|--------|---------|-------------------|---------------|---------|
| Video conferencing | Yes | Yes | Yes | Yes | Yes |
| Audio conferencing | Yes | Yes | Yes | Yes | Yes |
| Screen sharing | Yes | Yes | Yes | No | Limited |
| Audio output selection | Yes | Yes | No | No | Yes |
| Device label access | Yes | Yes | After permission | After permission | Yes |
| Camera/mic selection | Yes | Yes | Yes | Yes | Yes |
| Private mode | Yes | Yes | Yes | Yes | Yes |
