@dialstack/sdk-native 0.1.1 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -171,25 +171,75 @@ const storage: PlatformStorage = {
171
171
 
172
172
  `storage` just needs `getItem`/`setItem`/`removeItem`.
173
173
 
174
+ ## Call audio
175
+
176
+ By default `<SoftphoneProvider>` owns call audio through
177
+ `react-native-incall-manager`: it rings inbound calls, plays the outbound
178
+ ringback, and holds the audio session (which also turns on the proximity sensor)
179
+ while a call is connected. The ringback goes only to a phone the provider creates
180
+ from `token`: a phone passed as `existingPhone` keeps the `ringback` it was
181
+ created with, so pass one to `createPhone({ ringback })` yourself.
182
+
183
+ When the operating system owns the call instead, because you report calls to
184
+ CallKit or Telecom, the provider must stay out of it: the OS rings the phone and
185
+ activates the session itself, and ringing on top of it costs the answered call
186
+ its microphone. Set `callAudio="host"` and the provider does none of the above.
187
+ With a `bridge` it is always `"host"`. Anything you still want, such as the proximity
188
+ sensor, is then yours to drive (`InCallManager.startProximitySensor()` does not
189
+ touch the audio session).
190
+
191
+ The output route is yours too. Without an `audioOutput` controller the in-call
192
+ speaker button is disabled. To enable it, pass one built over your OS integration:
193
+
194
+ ```tsx
195
+ const audioOutput: AudioOutputController = {
196
+ current: () => lastReportedRoute, // what the OS reports, same object until it changes
197
+ onChange: (listener) => subscribeToRouteChanges(listener),
198
+ setSpeaker: (on) => requestSpeaker(on),
199
+ };
200
+
201
+ <SoftphoneProvider bridge={bridge} audioOutput={audioOutput}>
202
+ …
203
+ </SoftphoneProvider>;
204
+ ```
205
+
206
+ The button shows only the route the OS reports. A switch made from the CallKit
207
+ or Telecom UI, a headset, or a car therefore shows up in-app as well.
208
+ `useAudioOutput()` exposes the same state if you build your own UI.
209
+
174
210
  ## Example apps
175
211
 
176
- Two runnable apps, both wired with the permissions and plugin above:
212
+ Three runnable apps, all wired with the permissions and plugin above:
177
213
 
178
214
  - [Expo](https://github.com/dialstack/dialstack-sdk/tree/main/examples/mobile/expo)
179
215
  — ships the MMKV storage adapter
180
216
  - [Bare React Native](https://github.com/dialstack/dialstack-sdk/tree/main/examples/mobile/bare)
181
217
  — ships an AsyncStorage adapter
218
+ - [OS integration](https://github.com/dialstack/dialstack-sdk/tree/main/examples/mobile/os-integration)
219
+ — the worked example for the OS call surface: calls on a locked or killed
220
+ phone via push wake, `OsCallAdapter` over expo-callkit-telecom. Built and
221
+ verified on both Android (FCM + Telecom) and iOS (PushKit + CallKit).
182
222
 
183
223
  ## Scope
184
224
 
185
- This package provides the in-app calling surface: the provider, the call state,
186
- and the React Native UI. The operating system's own call experience — the
187
- full-screen incoming call, ringing on a locked screen, and waking the app from a
188
- push — is the integrator's to wire, using the platform frameworks directly (iOS
189
- PushKit + CallKit, Android FCM + Telecom/ConnectionService).
225
+ This package provides the in-app calling surface — the provider, the call state,
226
+ and the React Native UI — plus the bridge between the SDK and the operating
227
+ system's own call experience.
228
+
229
+ Binding the two remains the integrator's work, but not from scratch:
230
+ `NativeCallBridge` keeps an OS call session and an SDK `Call` in step in both
231
+ directions, and `OsCallAdapter` is the interface it drives, so the part you write
232
+ is one adapter over your chosen call library rather than the whole state machine.
233
+ A contract suite in `@dialstack/sdk-native/testing` exercises an adapter against
234
+ the behaviours the bridge depends on.
235
+
236
+ What the package does not ship is the platform wiring itself: the native call
237
+ library (iOS PushKit + CallKit, Android FCM + Telecom/ConnectionService) and the
238
+ push delivery. DialStack stores no device tokens — arranging the push that wakes
239
+ your app is yours. The OS-integration example above is a complete worked wiring
240
+ of both on Android.
190
241
 
191
- The seams for that are public. `useSoftphone()` exposes `calls`,
242
+ The lower-level seams stay public too: `useSoftphone()` exposes `calls`,
192
243
  `incomingCalls`, `activeCall` and `actions.callActionsFor(call)`, and every
193
- `Call` carries a stable `id` and `state`, so a native call session can be
194
- created, kept in step, and torn down alongside the SDK's own. DialStack stores
195
- no device tokens — delivering the push that wakes your app is yours to arrange.
244
+ `Call` carries a stable `id` and `state`, so an integrator who wants to drive the
245
+ OS session directly can still do so.