# Custom Loading Screen

The SDK does not include a built-in loading screen — you build your own using WebRTC lifecycle events. The example app demonstrates a complete loading screen pattern you can adapt.

## Mapping Events to Progress

Each WebRTC lifecycle event represents a stage in the connection process. Map them to progress values:

| Event               | Progress | Status Message                        |
| ------------------- | -------- | ------------------------------------- |
| (initialization)    | 10%      | "Connecting to server..."             |
| `webRtcAutoConnect` | 15%      | "Initializing connection..."          |
| `webRtcConnecting`  | 30%      | "Establishing WebRTC connection..."   |
| `webRtcSdp`         | 50%      | "Negotiating stream parameters..."    |
| `webRtcConnected`   | 70%      | "WebRTC connected, loading stream..." |
| `streamLoading`     | 80%      | "Stream is loading..."                |
| `playStream`        | 90%      | "Starting video playback..."          |
| `videoInitialized`  | 100%     | (hide loading screen)                 |

### Example Implementation

{% code lineNumbers="true" %}

```javascript
const loadingEl = document.getElementById('loading');
const progressEl = document.getElementById('progress-bar');
const statusEl = document.getElementById('status-text');

function updateLoading(progress, status) {
  progressEl.style.width = progress + '%';
  statusEl.textContent = status;
}

// Initial state
updateLoading(10, 'Connecting to server...');

pixelStreaming.addEventListener('webRtcAutoConnect', () => {
  updateLoading(15, 'Initializing connection...');
});

pixelStreaming.addEventListener('webRtcConnecting', () => {
  updateLoading(30, 'Establishing WebRTC connection...');
});

pixelStreaming.addEventListener('webRtcSdp', () => {
  updateLoading(50, 'Negotiating stream parameters...');
});

pixelStreaming.addEventListener('webRtcConnected', () => {
  updateLoading(70, 'WebRTC connected, loading stream...');
});

pixelStreaming.addEventListener('streamLoading', () => {
  updateLoading(80, 'Stream is loading...');
});

pixelStreaming.addEventListener('playStream', () => {
  updateLoading(90, 'Starting video playback...');
});

appStream.onVideoInitialized = () => {
  updateLoading(100, 'Ready!');
  setTimeout(() => {
    loadingEl.style.display = 'none';
  }, 300);
  document.getElementById('video-container').appendChild(appStream.rootElement);
};
```

{% endcode %}

## Failure States

Show error messages when the connection fails:

```javascript
pixelStreaming.addEventListener('webRtcFailed', () => {
  updateLoading(0, 'Connection failed. Please try again.');
});

pixelStreaming.addEventListener('webRtcDisconnected', () => {
  loadingEl.style.display = 'flex';
  updateLoading(0, 'Disconnected from stream.');
});
```

## Queue Position During Loading

When the user is in a queue, show their position:

```javascript
queueHandler((msg) => {
  statusEl.textContent = 'Waiting in queue...';
  document.getElementById('queue-badge').textContent = '#' + msg.position;
  document.getElementById('queue-badge').style.display = 'block';
});
```

## Reconnection States

Update the loading screen during reconnection:

```javascript
reconnectStream.on('state', (data) => {
  switch (data.status) {
    case 'reconnecting':
      loadingEl.style.display = 'flex';
      updateLoading(20, 'Reconnecting to stream...');
      break;
    case 'retrying':
      updateLoading(40, 'Retrying connection...');
      break;
    case 'connected':
      updateLoading(70, 'Reconnected! Loading stream...');
      break;
    case 'failed':
      updateLoading(0, 'Unable to reconnect. Please refresh the page.');
      break;
  }
});
```

## LOADING\_CONFIG Pattern (from Example App)

{% hint style="success" %}
The `LOADING_CONFIG` pattern is the recommended approach for loading screens. It centralizes all text, colors, and behavior in one object, making customization easy without modifying event handler logic.
{% endhint %}

The example app uses a configuration object to centralize all loading screen customization:

```javascript
const LOADING_CONFIG = {
  backgroundColor: '#18181A',
  accentColor: '#4e9cff',
  logoUrl: null,                    // Path to your logo image
  title: 'Connecting to Stream',
  subtitle: 'Please wait while we set up your experience...',
  disconnectedSubtitle: 'The stream session has ended.',
  showSpinner: true,

  // Queue message template
  queueMessage: (position) => `You are in queue at position ${position}`,

  // Status messages for each connection stage
  statusMessages: {
    initializing:     'Initializing...',
    connecting:       'Connecting to server...',
    webRtcConnecting: 'Establishing WebRTC connection...',
    sdpNegotiation:   'Negotiating stream parameters...',
    webRtcConnected:  'WebRTC connected, loading stream...',
    streamLoading:    'Stream is loading...',
    playingStream:    'Starting video playback...',
    inQueue:          'Waiting in queue...',
    failed:           'Connection failed. Please try again.',
    disconnected:     'Disconnected from stream.',
    reconnecting:     'Reconnecting to stream...',
    retrying:         'Retrying connection...',
    reconnected:      'Reconnected! Loading stream...',
    reconnectFailed:  'Unable to reconnect. Please refresh the page.',
  },

  // Reconnection-specific titles
  reconnectingTitle:       'Reconnecting',
  reconnectingSubtitle:    'Please wait while we restore your session...',
  reconnectedTitle:        'Reconnected',
  reconnectFailedTitle:    'Reconnection Failed',
  reconnectFailedSubtitle: 'We were unable to restore your session.',
};
```

This pattern makes it easy to customize text, colors, and behavior without modifying the event handler logic.
