@voipsdk/react-native-voipcloud 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 +172 -0
- package/android/build.gradle +61 -0
- package/android/src/main/AndroidManifest.xml +2 -0
- package/android/src/main/java/com/voipcloud/sdk/rn/VoipCloudModule.java +428 -0
- package/android/src/main/java/com/voipcloud/sdk/rn/VoipCloudPackage.java +21 -0
- package/android/src/main/java/com/voipcloud/sdk/rn/internal/Events.java +38 -0
- package/android/src/main/java/com/voipcloud/sdk/rn/internal/ManagedAccount.java +63 -0
- package/android/src/main/java/com/voipcloud/sdk/rn/internal/ManagedCall.java +179 -0
- package/android/src/main/java/com/voipcloud/sdk/rn/internal/ManagedCallRegistry.java +26 -0
- package/android/src/main/libs/voipcloud-release.aar +0 -0
- package/ios/VoipCloud.mm +40 -0
- package/lib/commonjs/License.js +51 -0
- package/lib/commonjs/License.js.map +1 -0
- package/lib/commonjs/VoipCloud.js +89 -0
- package/lib/commonjs/VoipCloud.js.map +1 -0
- package/lib/commonjs/events.js +29 -0
- package/lib/commonjs/events.js.map +1 -0
- package/lib/commonjs/index.js +27 -0
- package/lib/commonjs/index.js.map +1 -0
- package/lib/commonjs/types.js +2 -0
- package/lib/commonjs/types.js.map +1 -0
- package/lib/module/License.js +45 -0
- package/lib/module/License.js.map +1 -0
- package/lib/module/VoipCloud.js +83 -0
- package/lib/module/VoipCloud.js.map +1 -0
- package/lib/module/events.js +23 -0
- package/lib/module/events.js.map +1 -0
- package/lib/module/index.js +4 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/types.js +2 -0
- package/lib/module/types.js.map +1 -0
- package/lib/typescript/License.d.ts +31 -0
- package/lib/typescript/VoipCloud.d.ts +52 -0
- package/lib/typescript/events.d.ts +6 -0
- package/lib/typescript/index.d.ts +4 -0
- package/lib/typescript/types.d.ts +136 -0
- package/package.json +76 -0
- package/react-native-voipcloud.podspec +16 -0
- package/src/License.ts +52 -0
- package/src/VoipCloud.ts +98 -0
- package/src/events.ts +23 -0
- package/src/index.ts +23 -0
- package/src/types.ts +144 -0
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
package com.voipcloud.sdk.rn.internal;
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.bridge.ReactContext;
|
|
4
|
+
import com.facebook.react.bridge.WritableMap;
|
|
5
|
+
import com.facebook.react.modules.core.DeviceEventManagerModule;
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Thin wrapper around DeviceEventEmitter so the rest of the bridge
|
|
9
|
+
* never imports React internals directly.
|
|
10
|
+
*/
|
|
11
|
+
public final class Events {
|
|
12
|
+
// Account / call lifecycle (emitted by PJSIP callbacks).
|
|
13
|
+
public static final String REGISTRATION_STATE = "registrationState";
|
|
14
|
+
public static final String INCOMING_CALL = "incomingCall";
|
|
15
|
+
public static final String CALL_STATE = "callState";
|
|
16
|
+
public static final String CALL_MEDIA_STATE = "callMediaState";
|
|
17
|
+
|
|
18
|
+
// Per-action confirmations (emitted by the bridge after the action
|
|
19
|
+
// succeeds — gives the UI a single hook per control without forcing
|
|
20
|
+
// it to derive intent from callMediaState diffs).
|
|
21
|
+
public static final String CALL_HOLD = "callHold";
|
|
22
|
+
public static final String CALL_UNHOLD = "callUnhold";
|
|
23
|
+
public static final String CALL_MUTE = "callMute";
|
|
24
|
+
public static final String CALL_DTMF_SENT = "callDtmfSent";
|
|
25
|
+
public static final String CALL_TRANSFER = "callTransfer";
|
|
26
|
+
|
|
27
|
+
// Remote-driven events forwarded from PJSIP callbacks.
|
|
28
|
+
public static final String CALL_TRANSFER_STATUS = "callTransferStatus";
|
|
29
|
+
public static final String INCOMING_DTMF = "incomingDtmf";
|
|
30
|
+
|
|
31
|
+
private Events() {}
|
|
32
|
+
|
|
33
|
+
public static void emit(ReactContext ctx, String name, WritableMap payload) {
|
|
34
|
+
if (ctx == null || !ctx.hasActiveReactInstance()) return;
|
|
35
|
+
ctx.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
|
|
36
|
+
.emit(name, payload);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
package com.voipcloud.sdk.rn.internal;
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.bridge.Arguments;
|
|
4
|
+
import com.facebook.react.bridge.ReactContext;
|
|
5
|
+
import com.facebook.react.bridge.WritableMap;
|
|
6
|
+
|
|
7
|
+
import com.voipcloud.sdk.Account;
|
|
8
|
+
import com.voipcloud.sdk.AccountInfo;
|
|
9
|
+
import com.voipcloud.sdk.CallOpParam;
|
|
10
|
+
import com.voipcloud.sdk.OnIncomingCallParam;
|
|
11
|
+
import com.voipcloud.sdk.OnRegStateParam;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Account subclass forwarding PJSUA2 callbacks to JS as RN events.
|
|
15
|
+
* One instance per registered SIP account.
|
|
16
|
+
*/
|
|
17
|
+
public final class ManagedAccount extends Account {
|
|
18
|
+
private final ReactContext ctx;
|
|
19
|
+
private final ManagedCallRegistry callRegistry;
|
|
20
|
+
|
|
21
|
+
public ManagedAccount(ReactContext ctx, ManagedCallRegistry callRegistry) {
|
|
22
|
+
this.ctx = ctx;
|
|
23
|
+
this.callRegistry = callRegistry;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
public int accountId() {
|
|
27
|
+
try { return getId(); } catch (Exception e) { return -1; }
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
@Override
|
|
31
|
+
public void onRegState(OnRegStateParam prm) {
|
|
32
|
+
WritableMap payload = Arguments.createMap();
|
|
33
|
+
payload.putInt("accountId", accountId());
|
|
34
|
+
payload.putInt("code", prm.getCode());
|
|
35
|
+
payload.putString("reason", prm.getReason());
|
|
36
|
+
Events.emit(ctx, Events.REGISTRATION_STATE, payload);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
@Override
|
|
40
|
+
public void onIncomingCall(OnIncomingCallParam prm) {
|
|
41
|
+
// Allocate a ManagedCall so we can fire callState events for
|
|
42
|
+
// this inbound leg. The consumer must call answer(callId) or
|
|
43
|
+
// hangup(callId) to proceed.
|
|
44
|
+
ManagedCall call = new ManagedCall(ctx, this, prm.getCallId());
|
|
45
|
+
callRegistry.put(call);
|
|
46
|
+
|
|
47
|
+
try {
|
|
48
|
+
AccountInfo accInfo = getInfo();
|
|
49
|
+
WritableMap payload = Arguments.createMap();
|
|
50
|
+
payload.putInt("accountId", accountId());
|
|
51
|
+
payload.putInt("callId", call.callId());
|
|
52
|
+
payload.putString("from", call.getInfo().getRemoteUri());
|
|
53
|
+
payload.putString("to", accInfo.getUri());
|
|
54
|
+
Events.emit(ctx, Events.INCOMING_CALL, payload);
|
|
55
|
+
} catch (Exception ignored) {
|
|
56
|
+
// If we cannot pull info, still notify with what we have.
|
|
57
|
+
WritableMap payload = Arguments.createMap();
|
|
58
|
+
payload.putInt("accountId", accountId());
|
|
59
|
+
payload.putInt("callId", call.callId());
|
|
60
|
+
Events.emit(ctx, Events.INCOMING_CALL, payload);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
package com.voipcloud.sdk.rn.internal;
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.bridge.Arguments;
|
|
4
|
+
import com.facebook.react.bridge.ReactContext;
|
|
5
|
+
import com.facebook.react.bridge.WritableMap;
|
|
6
|
+
|
|
7
|
+
import com.voipcloud.sdk.Account;
|
|
8
|
+
import com.voipcloud.sdk.AudDevManager;
|
|
9
|
+
import com.voipcloud.sdk.AudioMedia;
|
|
10
|
+
import com.voipcloud.sdk.Call;
|
|
11
|
+
import com.voipcloud.sdk.CallInfo;
|
|
12
|
+
import com.voipcloud.sdk.CallMediaInfo;
|
|
13
|
+
import com.voipcloud.sdk.Endpoint;
|
|
14
|
+
import com.voipcloud.sdk.OnCallMediaStateParam;
|
|
15
|
+
import com.voipcloud.sdk.OnCallStateParam;
|
|
16
|
+
import com.voipcloud.sdk.OnCallTransferStatusParam;
|
|
17
|
+
import com.voipcloud.sdk.OnDtmfDigitParam;
|
|
18
|
+
import com.voipcloud.sdk.pjmedia_type;
|
|
19
|
+
import com.voipcloud.sdk.pjsip_inv_state;
|
|
20
|
+
import com.voipcloud.sdk.pjsua_call_media_status;
|
|
21
|
+
|
|
22
|
+
/** Call subclass forwarding state callbacks to JS. */
|
|
23
|
+
public final class ManagedCall extends Call {
|
|
24
|
+
private final ReactContext ctx;
|
|
25
|
+
/** Local snapshot of the PJSUA call id — Call.getId() can throw post-disconnect. */
|
|
26
|
+
private final int cachedId;
|
|
27
|
+
/** Mute is tracked at the bridge level — PJSIP does not own this state. */
|
|
28
|
+
private volatile boolean isMuted = false;
|
|
29
|
+
|
|
30
|
+
public ManagedCall(ReactContext ctx, Account acc) {
|
|
31
|
+
super(acc);
|
|
32
|
+
this.ctx = ctx;
|
|
33
|
+
this.cachedId = -1;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
public ManagedCall(ReactContext ctx, Account acc, int callId) {
|
|
37
|
+
super(acc, callId);
|
|
38
|
+
this.ctx = ctx;
|
|
39
|
+
this.cachedId = callId;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
public int callId() {
|
|
43
|
+
try { return getId(); } catch (Exception e) { return cachedId; }
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
public boolean isMuted() { return isMuted; }
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Toggle the local microphone for this call. Implementation:
|
|
50
|
+
* iterate the call's audio media, and for each active leg either
|
|
51
|
+
* stop (mute) or start (unmute) transmission from the capture
|
|
52
|
+
* device to that leg. Hold and mute are independent — muting a
|
|
53
|
+
* held call is a no-op for the audio bridge but the flag is still
|
|
54
|
+
* tracked so unhold-then-emit reflects the user's intent.
|
|
55
|
+
*/
|
|
56
|
+
public void setMuted(Endpoint endpoint, boolean muted) throws Exception {
|
|
57
|
+
AudDevManager adm = endpoint.audDevManager();
|
|
58
|
+
AudioMedia mic = adm.getCaptureDevMedia();
|
|
59
|
+
CallInfo info = getInfo();
|
|
60
|
+
for (int i = 0; i < info.getMedia().size(); i++) {
|
|
61
|
+
CallMediaInfo mi = info.getMedia().get(i);
|
|
62
|
+
if (mi.getType() != pjmedia_type.PJMEDIA_TYPE_AUDIO) continue;
|
|
63
|
+
if (mi.getStatus() != pjsua_call_media_status.PJSUA_CALL_MEDIA_ACTIVE) continue;
|
|
64
|
+
AudioMedia leg = getAudioMedia(i);
|
|
65
|
+
if (muted) {
|
|
66
|
+
mic.stopTransmit(leg);
|
|
67
|
+
} else {
|
|
68
|
+
mic.startTransmit(leg);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
this.isMuted = muted;
|
|
72
|
+
// PJSIP will not fire onCallMediaState for a bridge-only change,
|
|
73
|
+
// so push an event manually to keep the JS layer in sync.
|
|
74
|
+
emitMediaState();
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
@Override
|
|
78
|
+
public void onCallState(OnCallStateParam prm) {
|
|
79
|
+
CallInfo info;
|
|
80
|
+
try { info = getInfo(); }
|
|
81
|
+
catch (Exception e) {
|
|
82
|
+
// After DISCONNECTED, getInfo may fail; emit a minimal payload.
|
|
83
|
+
WritableMap p = Arguments.createMap();
|
|
84
|
+
p.putInt("callId", cachedId);
|
|
85
|
+
p.putString("state", "DISCONNECTED");
|
|
86
|
+
p.putInt("code", 0);
|
|
87
|
+
p.putString("reason", "");
|
|
88
|
+
Events.emit(ctx, Events.CALL_STATE, p);
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
WritableMap p = Arguments.createMap();
|
|
92
|
+
p.putInt("callId", callId());
|
|
93
|
+
p.putString("state", invStateName(info.getState()));
|
|
94
|
+
p.putInt("code", info.getLastStatusCode());
|
|
95
|
+
p.putString("reason", info.getLastReason());
|
|
96
|
+
Events.emit(ctx, Events.CALL_STATE, p);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
@Override
|
|
100
|
+
public void onCallMediaState(OnCallMediaStateParam prm) {
|
|
101
|
+
emitMediaState();
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Multi-stage progress notifications for a REFER (call transfer)
|
|
106
|
+
* we initiated. Fires for each NOTIFY received from the remote
|
|
107
|
+
* (typically 100 Trying → 200 OK → … → final 2xx/4xx-6xx with
|
|
108
|
+
* `finalNotify=true`). Consumers can use this to drive a "transfer
|
|
109
|
+
* pending / done / failed" UI without polling.
|
|
110
|
+
*/
|
|
111
|
+
@Override
|
|
112
|
+
public void onCallTransferStatus(OnCallTransferStatusParam prm) {
|
|
113
|
+
WritableMap p = Arguments.createMap();
|
|
114
|
+
p.putInt("callId", callId());
|
|
115
|
+
p.putInt("statusCode", prm.getStatusCode());
|
|
116
|
+
p.putString("reason", prm.getReason());
|
|
117
|
+
p.putBoolean("finalNotify", prm.getFinalNotify());
|
|
118
|
+
Events.emit(ctx, Events.CALL_TRANSFER_STATUS, p);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Inbound DTMF detected on the RTP stream of this call. Forward
|
|
123
|
+
* each digit individually so IVR-style consumers can build up an
|
|
124
|
+
* input buffer. `duration` is the digit duration in PJSIP timer
|
|
125
|
+
* ticks (≈ ms with default sampling).
|
|
126
|
+
*/
|
|
127
|
+
@Override
|
|
128
|
+
public void onDtmfDigit(OnDtmfDigitParam prm) {
|
|
129
|
+
WritableMap p = Arguments.createMap();
|
|
130
|
+
p.putInt("callId", callId());
|
|
131
|
+
p.putString("digit", prm.getDigit());
|
|
132
|
+
p.putDouble("duration", prm.getDuration());
|
|
133
|
+
Events.emit(ctx, Events.INCOMING_DTMF, p);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Build and emit the `callMediaState` event from the current PJSIP
|
|
138
|
+
* media-info snapshot plus the bridge-tracked mute flag. Safe to
|
|
139
|
+
* call from any thread: DeviceEventEmitter takes care of the hop
|
|
140
|
+
* to the JS bridge.
|
|
141
|
+
*/
|
|
142
|
+
public void emitMediaState() {
|
|
143
|
+
WritableMap p = Arguments.createMap();
|
|
144
|
+
p.putInt("callId", callId());
|
|
145
|
+
boolean hasAudio = false;
|
|
146
|
+
boolean isHold = false;
|
|
147
|
+
try {
|
|
148
|
+
CallInfo info = getInfo();
|
|
149
|
+
for (int i = 0; i < info.getMedia().size(); ++i) {
|
|
150
|
+
CallMediaInfo mi = info.getMedia().get(i);
|
|
151
|
+
if (mi.getType() != pjmedia_type.PJMEDIA_TYPE_AUDIO) continue;
|
|
152
|
+
int status = mi.getStatus();
|
|
153
|
+
if (status == pjsua_call_media_status.PJSUA_CALL_MEDIA_ACTIVE) {
|
|
154
|
+
hasAudio = true;
|
|
155
|
+
} else if (status == pjsua_call_media_status.PJSUA_CALL_MEDIA_LOCAL_HOLD
|
|
156
|
+
|| status == pjsua_call_media_status.PJSUA_CALL_MEDIA_REMOTE_HOLD) {
|
|
157
|
+
isHold = true;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
} catch (Exception ignored) {}
|
|
161
|
+
p.putBoolean("hasAudio", hasAudio);
|
|
162
|
+
p.putBoolean("isHold", isHold);
|
|
163
|
+
p.putBoolean("isMuted", isMuted);
|
|
164
|
+
Events.emit(ctx, Events.CALL_MEDIA_STATE, p);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
private static String invStateName(int s) {
|
|
168
|
+
switch (s) {
|
|
169
|
+
case pjsip_inv_state.PJSIP_INV_STATE_NULL: return "NULL";
|
|
170
|
+
case pjsip_inv_state.PJSIP_INV_STATE_CALLING: return "CALLING";
|
|
171
|
+
case pjsip_inv_state.PJSIP_INV_STATE_INCOMING: return "INCOMING";
|
|
172
|
+
case pjsip_inv_state.PJSIP_INV_STATE_EARLY: return "EARLY";
|
|
173
|
+
case pjsip_inv_state.PJSIP_INV_STATE_CONNECTING: return "CONNECTING";
|
|
174
|
+
case pjsip_inv_state.PJSIP_INV_STATE_CONFIRMED: return "CONFIRMED";
|
|
175
|
+
case pjsip_inv_state.PJSIP_INV_STATE_DISCONNECTED: return "DISCONNECTED";
|
|
176
|
+
default: return "UNKNOWN";
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
package com.voipcloud.sdk.rn.internal;
|
|
2
|
+
|
|
3
|
+
import java.util.concurrent.ConcurrentHashMap;
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Lookup of active {@link ManagedCall} instances by PJSUA call id.
|
|
7
|
+
* Threaded — PJSIP callbacks and JS-driven method calls can interleave.
|
|
8
|
+
*/
|
|
9
|
+
public final class ManagedCallRegistry {
|
|
10
|
+
private final ConcurrentHashMap<Integer, ManagedCall> calls = new ConcurrentHashMap<>();
|
|
11
|
+
|
|
12
|
+
public void put(ManagedCall call) {
|
|
13
|
+
int id = call.callId();
|
|
14
|
+
if (id >= 0) calls.put(id, call);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
public ManagedCall get(int id) {
|
|
18
|
+
return calls.get(id);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
public ManagedCall remove(int id) {
|
|
22
|
+
return calls.remove(id);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
public void clear() { calls.clear(); }
|
|
26
|
+
}
|
|
Binary file
|
package/ios/VoipCloud.mm
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
// react-native-voipcloud — iOS placeholder.
|
|
2
|
+
//
|
|
3
|
+
// The Android build of the SDK is complete (libvoipcloud.so + JNI
|
|
4
|
+
// bridge). iOS bindings need an xcframework build of PJSIP, which
|
|
5
|
+
// requires Xcode on macOS. Until then, every JS call from iOS rejects
|
|
6
|
+
// with NOT_IMPLEMENTED so consumer apps notice early.
|
|
7
|
+
|
|
8
|
+
#import <React/RCTBridgeModule.h>
|
|
9
|
+
|
|
10
|
+
@interface VoipCloud : NSObject <RCTBridgeModule>
|
|
11
|
+
@end
|
|
12
|
+
|
|
13
|
+
@implementation VoipCloud
|
|
14
|
+
|
|
15
|
+
RCT_EXPORT_MODULE(VoipCloud);
|
|
16
|
+
|
|
17
|
+
#define VC_STUB(name, ...) \
|
|
18
|
+
RCT_EXPORT_METHOD(name:(__VA_ARGS__) \
|
|
19
|
+
resolver:(RCTPromiseResolveBlock)resolve \
|
|
20
|
+
rejecter:(RCTPromiseRejectBlock)reject) \
|
|
21
|
+
{ reject(@"VC_NOT_IMPLEMENTED", @"VoipCloud SDK iOS bindings not yet shipped.", nil); }
|
|
22
|
+
|
|
23
|
+
VC_STUB(setLicense, NSString *token)
|
|
24
|
+
VC_STUB(getLicenseStatus)
|
|
25
|
+
VC_STUB(stopLicenseRefresh)
|
|
26
|
+
VC_STUB(init_, NSDictionary *config) // renamed because of init clash
|
|
27
|
+
VC_STUB(shutdown)
|
|
28
|
+
VC_STUB(register, NSDictionary *cfg)
|
|
29
|
+
VC_STUB(unregister, NSInteger accountId)
|
|
30
|
+
VC_STUB(makeCall, NSInteger accountId uri:(NSString *)uri)
|
|
31
|
+
VC_STUB(answer, NSInteger callId)
|
|
32
|
+
VC_STUB(hangup, NSInteger callId)
|
|
33
|
+
VC_STUB(hold, NSInteger callId)
|
|
34
|
+
VC_STUB(unhold, NSInteger callId)
|
|
35
|
+
VC_STUB(mute, NSInteger callId on:(BOOL)on)
|
|
36
|
+
VC_STUB(sendDtmf, NSInteger callId digits:(NSString *)digits)
|
|
37
|
+
VC_STUB(transferCall, NSInteger callId destinationUri:(NSString *)destinationUri)
|
|
38
|
+
VC_STUB(hangupAllCalls)
|
|
39
|
+
|
|
40
|
+
@end
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.License = void 0;
|
|
7
|
+
var _reactNative = require("react-native");
|
|
8
|
+
const Native = _reactNative.NativeModules.VoipCloud;
|
|
9
|
+
if (!Native) {
|
|
10
|
+
// Defer the error: only thrown if the consumer actually calls a
|
|
11
|
+
// method, so importing the package never crashes at load time.
|
|
12
|
+
console.warn('[react-native-voipcloud] Native module not linked. ' + 'Did you rebuild the Android app after adding the package?');
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* License management — all SDK functionality is gated behind a valid
|
|
17
|
+
* token. Customers paste their token (issued by your server) into the
|
|
18
|
+
* app; the app calls {@link set} once at startup and the SDK handles
|
|
19
|
+
* everything else, including periodic refresh.
|
|
20
|
+
*/
|
|
21
|
+
const License = exports.License = {
|
|
22
|
+
/**
|
|
23
|
+
* Apply a license token. Resolves on success, rejects with one of
|
|
24
|
+
* the granular `VC_*` codes if the token is malformed, signed by
|
|
25
|
+
* the wrong key, expired, suspended, or for a different app bundle.
|
|
26
|
+
*
|
|
27
|
+
* Side-effect: if the token's payload includes a `ref` field, the
|
|
28
|
+
* background refresher is started (or restarted with the new URL)
|
|
29
|
+
* automatically — the consumer never types a refresh URL.
|
|
30
|
+
*/
|
|
31
|
+
set(token) {
|
|
32
|
+
return Native.setLicense(token);
|
|
33
|
+
},
|
|
34
|
+
/**
|
|
35
|
+
* Query the current license state. Safe to call before `set`
|
|
36
|
+
* (returns valid=false, status="unset").
|
|
37
|
+
*/
|
|
38
|
+
status() {
|
|
39
|
+
return Native.getLicenseStatus();
|
|
40
|
+
},
|
|
41
|
+
/**
|
|
42
|
+
* Cancel the background refresher. Optional: most apps will
|
|
43
|
+
* never call this. Useful when the user logs out or the SDK is
|
|
44
|
+
* being torn down and you do not want a long-running daemon
|
|
45
|
+
* thread sitting in the process.
|
|
46
|
+
*/
|
|
47
|
+
stopRefresh() {
|
|
48
|
+
return Native.stopLicenseRefresh();
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
//# sourceMappingURL=License.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["_reactNative","require","Native","NativeModules","VoipCloud","console","warn","License","exports","set","token","setLicense","status","getLicenseStatus","stopRefresh","stopLicenseRefresh"],"sourceRoot":"../../src","sources":["License.ts"],"mappings":";;;;;;AAAA,IAAAA,YAAA,GAAAC,OAAA;AAGA,MAAMC,MAAM,GAAGC,0BAAa,CAACC,SAAS;AAEtC,IAAI,CAACF,MAAM,EAAE;EACT;EACA;EACAG,OAAO,CAACC,IAAI,CACR,qDAAqD,GACrD,2DACJ,CAAC;AACL;;AAEA;AACA;AACA;AACA;AACA;AACA;AACO,MAAMC,OAAO,GAAAC,OAAA,CAAAD,OAAA,GAAG;EACnB;AACJ;AACA;AACA;AACA;AACA;AACA;AACA;AACA;EACIE,GAAGA,CAACC,KAAa,EAAiB;IAC9B,OAAOR,MAAM,CAACS,UAAU,CAACD,KAAK,CAAC;EACnC,CAAC;EAED;AACJ;AACA;AACA;EACIE,MAAMA,CAAA,EAA2B;IAC7B,OAAOV,MAAM,CAACW,gBAAgB,CAAC,CAAC;EACpC,CAAC;EAED;AACJ;AACA;AACA;AACA;AACA;EACIC,WAAWA,CAAA,EAAkB;IACzB,OAAOZ,MAAM,CAACa,kBAAkB,CAAC,CAAC;EACtC;AACJ,CAAC","ignoreList":[]}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.VoipCloud = void 0;
|
|
7
|
+
var _reactNative = require("react-native");
|
|
8
|
+
var _License = require("./License");
|
|
9
|
+
var _events = require("./events");
|
|
10
|
+
const Native = _reactNative.NativeModules.VoipCloud;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Top-level VoIP SDK. Workflow:
|
|
14
|
+
*
|
|
15
|
+
* 1. {@link License.set} — install a token (paste from your portal).
|
|
16
|
+
* 2. {@link init} — start the PJSIP endpoint.
|
|
17
|
+
* 3. {@link register} — get an `accountId` back.
|
|
18
|
+
* 4. {@link makeCall} / {@link answer} / {@link hangup}.
|
|
19
|
+
*
|
|
20
|
+
* Every method returns a Promise. License-gate failures surface as a
|
|
21
|
+
* Promise rejection with `code = "VC_<NAME>"` matching the
|
|
22
|
+
* `PJ_EVOIPCLOUD_*` enum from `voipcloud_errno.h`.
|
|
23
|
+
*/
|
|
24
|
+
const VoipCloud = exports.VoipCloud = {
|
|
25
|
+
// ---------------------- License ---------------------------------
|
|
26
|
+
License: _License.License,
|
|
27
|
+
// ---------------------- Lifecycle -------------------------------
|
|
28
|
+
init(cfg = {}) {
|
|
29
|
+
return Native.init(cfg);
|
|
30
|
+
},
|
|
31
|
+
shutdown() {
|
|
32
|
+
return Native.shutdown();
|
|
33
|
+
},
|
|
34
|
+
// ---------------------- Accounts --------------------------------
|
|
35
|
+
/** Register a new SIP account. Resolves with the account id. */
|
|
36
|
+
register(account) {
|
|
37
|
+
return Native.register(account);
|
|
38
|
+
},
|
|
39
|
+
unregister(accountId) {
|
|
40
|
+
return Native.unregister(accountId);
|
|
41
|
+
},
|
|
42
|
+
// ---------------------- Calls -----------------------------------
|
|
43
|
+
/** Place an outbound call. Resolves with the new callId. */
|
|
44
|
+
makeCall(accountId, destinationUri) {
|
|
45
|
+
return Native.makeCall(accountId, destinationUri);
|
|
46
|
+
},
|
|
47
|
+
answer(callId) {
|
|
48
|
+
return Native.answer(callId);
|
|
49
|
+
},
|
|
50
|
+
hangup(callId) {
|
|
51
|
+
return Native.hangup(callId);
|
|
52
|
+
},
|
|
53
|
+
hold(callId) {
|
|
54
|
+
return Native.hold(callId);
|
|
55
|
+
},
|
|
56
|
+
unhold(callId) {
|
|
57
|
+
return Native.unhold(callId);
|
|
58
|
+
},
|
|
59
|
+
/**
|
|
60
|
+
* Mute / unmute the local microphone for a call. Implemented by
|
|
61
|
+
* stopping / starting the capture device's transmission to the
|
|
62
|
+
* call's active audio media — independent of `hold`. A
|
|
63
|
+
* `callMediaState` event fires after the toggle so the UI can
|
|
64
|
+
* mirror the new `isMuted` flag without polling.
|
|
65
|
+
*/
|
|
66
|
+
mute(callId, on) {
|
|
67
|
+
return Native.mute(callId, on);
|
|
68
|
+
},
|
|
69
|
+
sendDtmf(callId, digits) {
|
|
70
|
+
return Native.sendDtmf(callId, digits);
|
|
71
|
+
},
|
|
72
|
+
/**
|
|
73
|
+
* Blind-transfer a call (SIP REFER) to a new destination. The
|
|
74
|
+
* local leg moves to DISCONNECTED once the remote party accepts.
|
|
75
|
+
*/
|
|
76
|
+
transferCall(callId, destinationUri) {
|
|
77
|
+
return Native.transferCall(callId, destinationUri);
|
|
78
|
+
},
|
|
79
|
+
/**
|
|
80
|
+
* End every active call. Each call still emits its own
|
|
81
|
+
* `callState` event with state=DISCONNECTED.
|
|
82
|
+
*/
|
|
83
|
+
hangupAllCalls() {
|
|
84
|
+
return Native.hangupAllCalls();
|
|
85
|
+
},
|
|
86
|
+
// ---------------------- Events ----------------------------------
|
|
87
|
+
on: _events.on
|
|
88
|
+
};
|
|
89
|
+
//# sourceMappingURL=VoipCloud.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["_reactNative","require","_License","_events","Native","NativeModules","VoipCloud","exports","License","init","cfg","shutdown","register","account","unregister","accountId","makeCall","destinationUri","answer","callId","hangup","hold","unhold","mute","on","sendDtmf","digits","transferCall","hangupAllCalls"],"sourceRoot":"../../src","sources":["VoipCloud.ts"],"mappings":";;;;;;AAAA,IAAAA,YAAA,GAAAC,OAAA;AAEA,IAAAC,QAAA,GAAAD,OAAA;AACA,IAAAE,OAAA,GAAAF,OAAA;AAEA,MAAMG,MAAM,GAAGC,0BAAa,CAACC,SAAS;;AAEtC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,MAAMA,SAAS,GAAAC,OAAA,CAAAD,SAAA,GAAG;EACrB;EACAE,OAAO,EAAPA,gBAAO;EAEP;EACAC,IAAIA,CAACC,GAAe,GAAG,CAAC,CAAC,EAAiB;IACtC,OAAON,MAAM,CAACK,IAAI,CAACC,GAAG,CAAC;EAC3B,CAAC;EAEDC,QAAQA,CAAA,EAAkB;IACtB,OAAOP,MAAM,CAACO,QAAQ,CAAC,CAAC;EAC5B,CAAC;EAED;EACA;EACAC,QAAQA,CAACC,OAAsB,EAAmB;IAC9C,OAAOT,MAAM,CAACQ,QAAQ,CAACC,OAAO,CAAC;EACnC,CAAC;EAEDC,UAAUA,CAACC,SAAiB,EAAiB;IACzC,OAAOX,MAAM,CAACU,UAAU,CAACC,SAAS,CAAC;EACvC,CAAC;EAED;EACA;EACAC,QAAQA,CAACD,SAAiB,EAAEE,cAAsB,EAAmB;IACjE,OAAOb,MAAM,CAACY,QAAQ,CAACD,SAAS,EAAEE,cAAc,CAAC;EACrD,CAAC;EAEDC,MAAMA,CAACC,MAAc,EAAiB;IAClC,OAAOf,MAAM,CAACc,MAAM,CAACC,MAAM,CAAC;EAChC,CAAC;EAEDC,MAAMA,CAACD,MAAc,EAAiB;IAClC,OAAOf,MAAM,CAACgB,MAAM,CAACD,MAAM,CAAC;EAChC,CAAC;EAEDE,IAAIA,CAACF,MAAc,EAAiB;IAChC,OAAOf,MAAM,CAACiB,IAAI,CAACF,MAAM,CAAC;EAC9B,CAAC;EAEDG,MAAMA,CAACH,MAAc,EAAiB;IAClC,OAAOf,MAAM,CAACkB,MAAM,CAACH,MAAM,CAAC;EAChC,CAAC;EAED;AACJ;AACA;AACA;AACA;AACA;AACA;EACII,IAAIA,CAACJ,MAAc,EAAEK,EAAW,EAAiB;IAC7C,OAAOpB,MAAM,CAACmB,IAAI,CAACJ,MAAM,EAAEK,EAAE,CAAC;EAClC,CAAC;EAEDC,QAAQA,CAACN,MAAc,EAAEO,MAAc,EAAiB;IACpD,OAAOtB,MAAM,CAACqB,QAAQ,CAACN,MAAM,EAAEO,MAAM,CAAC;EAC1C,CAAC;EAED;AACJ;AACA;AACA;EACIC,YAAYA,CAACR,MAAc,EAAEF,cAAsB,EAAiB;IAChE,OAAOb,MAAM,CAACuB,YAAY,CAACR,MAAM,EAAEF,cAAc,CAAC;EACtD,CAAC;EAED;AACJ;AACA;AACA;EACIW,cAAcA,CAAA,EAAkB;IAC5B,OAAOxB,MAAM,CAACwB,cAAc,CAAC,CAAC;EAClC,CAAC;EAED;EACAJ,EAAE,EAAFA;AACJ,CAAC","ignoreList":[]}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.on = on;
|
|
7
|
+
var _reactNative = require("react-native");
|
|
8
|
+
const Native = _reactNative.NativeModules.VoipCloud;
|
|
9
|
+
|
|
10
|
+
// Lazy emitter — must point at the module to satisfy the contract
|
|
11
|
+
// NativeEventEmitter expects on RN 0.65+.
|
|
12
|
+
const emitter = Native ? new _reactNative.NativeEventEmitter(Native) : null;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Subscribe to a typed event. Returns a handle whose `remove()` must
|
|
16
|
+
* be called from a React `useEffect` cleanup to avoid leaks.
|
|
17
|
+
*/
|
|
18
|
+
function on(name, callback) {
|
|
19
|
+
if (!emitter) {
|
|
20
|
+
return {
|
|
21
|
+
remove: () => {}
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
const sub = emitter.addListener(name, callback);
|
|
25
|
+
return {
|
|
26
|
+
remove: () => sub.remove()
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=events.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["_reactNative","require","Native","NativeModules","VoipCloud","emitter","NativeEventEmitter","on","name","callback","remove","sub","addListener"],"sourceRoot":"../../src","sources":["events.ts"],"mappings":";;;;;;AAAA,IAAAA,YAAA,GAAAC,OAAA;AAGA,MAAMC,MAAM,GAAGC,0BAAa,CAACC,SAAS;;AAEtC;AACA;AACA,MAAMC,OAAO,GAAGH,MAAM,GAAG,IAAII,+BAAkB,CAACJ,MAAM,CAAC,GAAG,IAAI;;AAE9D;AACA;AACA;AACA;AACO,SAASK,EAAEA,CACdC,IAAO,EACPC,QAAsC,EAC1B;EACZ,IAAI,CAACJ,OAAO,EAAE;IACV,OAAO;MAAEK,MAAM,EAAEA,CAAA,KAAM,CAAC;IAAE,CAAC;EAC/B;EACA,MAAMC,GAAG,GAAGN,OAAO,CAACO,WAAW,CAACJ,IAAI,EAAEC,QAAgC,CAAC;EACvE,OAAO;IAAEC,MAAM,EAAEA,CAAA,KAAMC,GAAG,CAACD,MAAM,CAAC;EAAE,CAAC;AACzC","ignoreList":[]}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
Object.defineProperty(exports, "License", {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
get: function () {
|
|
9
|
+
return _License.License;
|
|
10
|
+
}
|
|
11
|
+
});
|
|
12
|
+
Object.defineProperty(exports, "VoipCloud", {
|
|
13
|
+
enumerable: true,
|
|
14
|
+
get: function () {
|
|
15
|
+
return _VoipCloud.VoipCloud;
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
Object.defineProperty(exports, "addEventListener", {
|
|
19
|
+
enumerable: true,
|
|
20
|
+
get: function () {
|
|
21
|
+
return _events.on;
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
var _VoipCloud = require("./VoipCloud");
|
|
25
|
+
var _License = require("./License");
|
|
26
|
+
var _events = require("./events");
|
|
27
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["_VoipCloud","require","_License","_events"],"sourceRoot":"../../src","sources":["index.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAAA,IAAAA,UAAA,GAAAC,OAAA;AACA,IAAAC,QAAA,GAAAD,OAAA;AACA,IAAAE,OAAA,GAAAF,OAAA","ignoreList":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":[],"sourceRoot":"../../src","sources":["types.ts"],"mappings":"","ignoreList":[]}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { NativeModules } from 'react-native';
|
|
2
|
+
const Native = NativeModules.VoipCloud;
|
|
3
|
+
if (!Native) {
|
|
4
|
+
// Defer the error: only thrown if the consumer actually calls a
|
|
5
|
+
// method, so importing the package never crashes at load time.
|
|
6
|
+
console.warn('[react-native-voipcloud] Native module not linked. ' + 'Did you rebuild the Android app after adding the package?');
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* License management — all SDK functionality is gated behind a valid
|
|
11
|
+
* token. Customers paste their token (issued by your server) into the
|
|
12
|
+
* app; the app calls {@link set} once at startup and the SDK handles
|
|
13
|
+
* everything else, including periodic refresh.
|
|
14
|
+
*/
|
|
15
|
+
export const License = {
|
|
16
|
+
/**
|
|
17
|
+
* Apply a license token. Resolves on success, rejects with one of
|
|
18
|
+
* the granular `VC_*` codes if the token is malformed, signed by
|
|
19
|
+
* the wrong key, expired, suspended, or for a different app bundle.
|
|
20
|
+
*
|
|
21
|
+
* Side-effect: if the token's payload includes a `ref` field, the
|
|
22
|
+
* background refresher is started (or restarted with the new URL)
|
|
23
|
+
* automatically — the consumer never types a refresh URL.
|
|
24
|
+
*/
|
|
25
|
+
set(token) {
|
|
26
|
+
return Native.setLicense(token);
|
|
27
|
+
},
|
|
28
|
+
/**
|
|
29
|
+
* Query the current license state. Safe to call before `set`
|
|
30
|
+
* (returns valid=false, status="unset").
|
|
31
|
+
*/
|
|
32
|
+
status() {
|
|
33
|
+
return Native.getLicenseStatus();
|
|
34
|
+
},
|
|
35
|
+
/**
|
|
36
|
+
* Cancel the background refresher. Optional: most apps will
|
|
37
|
+
* never call this. Useful when the user logs out or the SDK is
|
|
38
|
+
* being torn down and you do not want a long-running daemon
|
|
39
|
+
* thread sitting in the process.
|
|
40
|
+
*/
|
|
41
|
+
stopRefresh() {
|
|
42
|
+
return Native.stopLicenseRefresh();
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
//# sourceMappingURL=License.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["NativeModules","Native","VoipCloud","console","warn","License","set","token","setLicense","status","getLicenseStatus","stopRefresh","stopLicenseRefresh"],"sourceRoot":"../../src","sources":["License.ts"],"mappings":"AAAA,SAASA,aAAa,QAAQ,cAAc;AAG5C,MAAMC,MAAM,GAAGD,aAAa,CAACE,SAAS;AAEtC,IAAI,CAACD,MAAM,EAAE;EACT;EACA;EACAE,OAAO,CAACC,IAAI,CACR,qDAAqD,GACrD,2DACJ,CAAC;AACL;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,MAAMC,OAAO,GAAG;EACnB;AACJ;AACA;AACA;AACA;AACA;AACA;AACA;AACA;EACIC,GAAGA,CAACC,KAAa,EAAiB;IAC9B,OAAON,MAAM,CAACO,UAAU,CAACD,KAAK,CAAC;EACnC,CAAC;EAED;AACJ;AACA;AACA;EACIE,MAAMA,CAAA,EAA2B;IAC7B,OAAOR,MAAM,CAACS,gBAAgB,CAAC,CAAC;EACpC,CAAC;EAED;AACJ;AACA;AACA;AACA;AACA;EACIC,WAAWA,CAAA,EAAkB;IACzB,OAAOV,MAAM,CAACW,kBAAkB,CAAC,CAAC;EACtC;AACJ,CAAC","ignoreList":[]}
|