Skip to content

WebView Integration ​

Understand how the Lingu SDK uses WebView for a seamless chat experience.

Hybrid Architecture ​

The Lingu React Native SDK uses a hybrid approach that combines the best of both worlds:

ComponentTechnologyPurpose
UI LayerWebViewConsistent, beautiful chat interface
API LayerNativeFast, reliable network requests
StorageAsyncStoragePersistent message history

Why WebView? ​

Advantages ​

  1. Consistent UI: Same pixel-perfect interface on iOS and Android
  2. Rapid Updates: UI improvements without app store updates
  3. Smaller Bundle: Core UI shipped via web, reducing app size
  4. Feature Parity: New features available instantly across platforms

How It Works ​

mermaid
sequenceDiagram
    participant User
    participant WebView as WebView (UI)
    participant Native as Native Layer
    participant API as Lingu API

    User->>WebView: Types message
    WebView->>Native: postMessage()
    Native->>API: HTTP Request
    API-->>Native: AI Response
    Native->>WebView: Inject response
    WebView-->>User: Display message

Communication Bridge ​

The SDK creates a bridge between WebView and React Native:

Web → Native ​

javascript
// Inside WebView
window.ReactNativeWebView.postMessage(JSON.stringify({
  type: 'SEND_MESSAGE',
  payload: { text: 'Hello!' }
}));

Native → Web ​

typescript
// React Native side
webViewRef.current?.injectJavaScript(`
  window.receiveMessage(${JSON.stringify(message)});
`);

WebView Configuration ​

The SDK configures the WebView optimally:

tsx
<WebView
  source={{ uri: WIDGET_URL }}
  javaScriptEnabled={true}
  domStorageEnabled={true}
  mixedContentMode="compatibility"
  allowsInlineMediaPlayback={true}
  onMessage={handleMessage}
  // ... other configs
/>

Security Settings ​

SettingValueReason
javaScriptEnabledtrueRequired for chat functionality
domStorageEnabledtrueLocal data storage
allowsFullscreenVideofalseNot needed
allowsBackForwardNavigationGesturesfalsePrevent accidental navigation

Native API Benefits ​

While using WebView for UI, the SDK makes native API calls for:

1. Network Requests ​

Native HTTP requests are faster and more reliable than WebView network calls:

typescript
// Native fetch instead of WebView fetch
const response = await fetch(API_URL + '/message', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'X-API-Key': apiKey,
  },
  body: JSON.stringify({ message, sessionId }),
});

2. Session Management ​

Sessions are managed natively for better reliability:

typescript
// Heartbeat runs in native code
setInterval(() => {
  api.sendHeartbeat(sessionId);
}, 30000); // Every 30 seconds

3. Local Storage ​

Messages are persisted using AsyncStorage:

typescript
import AsyncStorage from '@react-native-async-storage/async-storage';

// Save messages
await AsyncStorage.setItem('lingu_messages', JSON.stringify(messages));

// Restore on app open
const saved = await AsyncStorage.getItem('lingu_messages');

Offline Support ​

The hybrid architecture enables basic offline functionality:

FeatureOffline Behavior
View message historyWorks (from AsyncStorage)
Send new messagesQueued until online
Receive new messagesRequires connection

Performance Optimization ​

1. Lazy Loading ​

The WebView loads only when the user opens the chat:

tsx
const [isOpen, setIsOpen] = useState(false);

return (
  <>
    <FloatingButton onPress={() => setIsOpen(true)} />
    {isOpen && <LinguWebView />}
  </>
);

2. Preloading ​

For faster open times, preload the WebView in the background:

tsx
// Preload WebView but keep it hidden
<View style={{ height: 0, overflow: 'hidden' }}>
  <LinguWebView />
</View>

3. Caching ​

Static assets are cached for faster subsequent loads:

tsx
<WebView
  cacheEnabled={true}
  cacheMode="LOAD_CACHE_ELSE_NETWORK"
/>

Custom WebView Integration ​

For advanced use cases, you can integrate the WebView manually:

tsx
import { WebView } from 'react-native-webview';
import { LinguAPI } from '@uselingu/react-native-sdk';

const WIDGET_URL = 'https://widget.uselingu.com';

function CustomChat() {
  const webViewRef = useRef<WebView>(null);
  const api = new LinguAPI('your-api-key');
  
  const handleMessage = async (event) => {
    const data = JSON.parse(event.nativeEvent.data);
    
    if (data.type === 'SEND_MESSAGE') {
      const response = await api.sendMessage(data.payload.text, sessionId);
      
      webViewRef.current?.injectJavaScript(`
        window.receiveMessage(${JSON.stringify(response)});
      `);
    }
  };
  
  return (
    <WebView
      ref={webViewRef}
      source={{ uri: WIDGET_URL }}
      onMessage={handleMessage}
      javaScriptEnabled={true}
    />
  );
}

Debugging ​

Inspect WebView Content ​

For iOS (Safari):

  1. Enable Safari Web Inspector on device
  2. Open Safari on Mac → Develop → [Device Name]

For Android (Chrome):

  1. Enable USB debugging on device
  2. Open chrome://inspect in Chrome

Log Bridge Messages ​

tsx
const handleMessage = (event) => {
  console.log('WebView message:', event.nativeEvent.data);
  // ... handle message
};

built with lingu