@sprucelabs/heartwood-view-controllers 118.0.30 → 118.0.32
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/build/esm/tests/MockRtcPeerConnection.d.ts +14 -6
- package/build/esm/tests/MockRtcPeerConnection.js +38 -8
- package/build/esm/webRtcStreaming/WebRtcConnection.d.ts +2 -2
- package/build/esm/webRtcStreaming/WebRtcConnection.js +20 -7
- package/build/esm/webRtcStreaming/WebRtcStreamer.d.ts +5 -5
- package/build/esm/webRtcStreaming/WebRtcStreamer.js +2 -4
- package/build/tests/MockRtcPeerConnection.d.ts +14 -6
- package/build/tests/MockRtcPeerConnection.js +38 -8
- package/build/webRtcStreaming/WebRtcConnection.d.ts +2 -2
- package/build/webRtcStreaming/WebRtcConnection.js +20 -7
- package/build/webRtcStreaming/WebRtcStreamer.d.ts +5 -5
- package/build/webRtcStreaming/WebRtcStreamer.js +2 -3
- package/package.json +3 -3
|
@@ -2,17 +2,21 @@ export default class MockRtcPeerConnection implements RTCPeerConnection {
|
|
|
2
2
|
static instance: MockRtcPeerConnection;
|
|
3
3
|
private static onCreateOfferHandler?;
|
|
4
4
|
private constructorOptions?;
|
|
5
|
-
private offerOptions?;
|
|
6
5
|
offer: RTCSessionDescription;
|
|
7
6
|
private lastAddedEventListener?;
|
|
7
|
+
private addedTransceivers;
|
|
8
|
+
private lastCreatedDataChannel?;
|
|
9
|
+
private tranceiverAndDataChannelCalls;
|
|
8
10
|
constructor(options?: RTCConfiguration);
|
|
9
11
|
assertCreatedOfferEquals(offer: RTCSessionDescriptionInit): void;
|
|
12
|
+
assertCreatedDataChannel(label: string, dataChannelDict?: RTCDataChannelInit): void;
|
|
13
|
+
assertTranceiversAndDataChannelCreatedInOrder(expected: string[]): void;
|
|
10
14
|
assertCreatedOfferSdpEquals(sdp: string): void;
|
|
11
15
|
assertCreatedWithOptions(expected: {
|
|
12
16
|
sdpSemantics: string;
|
|
13
17
|
iceServers: never[];
|
|
14
18
|
}): void;
|
|
15
|
-
|
|
19
|
+
assertAddedTranseivers(expected: RTCOfferOptions): void;
|
|
16
20
|
assertSetsResponseToConnectionLocalDescription(): void;
|
|
17
21
|
assertSetAnswerEquals(options: {
|
|
18
22
|
type: string;
|
|
@@ -20,7 +24,7 @@ export default class MockRtcPeerConnection implements RTCPeerConnection {
|
|
|
20
24
|
}): void;
|
|
21
25
|
assertTrackListenerSet(expected: () => void): void;
|
|
22
26
|
static onCreateOffer(cb?: () => void): void;
|
|
23
|
-
emitTrackAdded(): void;
|
|
27
|
+
emitTrackAdded(event?: RTCTrackEvent): void;
|
|
24
28
|
canTrickleIceCandidates: boolean | null;
|
|
25
29
|
connectionState: RTCPeerConnectionState;
|
|
26
30
|
currentLocalDescription: RTCSessionDescription | null;
|
|
@@ -44,11 +48,11 @@ export default class MockRtcPeerConnection implements RTCPeerConnection {
|
|
|
44
48
|
signalingState: RTCSignalingState;
|
|
45
49
|
addIceCandidate(_candidate?: unknown, _successCallback?: unknown, _failureCallback?: unknown): Promise<void>;
|
|
46
50
|
addTrack(_track: unknown, ..._streams: unknown[]): RTCRtpSender;
|
|
47
|
-
addTransceiver(
|
|
51
|
+
addTransceiver(trackOrKind: MediaStreamTrack | string, init?: RTCRtpTransceiverInit): RTCRtpTransceiver;
|
|
48
52
|
close(): void;
|
|
49
53
|
createAnswer(_successCallback?: unknown, _failureCallback?: unknown): Promise<any>;
|
|
50
|
-
createDataChannel(
|
|
51
|
-
createOffer(
|
|
54
|
+
createDataChannel(label: string, dataChannelDict?: RTCDataChannelInit): RTCDataChannel;
|
|
55
|
+
createOffer(_options?: RTCOfferOptions): Promise<any>;
|
|
52
56
|
getConfiguration(): RTCConfiguration;
|
|
53
57
|
getReceivers(): RTCRtpReceiver[];
|
|
54
58
|
getSenders(): RTCRtpSender[];
|
|
@@ -66,3 +70,7 @@ export default class MockRtcPeerConnection implements RTCPeerConnection {
|
|
|
66
70
|
removeEventListener(_type: unknown, _listener: unknown, _options?: unknown): void;
|
|
67
71
|
dispatchEvent(_event: Event): boolean;
|
|
68
72
|
}
|
|
73
|
+
export interface AddedTransceiver {
|
|
74
|
+
trackOrKind: MediaStreamTrack | string;
|
|
75
|
+
init?: RTCRtpTransceiverInit;
|
|
76
|
+
}
|
|
@@ -13,6 +13,8 @@ export default class MockRtcPeerConnection {
|
|
|
13
13
|
this.offer = {
|
|
14
14
|
[generateId()]: generateId(),
|
|
15
15
|
};
|
|
16
|
+
this.addedTransceivers = [];
|
|
17
|
+
this.tranceiverAndDataChannelCalls = [];
|
|
16
18
|
this.canTrickleIceCandidates = null;
|
|
17
19
|
this.connectionState = {};
|
|
18
20
|
this.currentLocalDescription = null;
|
|
@@ -40,14 +42,33 @@ export default class MockRtcPeerConnection {
|
|
|
40
42
|
assertCreatedOfferEquals(offer) {
|
|
41
43
|
assert.isEqualDeep(offer, this.offer, 'Did not return the generated offer');
|
|
42
44
|
}
|
|
45
|
+
assertCreatedDataChannel(label, dataChannelDict) {
|
|
46
|
+
assert.isEqualDeep(this.lastCreatedDataChannel, {
|
|
47
|
+
label,
|
|
48
|
+
dataChannelDict,
|
|
49
|
+
}, 'did not create expected data channel');
|
|
50
|
+
}
|
|
51
|
+
assertTranceiversAndDataChannelCreatedInOrder(expected) {
|
|
52
|
+
assert.isEqualDeep(this.tranceiverAndDataChannelCalls, expected, 'Did not call addTransceiver and createDataChannel in the expected order');
|
|
53
|
+
}
|
|
43
54
|
assertCreatedOfferSdpEquals(sdp) {
|
|
44
55
|
assert.isEqualDeep(this.offer.sdp, sdp, 'Did not return the generated offer sdp');
|
|
45
56
|
}
|
|
46
57
|
assertCreatedWithOptions(expected) {
|
|
47
58
|
assert.isEqualDeep(this.constructorOptions, expected, 'Did not pass default options to peer connection');
|
|
48
59
|
}
|
|
49
|
-
|
|
50
|
-
|
|
60
|
+
assertAddedTranseivers(expected) {
|
|
61
|
+
const expectedMapped = [];
|
|
62
|
+
for (const key in expected) {
|
|
63
|
+
const shouldAdd = expected[key];
|
|
64
|
+
if (shouldAdd) {
|
|
65
|
+
expectedMapped.push({
|
|
66
|
+
trackOrKind: key === 'offerToReceiveAudio' ? 'audio' : 'video',
|
|
67
|
+
init: { direction: 'recvonly' },
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
assert.isEqualDeep(this.addedTransceivers, expectedMapped, 'Did not add transceivers to peer connection');
|
|
51
72
|
}
|
|
52
73
|
assertSetsResponseToConnectionLocalDescription() {
|
|
53
74
|
assert.isEqualDeep(this.offer, this.localDescription, 'Did not set offer to local description');
|
|
@@ -64,10 +85,10 @@ export default class MockRtcPeerConnection {
|
|
|
64
85
|
static onCreateOffer(cb) {
|
|
65
86
|
this.onCreateOfferHandler = cb;
|
|
66
87
|
}
|
|
67
|
-
emitTrackAdded() {
|
|
88
|
+
emitTrackAdded(event) {
|
|
68
89
|
const lastListener = this.lastAddedEventListener;
|
|
69
90
|
if ((lastListener === null || lastListener === void 0 ? void 0 : lastListener.eventName) === 'track') {
|
|
70
|
-
lastListener.listener({});
|
|
91
|
+
lastListener.listener(event !== null && event !== void 0 ? event : {});
|
|
71
92
|
}
|
|
72
93
|
else {
|
|
73
94
|
assert.fail('Did not call connection.addEventListener with track listener');
|
|
@@ -81,7 +102,12 @@ export default class MockRtcPeerConnection {
|
|
|
81
102
|
addTrack(_track, ..._streams) {
|
|
82
103
|
return {};
|
|
83
104
|
}
|
|
84
|
-
addTransceiver(
|
|
105
|
+
addTransceiver(trackOrKind, init) {
|
|
106
|
+
this.addedTransceivers.push({
|
|
107
|
+
trackOrKind,
|
|
108
|
+
init,
|
|
109
|
+
});
|
|
110
|
+
this.tranceiverAndDataChannelCalls.push(`addTransceiver:${trackOrKind}`);
|
|
85
111
|
return {};
|
|
86
112
|
}
|
|
87
113
|
close() {
|
|
@@ -92,14 +118,18 @@ export default class MockRtcPeerConnection {
|
|
|
92
118
|
return {};
|
|
93
119
|
});
|
|
94
120
|
}
|
|
95
|
-
createDataChannel(
|
|
121
|
+
createDataChannel(label, dataChannelDict) {
|
|
122
|
+
this.lastCreatedDataChannel = {
|
|
123
|
+
label,
|
|
124
|
+
dataChannelDict,
|
|
125
|
+
};
|
|
126
|
+
this.tranceiverAndDataChannelCalls.push(`createDataChannel:${label}`);
|
|
96
127
|
return {};
|
|
97
128
|
}
|
|
98
129
|
//@ts-ignore
|
|
99
|
-
createOffer(
|
|
130
|
+
createOffer(_options) {
|
|
100
131
|
return __awaiter(this, void 0, void 0, function* () {
|
|
101
132
|
var _a;
|
|
102
|
-
this.offerOptions = options;
|
|
103
133
|
(_a = MockRtcPeerConnection.onCreateOfferHandler) === null || _a === void 0 ? void 0 : _a.call(MockRtcPeerConnection);
|
|
104
134
|
return this.offer;
|
|
105
135
|
});
|
|
@@ -4,7 +4,7 @@ export default class WebRtcConnectionImpl implements WebRtcConnection {
|
|
|
4
4
|
static Class: new () => WebRtcConnection;
|
|
5
5
|
static get RTCPeerConnection(): new (config: RTCConfiguration) => RTCPeerConnection | MockRtcPeerConnection;
|
|
6
6
|
static set RTCPeerConnection(value: new (config: RTCConfiguration) => RTCPeerConnection | MockRtcPeerConnection);
|
|
7
|
-
private
|
|
7
|
+
private stateChangeListeners;
|
|
8
8
|
static Connection(): WebRtcConnection;
|
|
9
9
|
createOffer(options: WebRtcVcPluginCreateOfferOptions): Promise<WebRtcCreateOfferResponse>;
|
|
10
10
|
private emitStateChange;
|
|
@@ -18,7 +18,7 @@ export interface WebRtcVcPluginCreateOfferOptions {
|
|
|
18
18
|
};
|
|
19
19
|
}
|
|
20
20
|
export type WebRtcConnectionState = 'createdOffer' | 'suppliedAnswer' | 'trackAdded';
|
|
21
|
-
export type WebRtcStateChangeHandler = (state: WebRtcConnectionState) => void | Promise<void>;
|
|
21
|
+
export type WebRtcStateChangeHandler = (state: WebRtcConnectionState, event?: RTCTrackEvent) => void | Promise<void>;
|
|
22
22
|
export interface WebRtcConnection {
|
|
23
23
|
offStateChange(listener: WebRtcStateChangeHandler): void;
|
|
24
24
|
createOffer(options: WebRtcVcPluginCreateOfferOptions): Promise<WebRtcCreateOfferResponse>;
|
|
@@ -11,7 +11,7 @@ import { assertOptions } from '@sprucelabs/schema';
|
|
|
11
11
|
import WebRtcStreamerImpl from './WebRtcStreamer.js';
|
|
12
12
|
export default class WebRtcConnectionImpl {
|
|
13
13
|
constructor() {
|
|
14
|
-
this.
|
|
14
|
+
this.stateChangeListeners = [];
|
|
15
15
|
}
|
|
16
16
|
static get RTCPeerConnection() {
|
|
17
17
|
return window.RTCPeerConnection;
|
|
@@ -31,9 +31,22 @@ export default class WebRtcConnectionImpl {
|
|
|
31
31
|
sdpSemantics: 'unified-plan',
|
|
32
32
|
iceServers: [],
|
|
33
33
|
});
|
|
34
|
-
const
|
|
34
|
+
const { offerToReceiveAudio, offerToReceiveVideo } = offerOptions;
|
|
35
|
+
if (offerToReceiveAudio) {
|
|
36
|
+
connection.addTransceiver('audio', { direction: 'recvonly' });
|
|
37
|
+
}
|
|
38
|
+
if (offerToReceiveVideo) {
|
|
39
|
+
connection.addTransceiver('video', { direction: 'recvonly' });
|
|
40
|
+
}
|
|
41
|
+
//must create this and add transceivers in order for Google Devices, if changing, make sure this
|
|
42
|
+
//stays the default behavior
|
|
43
|
+
connection.createDataChannel('dataSendChannel');
|
|
44
|
+
const offer = yield connection.createOffer({});
|
|
35
45
|
yield connection.setLocalDescription(offer);
|
|
36
46
|
void this.emitStateChange('createdOffer');
|
|
47
|
+
connection.addEventListener('track', (event) => {
|
|
48
|
+
void this.emitStateChange('trackAdded', event);
|
|
49
|
+
});
|
|
37
50
|
return {
|
|
38
51
|
offerSdp: offer,
|
|
39
52
|
streamer: WebRtcStreamerImpl.Streamer(connection, (status) => __awaiter(this, void 0, void 0, function* () {
|
|
@@ -42,17 +55,17 @@ export default class WebRtcConnectionImpl {
|
|
|
42
55
|
};
|
|
43
56
|
});
|
|
44
57
|
}
|
|
45
|
-
emitStateChange(state) {
|
|
58
|
+
emitStateChange(state, event) {
|
|
46
59
|
return __awaiter(this, void 0, void 0, function* () {
|
|
47
|
-
for (const handler of this.
|
|
48
|
-
yield handler(state);
|
|
60
|
+
for (const handler of this.stateChangeListeners) {
|
|
61
|
+
yield handler(state, event);
|
|
49
62
|
}
|
|
50
63
|
});
|
|
51
64
|
}
|
|
52
65
|
onStateChange(cb) {
|
|
53
|
-
this.
|
|
66
|
+
this.stateChangeListeners.push(cb);
|
|
54
67
|
}
|
|
55
68
|
offStateChange(listener) {
|
|
56
|
-
this.
|
|
69
|
+
this.stateChangeListeners = this.stateChangeListeners.filter((handler) => handler !== listener);
|
|
57
70
|
}
|
|
58
71
|
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { WebRtcStateChangeHandler } from './WebRtcConnection';
|
|
1
|
+
import { WebRtcStateChangeHandler as WebRtcStateChangeListener } from './WebRtcConnection';
|
|
2
2
|
export default class WebRtcStreamerImpl implements WebRtcStreamer {
|
|
3
3
|
private connection;
|
|
4
|
-
static Class?: new (connection: RTCPeerConnection, stateChangeHandlers?:
|
|
5
|
-
private
|
|
6
|
-
protected constructor(connection: RTCPeerConnection, stateChangeHandler?:
|
|
7
|
-
static Streamer(connection: RTCPeerConnection, stateChangeHandler?:
|
|
4
|
+
static Class?: new (connection: RTCPeerConnection, stateChangeHandlers?: WebRtcStateChangeListener) => WebRtcStreamer;
|
|
5
|
+
private setAnwserHandler?;
|
|
6
|
+
protected constructor(connection: RTCPeerConnection, stateChangeHandler?: WebRtcStateChangeListener);
|
|
7
|
+
static Streamer(connection: RTCPeerConnection, stateChangeHandler?: WebRtcStateChangeListener): WebRtcStreamer;
|
|
8
8
|
setAnswer(answerSdp: string): Promise<void>;
|
|
9
9
|
onTrack(cb: (event: RTCTrackEvent) => void): void;
|
|
10
10
|
}
|
|
@@ -11,7 +11,7 @@ import { assertOptions } from '@sprucelabs/schema';
|
|
|
11
11
|
export default class WebRtcStreamerImpl {
|
|
12
12
|
constructor(connection, stateChangeHandler) {
|
|
13
13
|
this.connection = connection;
|
|
14
|
-
this.
|
|
14
|
+
this.setAnwserHandler = stateChangeHandler;
|
|
15
15
|
}
|
|
16
16
|
static Streamer(connection, stateChangeHandler) {
|
|
17
17
|
var _a;
|
|
@@ -25,12 +25,10 @@ export default class WebRtcStreamerImpl {
|
|
|
25
25
|
type: 'answer',
|
|
26
26
|
sdp: answerSdp,
|
|
27
27
|
});
|
|
28
|
-
yield ((_a = this.
|
|
28
|
+
yield ((_a = this.setAnwserHandler) === null || _a === void 0 ? void 0 : _a.call(this, 'suppliedAnswer'));
|
|
29
29
|
});
|
|
30
30
|
}
|
|
31
31
|
onTrack(cb) {
|
|
32
|
-
var _a;
|
|
33
32
|
this.connection.addEventListener('track', cb);
|
|
34
|
-
void ((_a = this.stateChangeHandler) === null || _a === void 0 ? void 0 : _a.call(this, 'trackAdded'));
|
|
35
33
|
}
|
|
36
34
|
}
|
|
@@ -2,17 +2,21 @@ export default class MockRtcPeerConnection implements RTCPeerConnection {
|
|
|
2
2
|
static instance: MockRtcPeerConnection;
|
|
3
3
|
private static onCreateOfferHandler?;
|
|
4
4
|
private constructorOptions?;
|
|
5
|
-
private offerOptions?;
|
|
6
5
|
offer: RTCSessionDescription;
|
|
7
6
|
private lastAddedEventListener?;
|
|
7
|
+
private addedTransceivers;
|
|
8
|
+
private lastCreatedDataChannel?;
|
|
9
|
+
private tranceiverAndDataChannelCalls;
|
|
8
10
|
constructor(options?: RTCConfiguration);
|
|
9
11
|
assertCreatedOfferEquals(offer: RTCSessionDescriptionInit): void;
|
|
12
|
+
assertCreatedDataChannel(label: string, dataChannelDict?: RTCDataChannelInit): void;
|
|
13
|
+
assertTranceiversAndDataChannelCreatedInOrder(expected: string[]): void;
|
|
10
14
|
assertCreatedOfferSdpEquals(sdp: string): void;
|
|
11
15
|
assertCreatedWithOptions(expected: {
|
|
12
16
|
sdpSemantics: string;
|
|
13
17
|
iceServers: never[];
|
|
14
18
|
}): void;
|
|
15
|
-
|
|
19
|
+
assertAddedTranseivers(expected: RTCOfferOptions): void;
|
|
16
20
|
assertSetsResponseToConnectionLocalDescription(): void;
|
|
17
21
|
assertSetAnswerEquals(options: {
|
|
18
22
|
type: string;
|
|
@@ -20,7 +24,7 @@ export default class MockRtcPeerConnection implements RTCPeerConnection {
|
|
|
20
24
|
}): void;
|
|
21
25
|
assertTrackListenerSet(expected: () => void): void;
|
|
22
26
|
static onCreateOffer(cb?: () => void): void;
|
|
23
|
-
emitTrackAdded(): void;
|
|
27
|
+
emitTrackAdded(event?: RTCTrackEvent): void;
|
|
24
28
|
canTrickleIceCandidates: boolean | null;
|
|
25
29
|
connectionState: RTCPeerConnectionState;
|
|
26
30
|
currentLocalDescription: RTCSessionDescription | null;
|
|
@@ -44,11 +48,11 @@ export default class MockRtcPeerConnection implements RTCPeerConnection {
|
|
|
44
48
|
signalingState: RTCSignalingState;
|
|
45
49
|
addIceCandidate(_candidate?: unknown, _successCallback?: unknown, _failureCallback?: unknown): Promise<void>;
|
|
46
50
|
addTrack(_track: unknown, ..._streams: unknown[]): RTCRtpSender;
|
|
47
|
-
addTransceiver(
|
|
51
|
+
addTransceiver(trackOrKind: MediaStreamTrack | string, init?: RTCRtpTransceiverInit): RTCRtpTransceiver;
|
|
48
52
|
close(): void;
|
|
49
53
|
createAnswer(_successCallback?: unknown, _failureCallback?: unknown): Promise<any>;
|
|
50
|
-
createDataChannel(
|
|
51
|
-
createOffer(
|
|
54
|
+
createDataChannel(label: string, dataChannelDict?: RTCDataChannelInit): RTCDataChannel;
|
|
55
|
+
createOffer(_options?: RTCOfferOptions): Promise<any>;
|
|
52
56
|
getConfiguration(): RTCConfiguration;
|
|
53
57
|
getReceivers(): RTCRtpReceiver[];
|
|
54
58
|
getSenders(): RTCRtpSender[];
|
|
@@ -66,3 +70,7 @@ export default class MockRtcPeerConnection implements RTCPeerConnection {
|
|
|
66
70
|
removeEventListener(_type: unknown, _listener: unknown, _options?: unknown): void;
|
|
67
71
|
dispatchEvent(_event: Event): boolean;
|
|
68
72
|
}
|
|
73
|
+
export interface AddedTransceiver {
|
|
74
|
+
trackOrKind: MediaStreamTrack | string;
|
|
75
|
+
init?: RTCRtpTransceiverInit;
|
|
76
|
+
}
|
|
@@ -6,6 +6,8 @@ class MockRtcPeerConnection {
|
|
|
6
6
|
this.offer = {
|
|
7
7
|
[(0, test_utils_1.generateId)()]: (0, test_utils_1.generateId)(),
|
|
8
8
|
};
|
|
9
|
+
this.addedTransceivers = [];
|
|
10
|
+
this.tranceiverAndDataChannelCalls = [];
|
|
9
11
|
this.canTrickleIceCandidates = null;
|
|
10
12
|
this.connectionState = {};
|
|
11
13
|
this.currentLocalDescription = null;
|
|
@@ -33,14 +35,33 @@ class MockRtcPeerConnection {
|
|
|
33
35
|
assertCreatedOfferEquals(offer) {
|
|
34
36
|
test_utils_1.assert.isEqualDeep(offer, this.offer, 'Did not return the generated offer');
|
|
35
37
|
}
|
|
38
|
+
assertCreatedDataChannel(label, dataChannelDict) {
|
|
39
|
+
test_utils_1.assert.isEqualDeep(this.lastCreatedDataChannel, {
|
|
40
|
+
label,
|
|
41
|
+
dataChannelDict,
|
|
42
|
+
}, 'did not create expected data channel');
|
|
43
|
+
}
|
|
44
|
+
assertTranceiversAndDataChannelCreatedInOrder(expected) {
|
|
45
|
+
test_utils_1.assert.isEqualDeep(this.tranceiverAndDataChannelCalls, expected, 'Did not call addTransceiver and createDataChannel in the expected order');
|
|
46
|
+
}
|
|
36
47
|
assertCreatedOfferSdpEquals(sdp) {
|
|
37
48
|
test_utils_1.assert.isEqualDeep(this.offer.sdp, sdp, 'Did not return the generated offer sdp');
|
|
38
49
|
}
|
|
39
50
|
assertCreatedWithOptions(expected) {
|
|
40
51
|
test_utils_1.assert.isEqualDeep(this.constructorOptions, expected, 'Did not pass default options to peer connection');
|
|
41
52
|
}
|
|
42
|
-
|
|
43
|
-
|
|
53
|
+
assertAddedTranseivers(expected) {
|
|
54
|
+
const expectedMapped = [];
|
|
55
|
+
for (const key in expected) {
|
|
56
|
+
const shouldAdd = expected[key];
|
|
57
|
+
if (shouldAdd) {
|
|
58
|
+
expectedMapped.push({
|
|
59
|
+
trackOrKind: key === 'offerToReceiveAudio' ? 'audio' : 'video',
|
|
60
|
+
init: { direction: 'recvonly' },
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
test_utils_1.assert.isEqualDeep(this.addedTransceivers, expectedMapped, 'Did not add transceivers to peer connection');
|
|
44
65
|
}
|
|
45
66
|
assertSetsResponseToConnectionLocalDescription() {
|
|
46
67
|
test_utils_1.assert.isEqualDeep(this.offer, this.localDescription, 'Did not set offer to local description');
|
|
@@ -57,10 +78,10 @@ class MockRtcPeerConnection {
|
|
|
57
78
|
static onCreateOffer(cb) {
|
|
58
79
|
this.onCreateOfferHandler = cb;
|
|
59
80
|
}
|
|
60
|
-
emitTrackAdded() {
|
|
81
|
+
emitTrackAdded(event) {
|
|
61
82
|
const lastListener = this.lastAddedEventListener;
|
|
62
83
|
if (lastListener?.eventName === 'track') {
|
|
63
|
-
lastListener.listener({});
|
|
84
|
+
lastListener.listener(event ?? {});
|
|
64
85
|
}
|
|
65
86
|
else {
|
|
66
87
|
test_utils_1.assert.fail('Did not call connection.addEventListener with track listener');
|
|
@@ -72,7 +93,12 @@ class MockRtcPeerConnection {
|
|
|
72
93
|
addTrack(_track, ..._streams) {
|
|
73
94
|
return {};
|
|
74
95
|
}
|
|
75
|
-
addTransceiver(
|
|
96
|
+
addTransceiver(trackOrKind, init) {
|
|
97
|
+
this.addedTransceivers.push({
|
|
98
|
+
trackOrKind,
|
|
99
|
+
init,
|
|
100
|
+
});
|
|
101
|
+
this.tranceiverAndDataChannelCalls.push(`addTransceiver:${trackOrKind}`);
|
|
76
102
|
return {};
|
|
77
103
|
}
|
|
78
104
|
close() {
|
|
@@ -81,12 +107,16 @@ class MockRtcPeerConnection {
|
|
|
81
107
|
async createAnswer(_successCallback, _failureCallback) {
|
|
82
108
|
return {};
|
|
83
109
|
}
|
|
84
|
-
createDataChannel(
|
|
110
|
+
createDataChannel(label, dataChannelDict) {
|
|
111
|
+
this.lastCreatedDataChannel = {
|
|
112
|
+
label,
|
|
113
|
+
dataChannelDict,
|
|
114
|
+
};
|
|
115
|
+
this.tranceiverAndDataChannelCalls.push(`createDataChannel:${label}`);
|
|
85
116
|
return {};
|
|
86
117
|
}
|
|
87
118
|
//@ts-ignore
|
|
88
|
-
async createOffer(
|
|
89
|
-
this.offerOptions = options;
|
|
119
|
+
async createOffer(_options) {
|
|
90
120
|
MockRtcPeerConnection.onCreateOfferHandler?.();
|
|
91
121
|
return this.offer;
|
|
92
122
|
}
|
|
@@ -4,7 +4,7 @@ export default class WebRtcConnectionImpl implements WebRtcConnection {
|
|
|
4
4
|
static Class: new () => WebRtcConnection;
|
|
5
5
|
static get RTCPeerConnection(): new (config: RTCConfiguration) => RTCPeerConnection | MockRtcPeerConnection;
|
|
6
6
|
static set RTCPeerConnection(value: new (config: RTCConfiguration) => RTCPeerConnection | MockRtcPeerConnection);
|
|
7
|
-
private
|
|
7
|
+
private stateChangeListeners;
|
|
8
8
|
static Connection(): WebRtcConnection;
|
|
9
9
|
createOffer(options: WebRtcVcPluginCreateOfferOptions): Promise<WebRtcCreateOfferResponse>;
|
|
10
10
|
private emitStateChange;
|
|
@@ -18,7 +18,7 @@ export interface WebRtcVcPluginCreateOfferOptions {
|
|
|
18
18
|
};
|
|
19
19
|
}
|
|
20
20
|
export type WebRtcConnectionState = 'createdOffer' | 'suppliedAnswer' | 'trackAdded';
|
|
21
|
-
export type WebRtcStateChangeHandler = (state: WebRtcConnectionState) => void | Promise<void>;
|
|
21
|
+
export type WebRtcStateChangeHandler = (state: WebRtcConnectionState, event?: RTCTrackEvent) => void | Promise<void>;
|
|
22
22
|
export interface WebRtcConnection {
|
|
23
23
|
offStateChange(listener: WebRtcStateChangeHandler): void;
|
|
24
24
|
createOffer(options: WebRtcVcPluginCreateOfferOptions): Promise<WebRtcCreateOfferResponse>;
|
|
@@ -7,7 +7,7 @@ const schema_1 = require("@sprucelabs/schema");
|
|
|
7
7
|
const WebRtcStreamer_1 = __importDefault(require("./WebRtcStreamer"));
|
|
8
8
|
class WebRtcConnectionImpl {
|
|
9
9
|
constructor() {
|
|
10
|
-
this.
|
|
10
|
+
this.stateChangeListeners = [];
|
|
11
11
|
}
|
|
12
12
|
static get RTCPeerConnection() {
|
|
13
13
|
return window.RTCPeerConnection;
|
|
@@ -25,9 +25,22 @@ class WebRtcConnectionImpl {
|
|
|
25
25
|
sdpSemantics: 'unified-plan',
|
|
26
26
|
iceServers: [],
|
|
27
27
|
});
|
|
28
|
-
const
|
|
28
|
+
const { offerToReceiveAudio, offerToReceiveVideo } = offerOptions;
|
|
29
|
+
if (offerToReceiveAudio) {
|
|
30
|
+
connection.addTransceiver('audio', { direction: 'recvonly' });
|
|
31
|
+
}
|
|
32
|
+
if (offerToReceiveVideo) {
|
|
33
|
+
connection.addTransceiver('video', { direction: 'recvonly' });
|
|
34
|
+
}
|
|
35
|
+
//must create this and add transceivers in order for Google Devices, if changing, make sure this
|
|
36
|
+
//stays the default behavior
|
|
37
|
+
connection.createDataChannel('dataSendChannel');
|
|
38
|
+
const offer = await connection.createOffer({});
|
|
29
39
|
await connection.setLocalDescription(offer);
|
|
30
40
|
void this.emitStateChange('createdOffer');
|
|
41
|
+
connection.addEventListener('track', (event) => {
|
|
42
|
+
void this.emitStateChange('trackAdded', event);
|
|
43
|
+
});
|
|
31
44
|
return {
|
|
32
45
|
offerSdp: offer,
|
|
33
46
|
streamer: WebRtcStreamer_1.default.Streamer(connection, async (status) => {
|
|
@@ -35,16 +48,16 @@ class WebRtcConnectionImpl {
|
|
|
35
48
|
}),
|
|
36
49
|
};
|
|
37
50
|
}
|
|
38
|
-
async emitStateChange(state) {
|
|
39
|
-
for (const handler of this.
|
|
40
|
-
await handler(state);
|
|
51
|
+
async emitStateChange(state, event) {
|
|
52
|
+
for (const handler of this.stateChangeListeners) {
|
|
53
|
+
await handler(state, event);
|
|
41
54
|
}
|
|
42
55
|
}
|
|
43
56
|
onStateChange(cb) {
|
|
44
|
-
this.
|
|
57
|
+
this.stateChangeListeners.push(cb);
|
|
45
58
|
}
|
|
46
59
|
offStateChange(listener) {
|
|
47
|
-
this.
|
|
60
|
+
this.stateChangeListeners = this.stateChangeListeners.filter((handler) => handler !== listener);
|
|
48
61
|
}
|
|
49
62
|
}
|
|
50
63
|
exports.default = WebRtcConnectionImpl;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { WebRtcStateChangeHandler } from './WebRtcConnection';
|
|
1
|
+
import { WebRtcStateChangeHandler as WebRtcStateChangeListener } from './WebRtcConnection';
|
|
2
2
|
export default class WebRtcStreamerImpl implements WebRtcStreamer {
|
|
3
3
|
private connection;
|
|
4
|
-
static Class?: new (connection: RTCPeerConnection, stateChangeHandlers?:
|
|
5
|
-
private
|
|
6
|
-
protected constructor(connection: RTCPeerConnection, stateChangeHandler?:
|
|
7
|
-
static Streamer(connection: RTCPeerConnection, stateChangeHandler?:
|
|
4
|
+
static Class?: new (connection: RTCPeerConnection, stateChangeHandlers?: WebRtcStateChangeListener) => WebRtcStreamer;
|
|
5
|
+
private setAnwserHandler?;
|
|
6
|
+
protected constructor(connection: RTCPeerConnection, stateChangeHandler?: WebRtcStateChangeListener);
|
|
7
|
+
static Streamer(connection: RTCPeerConnection, stateChangeHandler?: WebRtcStateChangeListener): WebRtcStreamer;
|
|
8
8
|
setAnswer(answerSdp: string): Promise<void>;
|
|
9
9
|
onTrack(cb: (event: RTCTrackEvent) => void): void;
|
|
10
10
|
}
|
|
@@ -4,7 +4,7 @@ const schema_1 = require("@sprucelabs/schema");
|
|
|
4
4
|
class WebRtcStreamerImpl {
|
|
5
5
|
constructor(connection, stateChangeHandler) {
|
|
6
6
|
this.connection = connection;
|
|
7
|
-
this.
|
|
7
|
+
this.setAnwserHandler = stateChangeHandler;
|
|
8
8
|
}
|
|
9
9
|
static Streamer(connection, stateChangeHandler) {
|
|
10
10
|
return new (this.Class ?? this)(connection, stateChangeHandler);
|
|
@@ -15,11 +15,10 @@ class WebRtcStreamerImpl {
|
|
|
15
15
|
type: 'answer',
|
|
16
16
|
sdp: answerSdp,
|
|
17
17
|
});
|
|
18
|
-
await this.
|
|
18
|
+
await this.setAnwserHandler?.('suppliedAnswer');
|
|
19
19
|
}
|
|
20
20
|
onTrack(cb) {
|
|
21
21
|
this.connection.addEventListener('track', cb);
|
|
22
|
-
void this.stateChangeHandler?.('trackAdded');
|
|
23
22
|
}
|
|
24
23
|
}
|
|
25
24
|
exports.default = WebRtcStreamerImpl;
|
package/package.json
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"sideEffects": false,
|
|
14
14
|
"license": "MIT",
|
|
15
15
|
"description": "All the power of Heartwood in one, convenient package.",
|
|
16
|
-
"version": "118.0.
|
|
16
|
+
"version": "118.0.32",
|
|
17
17
|
"skill": {
|
|
18
18
|
"namespace": "HeartwoodViewControllers",
|
|
19
19
|
"commandOverrides": {
|
|
@@ -77,7 +77,7 @@
|
|
|
77
77
|
"@babel/plugin-transform-runtime": "^7.26.10",
|
|
78
78
|
"@babel/preset-env": "^7.26.9",
|
|
79
79
|
"@babel/preset-typescript": "^7.27.0",
|
|
80
|
-
"@sprucelabs/calendar-utils": "^42.0.
|
|
80
|
+
"@sprucelabs/calendar-utils": "^42.0.669",
|
|
81
81
|
"@sprucelabs/error": "^6.0.591",
|
|
82
82
|
"@sprucelabs/globby": "^2.0.502",
|
|
83
83
|
"@sprucelabs/mercury-core-events": "^26.0.52",
|
|
@@ -92,7 +92,7 @@
|
|
|
92
92
|
"babel-plugin-module-resolver": "^5.0.2",
|
|
93
93
|
"dot-prop": "^9.0.0",
|
|
94
94
|
"dotenv": "^16.4.7",
|
|
95
|
-
"esbuild": "^0.25.
|
|
95
|
+
"esbuild": "^0.25.2",
|
|
96
96
|
"object-set": "^1.0.1",
|
|
97
97
|
"terser-webpack-plugin": "5.3.1",
|
|
98
98
|
"uglify-js": "^3.19.3",
|