@tiledev/sdk-apptile-live-selling 0.8.1 → 0.9.0
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 +443 -34
- package/dist/auctionComments.d.ts +25 -0
- package/dist/auctionComments.d.ts.map +1 -0
- package/dist/auctionComments.js +28 -0
- package/dist/auctionComments.js.map +1 -0
- package/dist/auctionRules.d.ts +76 -0
- package/dist/auctionRules.d.ts.map +1 -0
- package/dist/auctionRules.js +106 -0
- package/dist/auctionRules.js.map +1 -0
- package/dist/auctions.d.ts.map +1 -1
- package/dist/auctions.js +19 -10
- package/dist/auctions.js.map +1 -1
- package/dist/client.d.ts +51 -2
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +123 -23
- package/dist/client.js.map +1 -1
- package/dist/commentHistory.d.ts +66 -0
- package/dist/commentHistory.d.ts.map +1 -0
- package/dist/commentHistory.js +125 -0
- package/dist/commentHistory.js.map +1 -0
- package/dist/engine.native.d.ts.map +1 -1
- package/dist/engine.native.js +17 -845
- package/dist/engine.native.js.map +1 -1
- package/dist/giveawayPrize.d.ts +13 -0
- package/dist/giveawayPrize.d.ts.map +1 -0
- package/dist/giveawayPrize.js +18 -0
- package/dist/giveawayPrize.js.map +1 -0
- package/dist/giveawayPrizeLines.d.ts +67 -0
- package/dist/giveawayPrizeLines.d.ts.map +1 -0
- package/dist/giveawayPrizeLines.js +48 -0
- package/dist/giveawayPrizeLines.js.map +1 -0
- package/dist/giveawayRoster.d.ts +53 -0
- package/dist/giveawayRoster.d.ts.map +1 -0
- package/dist/giveawayRoster.js +93 -0
- package/dist/giveawayRoster.js.map +1 -0
- package/dist/heldComments.d.ts +29 -0
- package/dist/heldComments.d.ts.map +1 -0
- package/dist/heldComments.js +61 -0
- package/dist/heldComments.js.map +1 -0
- package/dist/hiddenShows.d.ts +34 -0
- package/dist/hiddenShows.d.ts.map +1 -0
- package/dist/hiddenShows.js +42 -0
- package/dist/hiddenShows.js.map +1 -0
- package/dist/index.d.ts +17 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +86 -3
- package/dist/index.js.map +1 -1
- package/dist/liveShow.d.ts +58 -0
- package/dist/liveShow.d.ts.map +1 -0
- package/dist/liveShow.js +55 -0
- package/dist/liveShow.js.map +1 -0
- package/dist/pipWindow.d.ts +85 -0
- package/dist/pipWindow.d.ts.map +1 -0
- package/dist/pipWindow.js +88 -0
- package/dist/pipWindow.js.map +1 -0
- package/dist/polls.d.ts.map +1 -1
- package/dist/polls.js +3 -0
- package/dist/polls.js.map +1 -1
- package/dist/react/LiveSellingProvider.d.ts +10 -1
- package/dist/react/LiveSellingProvider.d.ts.map +1 -1
- package/dist/react/LiveSellingProvider.js +6 -2
- package/dist/react/LiveSellingProvider.js.map +1 -1
- package/dist/react/LiveVideoTarget.d.ts.map +1 -1
- package/dist/react/LiveVideoTarget.js +41 -3
- package/dist/react/LiveVideoTarget.js.map +1 -1
- package/dist/react/clocks.d.ts +29 -0
- package/dist/react/clocks.d.ts.map +1 -0
- package/dist/react/clocks.js +124 -0
- package/dist/react/clocks.js.map +1 -0
- package/dist/react/index.d.ts +7 -2
- package/dist/react/index.d.ts.map +1 -1
- package/dist/react/index.js +15 -1
- package/dist/react/index.js.map +1 -1
- package/dist/react/index.web.d.ts +9 -2
- package/dist/react/index.web.d.ts.map +1 -1
- package/dist/react/index.web.js +27 -4
- package/dist/react/index.web.js.map +1 -1
- package/dist/react/startSignIn.d.ts +3 -0
- package/dist/react/startSignIn.d.ts.map +1 -0
- package/dist/react/startSignIn.js +19 -0
- package/dist/react/startSignIn.js.map +1 -0
- package/dist/react/useAuctionBidGate.d.ts +54 -4
- package/dist/react/useAuctionBidGate.d.ts.map +1 -1
- package/dist/react/useAuctionBidGate.js +169 -25
- package/dist/react/useAuctionBidGate.js.map +1 -1
- package/dist/react/useAuctionWins.d.ts +9 -1
- package/dist/react/useAuctionWins.d.ts.map +1 -1
- package/dist/react/useAuctionWins.js +9 -3
- package/dist/react/useAuctionWins.js.map +1 -1
- package/dist/react/useGiveawayEntry.d.ts +59 -0
- package/dist/react/useGiveawayEntry.d.ts.map +1 -0
- package/dist/react/useGiveawayEntry.js +170 -0
- package/dist/react/useGiveawayEntry.js.map +1 -0
- package/dist/react/useGiveawayPrize.d.ts +12 -0
- package/dist/react/useGiveawayPrize.d.ts.map +1 -0
- package/dist/react/useGiveawayPrize.js +53 -0
- package/dist/react/useGiveawayPrize.js.map +1 -0
- package/dist/react/useHiddenShows.d.ts +10 -0
- package/dist/react/useHiddenShows.d.ts.map +1 -0
- package/dist/react/useHiddenShows.js +30 -0
- package/dist/react/useHiddenShows.js.map +1 -0
- package/dist/react/useLiveSession.d.ts +7 -3
- package/dist/react/useLiveSession.d.ts.map +1 -1
- package/dist/react/useLiveSession.js +522 -157
- package/dist/react/useLiveSession.js.map +1 -1
- package/dist/react/useLiveShow.d.ts +3 -0
- package/dist/react/useLiveShow.d.ts.map +1 -0
- package/dist/react/useLiveShow.js +21 -0
- package/dist/react/useLiveShow.js.map +1 -0
- package/dist/react/useLiveStreams.d.ts.map +1 -1
- package/dist/react/useLiveStreams.js +6 -2
- package/dist/react/useLiveStreams.js.map +1 -1
- package/dist/react/useOngoingLive.d.ts +1 -0
- package/dist/react/useOngoingLive.d.ts.map +1 -1
- package/dist/react/useOngoingLive.js +7 -1
- package/dist/react/useOngoingLive.js.map +1 -1
- package/dist/react/useReplays.d.ts +12 -0
- package/dist/react/useReplays.d.ts.map +1 -1
- package/dist/react/useReplays.js +56 -24
- package/dist/react/useReplays.js.map +1 -1
- package/dist/react/useStreamInfo.d.ts +13 -2
- package/dist/react/useStreamInfo.d.ts.map +1 -1
- package/dist/react/useStreamInfo.js +31 -5
- package/dist/react/useStreamInfo.js.map +1 -1
- package/dist/replayPages.d.ts +31 -0
- package/dist/replayPages.d.ts.map +1 -0
- package/dist/replayPages.js +34 -0
- package/dist/replayPages.js.map +1 -0
- package/dist/replays.d.ts +7 -0
- package/dist/replays.d.ts.map +1 -1
- package/dist/replays.js +52 -22
- package/dist/replays.js.map +1 -1
- package/dist/session.d.ts +39 -6
- package/dist/session.d.ts.map +1 -1
- package/dist/session.js +209 -22
- package/dist/session.js.map +1 -1
- package/dist/sessionTypes.d.ts +190 -14
- package/dist/sessionTypes.d.ts.map +1 -1
- package/dist/sessionTypes.js +2 -1
- package/dist/sessionTypes.js.map +1 -1
- package/dist/shopifyCommerce.d.ts +149 -0
- package/dist/shopifyCommerce.d.ts.map +1 -0
- package/dist/shopifyCommerce.js +123 -0
- package/dist/shopifyCommerce.js.map +1 -0
- package/dist/shopifyIdentity.d.ts +51 -0
- package/dist/shopifyIdentity.d.ts.map +1 -0
- package/dist/shopifyIdentity.js +52 -0
- package/dist/shopifyIdentity.js.map +1 -0
- package/dist/shopifyIds.d.ts +9 -0
- package/dist/shopifyIds.d.ts.map +1 -0
- package/dist/shopifyIds.js +18 -0
- package/dist/shopifyIds.js.map +1 -0
- package/dist/showLinks.d.ts +24 -0
- package/dist/showLinks.d.ts.map +1 -0
- package/dist/showLinks.js +23 -0
- package/dist/showLinks.js.map +1 -0
- package/dist/showLots.d.ts +28 -0
- package/dist/showLots.d.ts.map +1 -0
- package/dist/showLots.js +51 -0
- package/dist/showLots.js.map +1 -0
- package/dist/showNames.d.ts +45 -0
- package/dist/showNames.d.ts.map +1 -0
- package/dist/showNames.js +74 -0
- package/dist/showNames.js.map +1 -0
- package/dist/streams.d.ts +27 -1
- package/dist/streams.d.ts.map +1 -1
- package/dist/streams.js +84 -21
- package/dist/streams.js.map +1 -1
- package/dist/types.d.ts +192 -8
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +2 -1
- package/dist/types.js.map +1 -1
- package/dist/wire.d.ts +31 -0
- package/dist/wire.d.ts.map +1 -1
- package/dist/wire.js +25 -0
- package/dist/wire.js.map +1 -1
- package/dist/zego.d.ts +3 -1
- package/dist/zego.d.ts.map +1 -1
- package/dist/zego.js +1 -1
- package/dist/zegoEngine.d.ts +168 -0
- package/dist/zegoEngine.d.ts.map +1 -0
- package/dist/zegoEngine.js +1052 -0
- package/dist/zegoEngine.js.map +1 -0
- package/package.json +3 -2
package/dist/engine.native.js
CHANGED
|
@@ -4,854 +4,26 @@ exports.engine = void 0;
|
|
|
4
4
|
/**
|
|
5
5
|
* Live engine — NATIVE build (iOS / Android), driving `zego-express-engine-reactnative`.
|
|
6
6
|
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* and destroyed per mount (which caused the re-login churn the source blames for an Android
|
|
10
|
-
* NetworkCallback leak).
|
|
7
|
+
* Only the wiring lives here: the engine itself is `ZegoLiveEngine` in `zegoEngine.ts`, which takes
|
|
8
|
+
* the native pieces as arguments so it can be tested in Node. This file hands it the real ones.
|
|
11
9
|
*
|
|
12
|
-
* The Zego SDK is an OPTIONAL peer, pulled in with a lazy `require()`
|
|
13
|
-
* carries no static import of it — that keeps the native SDK out of every
|
|
14
|
-
* the pure `tsc --noEmit` pass without the Zego types installed. Metro
|
|
15
|
-
* `engine.ts` (a no-op) everywhere else; keep the two signatures in
|
|
10
|
+
* The Zego SDK is an OPTIONAL peer, pulled in with a lazy `require()` the first time the engine is
|
|
11
|
+
* used, so this file carries no static import of it — that keeps the native SDK out of every
|
|
12
|
+
* non-native bundle and lets the pure `tsc --noEmit` pass without the Zego types installed. Metro
|
|
13
|
+
* resolves this file on-device and `engine.ts` (a no-op) everywhere else; keep the two signatures in
|
|
14
|
+
* lock-step.
|
|
16
15
|
*
|
|
17
|
-
*
|
|
18
|
-
* app id comes from `configure({ zegoAppId })` rather than a config global.
|
|
19
|
-
*
|
|
20
|
-
* The engine also feeds the system picture-in-picture module — which stream is playing, and nothing
|
|
21
|
-
* more. It has to be told here rather than by the session, because only this file knows when the
|
|
22
|
-
* played id actually changes: a co-host mixer swap moves it from `{id}` to `{id}_mixed` with no
|
|
23
|
-
* involvement from React at all.
|
|
16
|
+
* The platform-level Zego app id comes from `configure({ zegoAppId })` rather than a config global.
|
|
24
17
|
*/
|
|
25
18
|
const react_native_1 = require("react-native");
|
|
26
|
-
const client_1 = require("./client");
|
|
27
|
-
const wire_1 = require("./wire");
|
|
28
|
-
const commentLinks_1 = require("./commentLinks");
|
|
29
19
|
const sdk_apptile_live_selling_native_1 = require("@tiledev/sdk-apptile-live-selling-native");
|
|
30
|
-
const
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
this.queue = Promise.resolve();
|
|
40
|
-
this.listeners = new Set();
|
|
41
|
-
this.joined = null;
|
|
42
|
-
this.playingStreamId = null;
|
|
43
|
-
this.boundTag = null;
|
|
44
|
-
this.playingTag = null;
|
|
45
|
-
this.mixerActive = false;
|
|
46
|
-
this.guest = null;
|
|
47
|
-
this.previewTag = null;
|
|
48
|
-
this.viewerNameOverride = null;
|
|
49
|
-
this.commentSeq = 0;
|
|
50
|
-
this.mutedDeviceIds = [];
|
|
51
|
-
}
|
|
52
|
-
subscribe(listener) {
|
|
53
|
-
this.listeners.add(listener);
|
|
54
|
-
return () => {
|
|
55
|
-
this.listeners.delete(listener);
|
|
56
|
-
};
|
|
57
|
-
}
|
|
58
|
-
emit(event) {
|
|
59
|
-
for (const listener of this.listeners)
|
|
60
|
-
listener(event);
|
|
61
|
-
}
|
|
62
|
-
/**
|
|
63
|
-
* The loaded SDK. Only valid after `createEngine`, and every caller below is downstream of it —
|
|
64
|
-
* throwing beats the `undefined is not a constructor` a missing enum would produce deeper in.
|
|
65
|
-
*/
|
|
66
|
-
get Zego() {
|
|
67
|
-
if (!this.Z)
|
|
68
|
-
throw new Error('Zego SDK is not loaded');
|
|
69
|
-
return this.Z;
|
|
70
|
-
}
|
|
71
|
-
/** The default export is the engine class; the enums/structs are named exports. */
|
|
72
|
-
get Engine() {
|
|
73
|
-
var _a;
|
|
74
|
-
const mod = this.Zego;
|
|
75
|
-
return ((_a = mod === null || mod === void 0 ? void 0 : mod.default) !== null && _a !== void 0 ? _a : mod);
|
|
76
|
-
}
|
|
77
|
-
async ensureEngine() {
|
|
78
|
-
if (this.engineReady)
|
|
79
|
-
return;
|
|
80
|
-
if (!this.creating)
|
|
81
|
-
this.creating = this.createEngine();
|
|
82
|
-
try {
|
|
83
|
-
await this.creating;
|
|
84
|
-
}
|
|
85
|
-
finally {
|
|
86
|
-
this.creating = null;
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
async createEngine() {
|
|
90
|
-
var _a;
|
|
91
|
-
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
92
|
-
this.Z = require('zego-express-engine-reactnative');
|
|
93
|
-
const Engine = this.Engine;
|
|
94
|
-
const { ZegoScenario } = this.Zego;
|
|
95
|
-
// The native engine outlives this module, so adopt an existing instance rather than creating a
|
|
96
|
-
// second — "multiple instances" is a documented failure.
|
|
97
|
-
let existing = null;
|
|
98
|
-
try {
|
|
99
|
-
existing = Engine.instance();
|
|
100
|
-
}
|
|
101
|
-
catch {
|
|
102
|
-
existing = null;
|
|
103
|
-
}
|
|
104
|
-
if (!existing) {
|
|
105
|
-
// appSign empty is the documented pairing for token auth; the token rides on the room config.
|
|
106
|
-
await Engine.createEngineWithProfile({
|
|
107
|
-
appID: (_a = (0, client_1.getConfig)().zegoAppId) !== null && _a !== void 0 ? _a : 0,
|
|
108
|
-
appSign: '',
|
|
109
|
-
scenario: ZegoScenario.Default,
|
|
110
|
-
});
|
|
111
|
-
}
|
|
112
|
-
// After the engine exists and before anything plays, and every time rather than only after a
|
|
113
|
-
// fresh create: the engine outlives this module, so an adopted one may never have been configured
|
|
114
|
-
// by this process. The native side ignores a second call.
|
|
115
|
-
try {
|
|
116
|
-
await sdk_apptile_live_selling_native_1.livePip.configure();
|
|
117
|
-
}
|
|
118
|
-
catch (caught) {
|
|
119
|
-
// A live stream without picture-in-picture is still a working live stream.
|
|
120
|
-
(0, client_1.getLogger)().error(caught, { at: 'liveEngine.configurePip' });
|
|
121
|
-
}
|
|
122
|
-
this.attachListeners();
|
|
123
|
-
this.engineReady = true;
|
|
124
|
-
}
|
|
125
|
-
/**
|
|
126
|
-
* Zego stops delivering video once the app leaves the foreground unless this is set. iOS only;
|
|
127
|
-
* Android's PIP window is the activity itself, which stays visible and keeps decoding.
|
|
128
|
-
*/
|
|
129
|
-
async setBackgroundVideoEnabled(enabled) {
|
|
130
|
-
if (!this.engineReady)
|
|
131
|
-
return;
|
|
132
|
-
if (react_native_1.Platform.OS !== 'ios')
|
|
133
|
-
return;
|
|
134
|
-
await this.Engine.instance().callExperimentalAPI(JSON.stringify({ method: 'liveroom.video.enable_ios_multitask', params: { enable: enabled } }));
|
|
135
|
-
}
|
|
136
|
-
attachListeners() {
|
|
137
|
-
const engine = this.Engine.instance();
|
|
138
|
-
const { ZegoUpdateType } = this.Zego;
|
|
139
|
-
// Clear first: attaching twice would deliver every comment and reaction twice over.
|
|
140
|
-
for (const event of [
|
|
141
|
-
'roomStateUpdate',
|
|
142
|
-
'roomStreamUpdate',
|
|
143
|
-
'roomOnlineUserCountUpdate',
|
|
144
|
-
'playerMediaEvent',
|
|
145
|
-
'roomStreamExtraInfoUpdate',
|
|
146
|
-
'IMRecvBarrageMessage',
|
|
147
|
-
'IMRecvCustomCommand',
|
|
148
|
-
'IMRecvBroadcastMessage',
|
|
149
|
-
]) {
|
|
150
|
-
try {
|
|
151
|
-
engine.off(event, undefined);
|
|
152
|
-
}
|
|
153
|
-
catch {
|
|
154
|
-
// Nothing attached yet.
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
engine.on('roomStateUpdate', (_roomId, stateVal) => {
|
|
158
|
-
this.emit({ type: 'roomState', connected: stateVal === 2 });
|
|
159
|
-
if (stateVal === 2)
|
|
160
|
-
this.announceJoin();
|
|
161
|
-
});
|
|
162
|
-
engine.on('roomStreamUpdate', (_roomId, updateType, streamList) => {
|
|
163
|
-
const ids = (0, wire_1.arr)(streamList).map((entry) => (0, wire_1.str)((0, wire_1.get)(entry, 'streamID')));
|
|
164
|
-
const isHost = ids.some((id) => { var _a, _b; return id === ((_a = this.joined) === null || _a === void 0 ? void 0 : _a.streamingId) || id === ((_b = this.joined) === null || _b === void 0 ? void 0 : _b.mixedStreamId); });
|
|
165
|
-
if (!isHost)
|
|
166
|
-
return;
|
|
167
|
-
this.emit({ type: 'publisher', publishing: updateType === ZegoUpdateType.Add });
|
|
168
|
-
});
|
|
169
|
-
engine.on('roomOnlineUserCountUpdate', (_roomId, count) => {
|
|
170
|
-
this.emit({ type: 'viewers', count });
|
|
171
|
-
});
|
|
172
|
-
engine.on('playerMediaEvent', (_streamId, event) => {
|
|
173
|
-
// 4/6 = video break/resume, 5/7 = audio break/resume. One field per event.
|
|
174
|
-
if (event === 4)
|
|
175
|
-
this.emit({ type: 'hostMedia', kind: 'video', broken: true });
|
|
176
|
-
if (event === 6)
|
|
177
|
-
this.emit({ type: 'hostMedia', kind: 'video', broken: false });
|
|
178
|
-
if (event === 5)
|
|
179
|
-
this.emit({ type: 'hostMedia', kind: 'audio', broken: true });
|
|
180
|
-
if (event === 7)
|
|
181
|
-
this.emit({ type: 'hostMedia', kind: 'audio', broken: false });
|
|
182
|
-
});
|
|
183
|
-
engine.on('playerQualityUpdate', (streamId, quality) => {
|
|
184
|
-
var _a;
|
|
185
|
-
if (streamId !== this.playingStreamId)
|
|
186
|
-
return;
|
|
187
|
-
this.emit({ type: 'hostVideo', receiving: ((_a = (0, wire_1.num)((0, wire_1.get)(quality, 'videoRecvFPS'))) !== null && _a !== void 0 ? _a : 0) > 0 });
|
|
188
|
-
});
|
|
189
|
-
engine.on('roomStreamExtraInfoUpdate', (_roomId, streamList) => {
|
|
190
|
-
const extra = (0, wire_1.get)((0, wire_1.arr)(streamList)[0], 'extraInfo');
|
|
191
|
-
if (!extra)
|
|
192
|
-
return;
|
|
193
|
-
this.handleExtraInfo(extra);
|
|
194
|
-
});
|
|
195
|
-
engine.on('IMRecvBarrageMessage', (_roomId, messageList) => {
|
|
196
|
-
this.handleBarrage((0, wire_1.arr)(messageList)[0]);
|
|
197
|
-
});
|
|
198
|
-
engine.on('IMRecvCustomCommand', (_roomId, _from, command) => {
|
|
199
|
-
this.handleCommand(command);
|
|
200
|
-
});
|
|
201
|
-
engine.on('IMRecvBroadcastMessage', (_roomId, messageList) => {
|
|
202
|
-
var _a;
|
|
203
|
-
// `sendTime` is the host's clock — the only reference an auction deadline can be read against.
|
|
204
|
-
const first = (0, wire_1.arr)(messageList)[0];
|
|
205
|
-
this.handleBroadcast((0, wire_1.get)(first, 'message'), (_a = (0, wire_1.num)((0, wire_1.get)(first, 'sendTime'))) !== null && _a !== void 0 ? _a : 0);
|
|
206
|
-
});
|
|
207
|
-
}
|
|
208
|
-
handleExtraInfo(raw) {
|
|
209
|
-
const payload = (0, wire_1.parseJson)(raw);
|
|
210
|
-
if (!(0, wire_1.isRecord)(payload))
|
|
211
|
-
return;
|
|
212
|
-
const lot = () => { var _a; return (_a = (0, wire_1.str)((0, wire_1.path)(payload, 'data', 'store_product_id'))) !== null && _a !== void 0 ? _a : (0, wire_1.str)((0, wire_1.path)(payload, 'data', 'product_id')); };
|
|
213
|
-
switch ((0, wire_1.str)(payload.event)) {
|
|
214
|
-
case 'PRODUCT_CHANGE': {
|
|
215
|
-
const id = lot();
|
|
216
|
-
if (id)
|
|
217
|
-
this.emit({ type: 'productChange', storeProductId: id });
|
|
218
|
-
return;
|
|
219
|
-
}
|
|
220
|
-
case 'DELETE_PRODUCT': {
|
|
221
|
-
const id = lot();
|
|
222
|
-
if (id)
|
|
223
|
-
this.emit({ type: 'productRemoved', storeProductId: id });
|
|
224
|
-
return;
|
|
225
|
-
}
|
|
226
|
-
case 'MULTIPLIER_CHANGE': {
|
|
227
|
-
const multiplier = (0, wire_1.num)(payload.count);
|
|
228
|
-
this.emit({
|
|
229
|
-
type: 'viewerMultiplier',
|
|
230
|
-
multiplier: multiplier !== null && multiplier > 0 ? multiplier : 1,
|
|
231
|
-
});
|
|
232
|
-
return;
|
|
233
|
-
}
|
|
234
|
-
default:
|
|
235
|
-
this.emit({ type: 'unknown', channel: 'extraInfo', payload });
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
handleBarrage(message) {
|
|
239
|
-
var _a, _b, _c;
|
|
240
|
-
const payload = (0, wire_1.parseJson)((0, wire_1.get)(message, 'message'));
|
|
241
|
-
if (!(0, wire_1.isRecord)(payload))
|
|
242
|
-
return;
|
|
243
|
-
// The host mutes a viewer for everyone by flagging their messages, not by dropping them.
|
|
244
|
-
if (payload.muted === true)
|
|
245
|
-
return;
|
|
246
|
-
// `payload.name` wins: a bid announcement is relayed by the host's own Zego identity, so
|
|
247
|
-
// `fromUser.userName` there is the HOST's name, not the bidder's.
|
|
248
|
-
const fromUser = (0, wire_1.str)((0, wire_1.path)(message, 'fromUser', 'userName'));
|
|
249
|
-
const userName = (_b = (_a = (0, wire_1.str)(payload.name)) !== null && _a !== void 0 ? _a : fromUser) !== null && _b !== void 0 ? _b : 'Anonymous';
|
|
250
|
-
this.emit({
|
|
251
|
-
type: 'comment',
|
|
252
|
-
comment: this.makeComment((_c = (0, wire_1.str)(payload.comment)) !== null && _c !== void 0 ? _c : '', userName, payload.source, undefined, false, payload.urlPreview),
|
|
253
|
-
});
|
|
254
|
-
}
|
|
255
|
-
makeComment(text, userName, source, tipAmount, isOwn, urlPreview) {
|
|
256
|
-
const known = source === 'HOST' || source === 'MODERATOR' || source === 'TIP' ? source : 'USER';
|
|
257
|
-
this.commentSeq += 1;
|
|
258
|
-
return {
|
|
259
|
-
id: `c${this.commentSeq}`,
|
|
260
|
-
text,
|
|
261
|
-
userName,
|
|
262
|
-
source: known,
|
|
263
|
-
tipAmount,
|
|
264
|
-
urlPreview: (0, commentLinks_1.toUrlPreview)(urlPreview),
|
|
265
|
-
isOwn,
|
|
266
|
-
};
|
|
267
|
-
}
|
|
268
|
-
handleCommand(raw) {
|
|
269
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
|
|
270
|
-
const payload = (0, wire_1.parseJson)(raw);
|
|
271
|
-
if (!(0, wire_1.isRecord)(payload))
|
|
272
|
-
return;
|
|
273
|
-
switch ((0, wire_1.str)(payload.type)) {
|
|
274
|
-
case 'REACTION_ANNOUCEMENT':
|
|
275
|
-
this.emit({
|
|
276
|
-
type: 'reaction',
|
|
277
|
-
reactionUrl: (_a = (0, wire_1.str)(payload.reactionUrl)) !== null && _a !== void 0 ? _a : '',
|
|
278
|
-
userName: (_b = (0, wire_1.str)(payload.userName)) !== null && _b !== void 0 ? _b : 'Anonymous',
|
|
279
|
-
});
|
|
280
|
-
return;
|
|
281
|
-
case 'CART_ANNOUCEMENT':
|
|
282
|
-
this.emit({
|
|
283
|
-
type: 'cartAnnouncement',
|
|
284
|
-
productTitle: (_c = (0, wire_1.str)(payload.productTitle)) !== null && _c !== void 0 ? _c : '',
|
|
285
|
-
userName: (_d = (0, wire_1.str)(payload.userName)) !== null && _d !== void 0 ? _d : 'Anonymous',
|
|
286
|
-
sellId: (_e = (0, wire_1.str)(payload.sellId)) !== null && _e !== void 0 ? _e : null,
|
|
287
|
-
});
|
|
288
|
-
return;
|
|
289
|
-
case 'DONATION_ANNOUCEMENT':
|
|
290
|
-
this.emit({
|
|
291
|
-
type: 'comment',
|
|
292
|
-
comment: this.makeComment('Sent a tip', (_f = (0, wire_1.str)(payload.userName)) !== null && _f !== void 0 ? _f : 'Anonymous', 'TIP', (_g = (0, wire_1.str)(payload.donationAmount)) !== null && _g !== void 0 ? _g : undefined, false),
|
|
293
|
-
});
|
|
294
|
-
return;
|
|
295
|
-
case 'PRODUCT_SOLD_ANNOUNCEMENT':
|
|
296
|
-
this.emit({
|
|
297
|
-
type: 'sold',
|
|
298
|
-
announcement: {
|
|
299
|
-
productName: (_h = (0, wire_1.str)(payload.productName)) !== null && _h !== void 0 ? _h : '',
|
|
300
|
-
variantLabel: (0, wire_1.str)(payload.variantLabel),
|
|
301
|
-
quantity: (_j = (0, wire_1.num)(payload.qty)) !== null && _j !== void 0 ? _j : 1,
|
|
302
|
-
productImage: (0, wire_1.str)(payload.productImage),
|
|
303
|
-
sellId: (_k = (0, wire_1.str)(payload.sellId)) !== null && _k !== void 0 ? _k : null,
|
|
304
|
-
},
|
|
305
|
-
});
|
|
306
|
-
return;
|
|
307
|
-
case 'START_POLL':
|
|
308
|
-
this.emitPollStarted((_l = payload.poll) !== null && _l !== void 0 ? _l : (0, wire_1.path)(payload, 'data', 'poll'));
|
|
309
|
-
return;
|
|
310
|
-
case 'MUTE_USER':
|
|
311
|
-
this.mutedDeviceIds = this.mutedIdsFrom(payload.mutedUsers);
|
|
312
|
-
this.emit({ type: 'mutedUsers', deviceIds: this.mutedDeviceIds });
|
|
313
|
-
return;
|
|
314
|
-
case 'START_BIDDING':
|
|
315
|
-
this.emitBiddingStarted(payload.data, (_m = (0, wire_1.num)((0, wire_1.path)(payload, 'data', 'timeStamp'))) !== null && _m !== void 0 ? _m : 0);
|
|
316
|
-
return;
|
|
317
|
-
case 'BROADCAST_BID_INFO':
|
|
318
|
-
this.emitBidInfo(payload.data, (_o = (0, wire_1.num)(payload.serverSentTime)) !== null && _o !== void 0 ? _o : 0);
|
|
319
|
-
return;
|
|
320
|
-
case 'giveaway_start':
|
|
321
|
-
this.emitGiveawayStarted(payload.eventData);
|
|
322
|
-
return;
|
|
323
|
-
case 'giveaway_end':
|
|
324
|
-
this.emitGiveawayEnded(payload.eventData);
|
|
325
|
-
return;
|
|
326
|
-
case 'user_registered': {
|
|
327
|
-
const count = (0, wire_1.num)((0, wire_1.path)(payload, 'eventData', 'usersCount'));
|
|
328
|
-
if (count !== null)
|
|
329
|
-
this.emit({ type: 'giveawayEntries', count });
|
|
330
|
-
return;
|
|
331
|
-
}
|
|
332
|
-
default:
|
|
333
|
-
this.emit({ type: 'unknown', channel: 'customCommand', payload });
|
|
334
|
-
}
|
|
335
|
-
}
|
|
336
|
-
/** The moderator's Zego user id, whatever shape it arrived in — an object smuggled through crashes iOS. */
|
|
337
|
-
/**
|
|
338
|
-
* Device ids out of a host mute list.
|
|
339
|
-
*
|
|
340
|
-
* Entries with no id are dropped rather than passed through: the host dashboard can record a comment
|
|
341
|
-
* with no `deviceId`, and an id-less entry would match every viewer whose id is also absent —
|
|
342
|
-
* muting one person would silence the room.
|
|
343
|
-
*/
|
|
344
|
-
mutedIdsFrom(raw) {
|
|
345
|
-
return (0, wire_1.arr)(raw)
|
|
346
|
-
.map((entry) => (0, wire_1.str)((0, wire_1.get)(entry, 'deviceId')))
|
|
347
|
-
.filter((id) => !!id);
|
|
348
|
-
}
|
|
349
|
-
moderatorIdFrom(raw) {
|
|
350
|
-
var _a, _b;
|
|
351
|
-
if (!raw)
|
|
352
|
-
return null;
|
|
353
|
-
if (typeof raw === 'string')
|
|
354
|
-
return raw;
|
|
355
|
-
if (typeof raw === 'object') {
|
|
356
|
-
const record = raw;
|
|
357
|
-
const id = (_b = (_a = record.userID) !== null && _a !== void 0 ? _a : record.userId) !== null && _b !== void 0 ? _b : record.user_id;
|
|
358
|
-
if (typeof id === 'string' && id)
|
|
359
|
-
return id;
|
|
360
|
-
if (typeof id === 'number')
|
|
361
|
-
return String(id);
|
|
362
|
-
}
|
|
363
|
-
return null;
|
|
364
|
-
}
|
|
365
|
-
emitBiddingStarted(data, serverNowMs) {
|
|
366
|
-
const wire = data;
|
|
367
|
-
const endsAtMs = (0, wire_1.num)((0, wire_1.get)(wire, 'endTimeStamp'));
|
|
368
|
-
if (endsAtMs === null || endsAtMs <= 0)
|
|
369
|
-
return;
|
|
370
|
-
this.emit({
|
|
371
|
-
type: 'biddingStarted',
|
|
372
|
-
endsAtMs,
|
|
373
|
-
serverNowMs: serverNowMs || endsAtMs,
|
|
374
|
-
storeProductId: (0, wire_1.str)((0, wire_1.get)(wire, 'selectedProductId')),
|
|
375
|
-
moderatorId: this.moderatorIdFrom((0, wire_1.get)(wire, 'moderatorInCharge')),
|
|
376
|
-
});
|
|
377
|
-
}
|
|
378
|
-
emitBidInfo(data, serverNowMs) {
|
|
379
|
-
var _a, _b, _c, _d;
|
|
380
|
-
const wire = data;
|
|
381
|
-
if (!(0, wire_1.isRecord)(wire))
|
|
382
|
-
return;
|
|
383
|
-
const endsAtMs = (0, wire_1.num)(wire.newEndTimeStamp);
|
|
384
|
-
const user = wire.user;
|
|
385
|
-
this.emit({
|
|
386
|
-
type: 'bidInfo',
|
|
387
|
-
highestBid: (_a = (0, wire_1.num)(wire.newHighestBid)) !== null && _a !== void 0 ? _a : 0,
|
|
388
|
-
nextBid: (_b = (0, wire_1.num)(wire.nextBid)) !== null && _b !== void 0 ? _b : 0,
|
|
389
|
-
endsAtMs: endsAtMs !== null && endsAtMs > 0 ? endsAtMs : null,
|
|
390
|
-
serverNowMs,
|
|
391
|
-
leader: (0, wire_1.isRecord)(user)
|
|
392
|
-
? { userId: (_c = (0, wire_1.str)(user.userId)) !== null && _c !== void 0 ? _c : '', userName: (_d = (0, wire_1.str)(user.userName)) !== null && _d !== void 0 ? _d : '' }
|
|
393
|
-
: null,
|
|
394
|
-
});
|
|
395
|
-
}
|
|
396
|
-
emitGiveawayStarted(eventData) {
|
|
397
|
-
const wire = eventData;
|
|
398
|
-
const storeProductId = (0, wire_1.str)((0, wire_1.get)(wire, 'productId'));
|
|
399
|
-
if (!storeProductId)
|
|
400
|
-
return;
|
|
401
|
-
this.emit({
|
|
402
|
-
type: 'giveawayStarted',
|
|
403
|
-
storeProductId,
|
|
404
|
-
variantId: (0, wire_1.str)((0, wire_1.get)(wire, 'variantId')),
|
|
405
|
-
entryCount: (0, wire_1.num)((0, wire_1.get)(wire, 'userCount')),
|
|
406
|
-
});
|
|
407
|
-
}
|
|
408
|
-
emitGiveawayEnded(eventData) {
|
|
409
|
-
const storeProductId = (0, wire_1.str)((0, wire_1.get)(eventData, 'productId'));
|
|
410
|
-
if (!storeProductId)
|
|
411
|
-
return;
|
|
412
|
-
// The host sends the literal string "null" when a giveaway closes with nobody in it, so only an
|
|
413
|
-
// object is a real winner.
|
|
414
|
-
const winner = (0, wire_1.get)(eventData, 'winner');
|
|
415
|
-
const winnerName = (0, wire_1.isRecord)(winner) ? (0, wire_1.str)(winner.displayName) : null;
|
|
416
|
-
this.emit({ type: 'giveawayEnded', storeProductId, winnerName });
|
|
417
|
-
}
|
|
418
|
-
handleBroadcast(raw, serverNowMs = 0) {
|
|
419
|
-
var _a, _b, _c, _d, _e, _f, _g;
|
|
420
|
-
const payload = (0, wire_1.parseJson)(raw);
|
|
421
|
-
if (!(0, wire_1.isRecord)(payload))
|
|
422
|
-
return;
|
|
423
|
-
switch ((0, wire_1.str)(payload.type)) {
|
|
424
|
-
case 'START_BIDDING':
|
|
425
|
-
this.emitBiddingStarted(payload.data, serverNowMs);
|
|
426
|
-
return;
|
|
427
|
-
case 'CLOSE_BIDDING':
|
|
428
|
-
this.emit({ type: 'biddingClosed' });
|
|
429
|
-
return;
|
|
430
|
-
case 'BID_WINNER_ANNOUNCEMENT': {
|
|
431
|
-
const wire = payload.data;
|
|
432
|
-
const meta = (0, wire_1.path)(wire, 'bidWinner', 'meta');
|
|
433
|
-
this.emit({
|
|
434
|
-
type: 'auctionWon',
|
|
435
|
-
win: {
|
|
436
|
-
userName: (_a = (0, wire_1.str)((0, wire_1.path)(meta, 'user', 'userName'))) !== null && _a !== void 0 ? _a : '',
|
|
437
|
-
winningBid: (_b = (0, wire_1.num)((0, wire_1.get)(meta, 'winningBid'))) !== null && _b !== void 0 ? _b : 0,
|
|
438
|
-
storeProductId: (0, wire_1.str)((0, wire_1.path)(wire, 'auctionedProduct', 'store_product_id')),
|
|
439
|
-
},
|
|
440
|
-
});
|
|
441
|
-
return;
|
|
442
|
-
}
|
|
443
|
-
case 'START_POLL':
|
|
444
|
-
this.emitPollStarted((0, wire_1.path)(payload, 'data', 'poll'));
|
|
445
|
-
return;
|
|
446
|
-
case 'BROADCAST_POLL_RESULTS': {
|
|
447
|
-
const results = (0, polls_1.toLivePollResults)((0, wire_1.path)(payload, 'data', 'pollResults'));
|
|
448
|
-
if (results)
|
|
449
|
-
this.emit({ type: 'pollResults', results });
|
|
450
|
-
return;
|
|
451
|
-
}
|
|
452
|
-
case 'REACTION_ANNOUCEMENT':
|
|
453
|
-
this.emit({
|
|
454
|
-
type: 'reaction',
|
|
455
|
-
reactionUrl: (_d = (_c = (0, wire_1.str)((0, wire_1.path)(payload, 'data', 'reactionUrl'))) !== null && _c !== void 0 ? _c : (0, wire_1.str)(payload.reactionUrl)) !== null && _d !== void 0 ? _d : '',
|
|
456
|
-
userName: (_f = (_e = (0, wire_1.str)((0, wire_1.path)(payload, 'data', 'userName'))) !== null && _e !== void 0 ? _e : (0, wire_1.str)(payload.userName)) !== null && _f !== void 0 ? _f : 'Anonymous',
|
|
457
|
-
});
|
|
458
|
-
return;
|
|
459
|
-
case 'END_POLL':
|
|
460
|
-
this.emit({ type: 'pollEnded' });
|
|
461
|
-
return;
|
|
462
|
-
/**
|
|
463
|
-
* The host's reaction setting, changed mid-show.
|
|
464
|
-
*
|
|
465
|
-
* On the BROADCAST channel deliberately, not stream extra info where `MULTIPLIER_CHANGE` lives:
|
|
466
|
-
* extra info is a single slot, so a third event there would overwrite whatever product change
|
|
467
|
-
* was in it and force the console to re-send all three every time the room's population moves.
|
|
468
|
-
* This channel is a message, so it competes with nothing.
|
|
469
|
-
*
|
|
470
|
-
* Wire: `{type: 'REACTION_MODE_CHANGE', data: {mode: 'single' | 'multiple'}}`, with a bare
|
|
471
|
-
* `mode` at the top level accepted too, because the channel's existing senders are split on it.
|
|
472
|
-
* Anything but `multiple` is `single` — the same reading `streams.ts` gives the stored record,
|
|
473
|
-
* so a typo degrades the same way in both places rather than throwing.
|
|
474
|
-
*
|
|
475
|
-
* Reaches only who is in the room NOW. A later joiner has the record, which is why the dashboard
|
|
476
|
-
* has to persist `meta.reactionType` as well as send this.
|
|
477
|
-
*/
|
|
478
|
-
case 'REACTION_MODE_CHANGE': {
|
|
479
|
-
const mode = ((_g = (0, wire_1.str)((0, wire_1.path)(payload, 'data', 'mode'))) !== null && _g !== void 0 ? _g : (0, wire_1.str)(payload.mode)) === 'multiple'
|
|
480
|
-
? 'multiple'
|
|
481
|
-
: 'single';
|
|
482
|
-
this.emit({ type: 'reactionMode', mode });
|
|
483
|
-
return;
|
|
484
|
-
}
|
|
485
|
-
case 'MUTE_USER':
|
|
486
|
-
this.mutedDeviceIds = this.mutedIdsFrom((0, wire_1.path)(payload, 'data', 'mutedUsers'));
|
|
487
|
-
this.emit({ type: 'mutedUsers', deviceIds: this.mutedDeviceIds });
|
|
488
|
-
return;
|
|
489
|
-
case 'STREAM_ENDED':
|
|
490
|
-
this.emit({ type: 'streamEnded' });
|
|
491
|
-
return;
|
|
492
|
-
case 'MIXER_STATE':
|
|
493
|
-
void this.applyMixerState(!!payload.active);
|
|
494
|
-
return;
|
|
495
|
-
case 'COHOST_ADMITTED':
|
|
496
|
-
if (!this.isOurSlot(payload.slot))
|
|
497
|
-
return;
|
|
498
|
-
this.emit({
|
|
499
|
-
type: 'guestAdmitted',
|
|
500
|
-
slot: Number(payload.slot),
|
|
501
|
-
mixerLayout: (0, guest_1.toMixerLayout)(payload.mixerLayout),
|
|
502
|
-
});
|
|
503
|
-
return;
|
|
504
|
-
case 'COHOST_REMOVED':
|
|
505
|
-
if (!this.isOurSlot(payload.slot))
|
|
506
|
-
return;
|
|
507
|
-
this.emit({ type: 'guestRemoved', slot: Number(payload.slot) });
|
|
508
|
-
return;
|
|
509
|
-
case 'COHOST_MUTE_AUDIO':
|
|
510
|
-
if (!this.isOurSlot(payload.slot))
|
|
511
|
-
return;
|
|
512
|
-
this.emit({ type: 'guestMutedByHost', slot: Number(payload.slot), muted: !!payload.muted });
|
|
513
|
-
return;
|
|
514
|
-
case 'COHOST_CAM_OFF':
|
|
515
|
-
if (!this.isOurSlot(payload.slot))
|
|
516
|
-
return;
|
|
517
|
-
this.emit({ type: 'guestCameraOffByHost', slot: Number(payload.slot), off: !!payload.off });
|
|
518
|
-
return;
|
|
519
|
-
case 'LAYOUT_CHANGED': {
|
|
520
|
-
const layout = (0, guest_1.toMixerLayout)(payload.mixerLayout);
|
|
521
|
-
if (layout)
|
|
522
|
-
this.emit({ type: 'mixerLayout', layout });
|
|
523
|
-
return;
|
|
524
|
-
}
|
|
525
|
-
case 'GUESTS_CHANGED':
|
|
526
|
-
return;
|
|
527
|
-
default:
|
|
528
|
-
this.emit({ type: 'unknown', channel: 'broadcast', payload });
|
|
529
|
-
}
|
|
530
|
-
}
|
|
531
|
-
isOurSlot(slot) {
|
|
532
|
-
return this.guest != null && Number(slot) === this.guest.slot;
|
|
533
|
-
}
|
|
534
|
-
emitPollStarted(raw) {
|
|
535
|
-
const poll = (0, polls_1.toLivePoll)(raw);
|
|
536
|
-
if (poll)
|
|
537
|
-
this.emit({ type: 'pollStarted', poll, results: (0, polls_1.toEmbeddedResults)(raw) });
|
|
538
|
-
}
|
|
539
|
-
async applyMixerState(active) {
|
|
540
|
-
this.mixerActive = active;
|
|
541
|
-
this.emit({ type: 'mixer', active });
|
|
542
|
-
const target = this.targetStreamId();
|
|
543
|
-
if (!target || target === this.playingStreamId)
|
|
544
|
-
return;
|
|
545
|
-
await this.playStream(target);
|
|
546
|
-
}
|
|
547
|
-
targetStreamId() {
|
|
548
|
-
if (!this.joined)
|
|
549
|
-
return null;
|
|
550
|
-
return this.mixerActive && this.joined.mixedStreamId ? this.joined.mixedStreamId : this.joined.streamingId;
|
|
551
|
-
}
|
|
552
|
-
announceJoin() {
|
|
553
|
-
if (!this.joined)
|
|
554
|
-
return;
|
|
555
|
-
this.Engine.instance()
|
|
556
|
-
.sendCustomCommand(this.joined.roomId, JSON.stringify({ type: 'USER_JOINED', userName: this.joined.viewerName }), [])
|
|
557
|
-
.catch((error) => (0, client_1.getLogger)().error('[liveSelling] announceJoin', error));
|
|
558
|
-
}
|
|
559
|
-
enqueue(operation) {
|
|
560
|
-
const result = this.queue.then(operation, operation);
|
|
561
|
-
this.queue = result.catch(() => undefined);
|
|
562
|
-
return result;
|
|
563
|
-
}
|
|
564
|
-
join(params) {
|
|
565
|
-
return this.enqueue(() => this.joinNow(params));
|
|
566
|
-
}
|
|
567
|
-
leave() {
|
|
568
|
-
// A guest owns the room login while one is active; `leaveGuest` is the way out of guest mode.
|
|
569
|
-
if (this.guest)
|
|
570
|
-
return Promise.resolve();
|
|
571
|
-
return this.enqueue(() => this.leaveNow());
|
|
572
|
-
}
|
|
573
|
-
async joinNow(params) {
|
|
574
|
-
var _a;
|
|
575
|
-
await this.ensureEngine();
|
|
576
|
-
if (((_a = this.joined) === null || _a === void 0 ? void 0 : _a.streamingId) === params.streamingId)
|
|
577
|
-
return;
|
|
578
|
-
if (this.joined)
|
|
579
|
-
await this.leaveNow();
|
|
580
|
-
const { ZegoUser, ZegoRoomConfig } = this.Zego;
|
|
581
|
-
this.joined = params;
|
|
582
|
-
/**
|
|
583
|
-
* Seeded from the record, not assumed false.
|
|
584
|
-
*
|
|
585
|
-
* A guest admitted before this viewer arrived means the mixer is already publishing
|
|
586
|
-
* `{streamingId}_mixed`, and the `MIXER_STATE` broadcast that would have said so went out before
|
|
587
|
-
* they were in the room — broadcasts are never replayed. The mixer's output is a server-side
|
|
588
|
-
* task rather than a room participant, so `roomStreamUpdate` does not mention it either. Without
|
|
589
|
-
* this the viewer plays the host's solo stream for the rest of the show and the co-host simply
|
|
590
|
-
* never appears. Same reason `mutedDeviceIds` is seeded from the record beside it.
|
|
591
|
-
*/
|
|
592
|
-
this.mixerActive = params.hasActiveGuest && !!params.mixedStreamId;
|
|
593
|
-
// Before the room is entered, so the first comment after a cold rejoin is already checked.
|
|
594
|
-
this.mutedDeviceIds = params.mutedDeviceIds;
|
|
595
|
-
const result = await this.Engine.instance().loginRoom(params.roomId, new ZegoUser(params.viewerId, params.viewerName), new ZegoRoomConfig(0, true, params.token));
|
|
596
|
-
if (result === null || result === void 0 ? void 0 : result.errorCode)
|
|
597
|
-
throw new Error(`loginRoom failed with ${result.errorCode}`);
|
|
598
|
-
}
|
|
599
|
-
async bindView(reactTag, force = false) {
|
|
600
|
-
return this.enqueue(() => this.bindViewNow(reactTag, force));
|
|
601
|
-
}
|
|
602
|
-
async bindViewNow(reactTag, force = false) {
|
|
603
|
-
const target = this.targetStreamId();
|
|
604
|
-
if (!force &&
|
|
605
|
-
reactTag === this.boundTag &&
|
|
606
|
-
reactTag === this.playingTag &&
|
|
607
|
-
target &&
|
|
608
|
-
target === this.playingStreamId) {
|
|
609
|
-
return;
|
|
610
|
-
}
|
|
611
|
-
this.boundTag = reactTag;
|
|
612
|
-
if (!target || reactTag == null)
|
|
613
|
-
return;
|
|
614
|
-
await this.playStream(target);
|
|
615
|
-
}
|
|
616
|
-
async refreshPlayback() {
|
|
617
|
-
return this.enqueue(() => this.refreshPlaybackNow());
|
|
618
|
-
}
|
|
619
|
-
async refreshPlaybackNow() {
|
|
620
|
-
const target = this.targetStreamId();
|
|
621
|
-
if (!target || this.boundTag == null)
|
|
622
|
-
return;
|
|
623
|
-
const { ZegoView, ZegoPlayerConfig } = this.Zego;
|
|
624
|
-
this.playingStreamId = target;
|
|
625
|
-
this.playingTag = this.boundTag;
|
|
626
|
-
void sdk_apptile_live_selling_native_1.livePip.setStream(target);
|
|
627
|
-
await this.Engine.instance().startPlayingStream(target, new ZegoView(this.boundTag, 1, 0), new ZegoPlayerConfig());
|
|
628
|
-
}
|
|
629
|
-
async stopPlayback() {
|
|
630
|
-
return this.enqueue(() => this.stopPlaybackNow());
|
|
631
|
-
}
|
|
632
|
-
async stopPlaybackNow() {
|
|
633
|
-
const playing = this.playingStreamId;
|
|
634
|
-
this.playingStreamId = null;
|
|
635
|
-
this.playingTag = null;
|
|
636
|
-
this.boundTag = null;
|
|
637
|
-
void sdk_apptile_live_selling_native_1.livePip.setStream(null);
|
|
638
|
-
if (!playing)
|
|
639
|
-
return;
|
|
640
|
-
await this.Engine.instance().stopPlayingStream(playing);
|
|
641
|
-
}
|
|
642
|
-
async playStream(streamId) {
|
|
643
|
-
if (this.boundTag == null)
|
|
644
|
-
return;
|
|
645
|
-
const { ZegoView, ZegoPlayerConfig } = this.Zego;
|
|
646
|
-
const previous = this.playingStreamId;
|
|
647
|
-
// Zego ignores a new canvas for a stream it is already playing, so moving the picture means
|
|
648
|
-
// stopping first.
|
|
649
|
-
const movingView = this.playingTag != null && this.playingTag !== this.boundTag;
|
|
650
|
-
if (previous && (previous !== streamId || movingView)) {
|
|
651
|
-
await this.Engine.instance().stopPlayingStream(previous);
|
|
652
|
-
}
|
|
653
|
-
this.playingStreamId = streamId;
|
|
654
|
-
this.playingTag = this.boundTag;
|
|
655
|
-
await this.Engine.instance().startPlayingStream(streamId, new ZegoView(this.boundTag, 1, 0), new ZegoPlayerConfig());
|
|
656
|
-
// Tracks the mixed id through a co-host swap, which is why it is set here rather than at join.
|
|
657
|
-
void sdk_apptile_live_selling_native_1.livePip.setStream(streamId);
|
|
658
|
-
this.emit({ type: 'videoBound', tag: this.playingTag });
|
|
659
|
-
}
|
|
660
|
-
// ─── Guest / co-host ──────────────────────────────────────────────────────
|
|
661
|
-
joinAsGuest(credentials, previewTag) {
|
|
662
|
-
return this.enqueue(() => this.joinAsGuestNow(credentials, previewTag));
|
|
663
|
-
}
|
|
664
|
-
async joinAsGuestNow(credentials, previewTag) {
|
|
665
|
-
await this.ensureEngine();
|
|
666
|
-
const engine = this.Engine.instance();
|
|
667
|
-
const { ZegoUser, ZegoRoomConfig, ZegoOrientation, ZegoPublishChannel } = this.Zego;
|
|
668
|
-
// The viewer login has to go first: one session per engine, and the publish privilege lives in
|
|
669
|
-
// the guest's token.
|
|
670
|
-
if (this.joined)
|
|
671
|
-
await this.leaveNow();
|
|
672
|
-
this.guest = credentials;
|
|
673
|
-
this.emit({ type: 'guestMode', active: true });
|
|
674
|
-
// Before publishing: without it the server-side MixStream output is rotated.
|
|
675
|
-
await engine.setAppOrientation(ZegoOrientation.PortraitUp, ZegoPublishChannel.Main);
|
|
676
|
-
await engine.useFrontCamera(true, ZegoPublishChannel.Main);
|
|
677
|
-
const result = await engine.loginRoom(credentials.roomId, new ZegoUser(credentials.userId, credentials.userName), new ZegoRoomConfig(0, true, credentials.token));
|
|
678
|
-
if (result === null || result === void 0 ? void 0 : result.errorCode) {
|
|
679
|
-
this.guest = null;
|
|
680
|
-
this.emit({ type: 'guestMode', active: false });
|
|
681
|
-
throw new Error(`guest loginRoom failed with ${result.errorCode}`);
|
|
682
|
-
}
|
|
683
|
-
if (previewTag != null)
|
|
684
|
-
await this.startPreviewNow(previewTag);
|
|
685
|
-
await engine.startPublishingStream(credentials.guestStreamId, ZegoPublishChannel.Main, {
|
|
686
|
-
roomID: credentials.roomId,
|
|
687
|
-
});
|
|
688
|
-
}
|
|
689
|
-
bindGuestPreview(reactTag) {
|
|
690
|
-
return this.enqueue(() => this.startPreviewNow(reactTag));
|
|
691
|
-
}
|
|
692
|
-
async startPreviewNow(reactTag) {
|
|
693
|
-
if (!this.guest || reactTag == null || reactTag === this.previewTag)
|
|
694
|
-
return;
|
|
695
|
-
const { ZegoView, ZegoPublishChannel } = this.Zego;
|
|
696
|
-
this.previewTag = reactTag;
|
|
697
|
-
await this.Engine.instance().startPreview(new ZegoView(reactTag, 1, 0), ZegoPublishChannel.Main);
|
|
698
|
-
}
|
|
699
|
-
bindGuestHostView(reactTag) {
|
|
700
|
-
return this.enqueue(async () => {
|
|
701
|
-
if (!this.guest || reactTag == null)
|
|
702
|
-
return;
|
|
703
|
-
const { ZegoView, ZegoPlayerConfig } = this.Zego;
|
|
704
|
-
// The host's raw stream, never `_mixed`: the mix contains this guest.
|
|
705
|
-
await this.Engine.instance().startPlayingStream(this.guest.streamingId, new ZegoView(reactTag, 1, 0), new ZegoPlayerConfig());
|
|
706
|
-
});
|
|
707
|
-
}
|
|
708
|
-
async setGuestMicMuted(muted) {
|
|
709
|
-
if (!this.guest)
|
|
710
|
-
return;
|
|
711
|
-
const engine = this.Engine.instance();
|
|
712
|
-
const { ZegoPublishChannel } = this.Zego;
|
|
713
|
-
await engine.muteMicrophone(muted);
|
|
714
|
-
await engine.mutePublishStreamAudio(muted, ZegoPublishChannel.Main);
|
|
715
|
-
}
|
|
716
|
-
async setGuestCameraOff(off) {
|
|
717
|
-
if (!this.guest)
|
|
718
|
-
return;
|
|
719
|
-
const engine = this.Engine.instance();
|
|
720
|
-
const { ZegoPublishChannel } = this.Zego;
|
|
721
|
-
await engine.enableCamera(!off, ZegoPublishChannel.Main);
|
|
722
|
-
await engine.mutePublishStreamVideo(off, ZegoPublishChannel.Main);
|
|
723
|
-
}
|
|
724
|
-
async flipGuestCamera(front) {
|
|
725
|
-
if (!this.guest)
|
|
726
|
-
return;
|
|
727
|
-
const { ZegoPublishChannel } = this.Zego;
|
|
728
|
-
await this.Engine.instance().useFrontCamera(front, ZegoPublishChannel.Main);
|
|
729
|
-
}
|
|
730
|
-
leaveGuest() {
|
|
731
|
-
return this.enqueue(() => this.leaveGuestNow());
|
|
732
|
-
}
|
|
733
|
-
async leaveGuestNow() {
|
|
734
|
-
const guest = this.guest;
|
|
735
|
-
if (!guest)
|
|
736
|
-
return;
|
|
737
|
-
const engine = this.Engine.instance();
|
|
738
|
-
const { ZegoPublishChannel } = this.Zego;
|
|
739
|
-
const logger = (0, client_1.getLogger)();
|
|
740
|
-
// Each guarded on its own: a failure part-way must not leave the room joined.
|
|
741
|
-
try {
|
|
742
|
-
await engine.stopPublishingStream(ZegoPublishChannel.Main);
|
|
743
|
-
}
|
|
744
|
-
catch (caught) {
|
|
745
|
-
logger.error('[liveSelling] stopPublishing', caught);
|
|
746
|
-
}
|
|
747
|
-
try {
|
|
748
|
-
await engine.stopPreview(ZegoPublishChannel.Main);
|
|
749
|
-
}
|
|
750
|
-
catch (caught) {
|
|
751
|
-
logger.error('[liveSelling] stopPreview', caught);
|
|
752
|
-
}
|
|
753
|
-
try {
|
|
754
|
-
await engine.stopPlayingStream(guest.streamingId);
|
|
755
|
-
}
|
|
756
|
-
catch {
|
|
757
|
-
// Nothing was playing — the guest may never have seen the host.
|
|
758
|
-
}
|
|
759
|
-
try {
|
|
760
|
-
await engine.logoutRoom(guest.roomId);
|
|
761
|
-
}
|
|
762
|
-
catch (caught) {
|
|
763
|
-
logger.error('[liveSelling] guestLogout', caught);
|
|
764
|
-
}
|
|
765
|
-
this.guest = null;
|
|
766
|
-
this.previewTag = null;
|
|
767
|
-
this.emit({ type: 'guestMode', active: false });
|
|
768
|
-
}
|
|
769
|
-
setMutedDeviceIds(ids) {
|
|
770
|
-
const changed = ids.length !== this.mutedDeviceIds.length || ids.some((id, index) => id !== this.mutedDeviceIds[index]);
|
|
771
|
-
if (!changed)
|
|
772
|
-
return;
|
|
773
|
-
this.mutedDeviceIds = ids;
|
|
774
|
-
this.emit({ type: 'mutedUsers', deviceIds: ids });
|
|
775
|
-
}
|
|
776
|
-
setViewerName(name) {
|
|
777
|
-
this.viewerNameOverride = (name === null || name === void 0 ? void 0 : name.trim()) || null;
|
|
778
|
-
}
|
|
779
|
-
get publishedName() {
|
|
780
|
-
var _a, _b, _c;
|
|
781
|
-
return (_c = (_a = this.viewerNameOverride) !== null && _a !== void 0 ? _a : (_b = this.joined) === null || _b === void 0 ? void 0 : _b.viewerName) !== null && _c !== void 0 ? _c : 'Anonymous';
|
|
782
|
-
}
|
|
783
|
-
setMuted(muted) {
|
|
784
|
-
if (!this.engineReady)
|
|
785
|
-
return;
|
|
786
|
-
this.Engine.instance().muteSpeaker(muted);
|
|
787
|
-
}
|
|
788
|
-
async sendComment(text, deviceId, options) {
|
|
789
|
-
if (!this.joined || !text.trim())
|
|
790
|
-
return null;
|
|
791
|
-
const muted = (options === null || options === void 0 ? void 0 : options.forceMuted) === true || this.mutedDeviceIds.includes(deviceId);
|
|
792
|
-
await this.Engine.instance().sendBarrageMessage(this.joined.roomId, JSON.stringify({ name: this.publishedName, comment: text, source: 'USER', deviceId, muted, isBanned: false }));
|
|
793
|
-
return this.makeComment(text, this.publishedName, 'USER', undefined, true);
|
|
794
|
-
}
|
|
795
|
-
async sendReaction(reactionUrl) {
|
|
796
|
-
if (!this.joined)
|
|
797
|
-
return;
|
|
798
|
-
const userName = this.publishedName;
|
|
799
|
-
// `sendCustomCommand` does not echo to the sender, so emit the local event here.
|
|
800
|
-
await this.Engine.instance().sendCustomCommand(this.joined.roomId, JSON.stringify({ type: 'REACTION_ANNOUCEMENT', reactionUrl, userName, roomId: this.joined.roomId }), []);
|
|
801
|
-
this.emit({ type: 'reaction', reactionUrl, userName });
|
|
802
|
-
}
|
|
803
|
-
async sendBid(params) {
|
|
804
|
-
var _a;
|
|
805
|
-
if (!this.joined || !params.moderatorId)
|
|
806
|
-
return;
|
|
807
|
-
const { ZegoUser } = this.Zego;
|
|
808
|
-
// Coerced at the crash boundary: a non-string recipient id is an uncatchable native crash on iOS.
|
|
809
|
-
const moderatorId = String(params.moderatorId);
|
|
810
|
-
await this.Engine.instance().sendCustomCommand(this.joined.roomId, JSON.stringify({
|
|
811
|
-
type: 'BID_PLACED',
|
|
812
|
-
data: {
|
|
813
|
-
bidAmount: params.bidAmount,
|
|
814
|
-
user: params.bidder,
|
|
815
|
-
timeStamp: params.placedAtMs,
|
|
816
|
-
userOptedVariantId: (_a = params.variantId) !== null && _a !== void 0 ? _a : '',
|
|
817
|
-
},
|
|
818
|
-
}), [new ZegoUser(moderatorId, moderatorId)]);
|
|
819
|
-
}
|
|
820
|
-
async sendCartAnnouncement(productTitle, sellId) {
|
|
821
|
-
if (!this.joined || !productTitle.trim())
|
|
822
|
-
return;
|
|
823
|
-
const userName = this.publishedName;
|
|
824
|
-
const code = sellId !== null && sellId !== void 0 ? sellId : null;
|
|
825
|
-
await this.Engine.instance().sendCustomCommand(this.joined.roomId, JSON.stringify({
|
|
826
|
-
type: 'CART_ANNOUCEMENT',
|
|
827
|
-
productTitle,
|
|
828
|
-
userName,
|
|
829
|
-
sellId: code,
|
|
830
|
-
roomId: this.joined.roomId,
|
|
831
|
-
}), []);
|
|
832
|
-
this.emit({ type: 'cartAnnouncement', productTitle, userName, sellId: code });
|
|
833
|
-
}
|
|
834
|
-
async leaveNow() {
|
|
835
|
-
if (!this.engineReady || !this.joined)
|
|
836
|
-
return;
|
|
837
|
-
const engine = this.Engine.instance();
|
|
838
|
-
if (this.playingStreamId)
|
|
839
|
-
await engine.stopPlayingStream(this.playingStreamId);
|
|
840
|
-
await engine.logoutRoom(this.joined.roomId);
|
|
841
|
-
this.playingStreamId = null;
|
|
842
|
-
this.playingTag = null;
|
|
843
|
-
this.boundTag = null;
|
|
844
|
-
this.joined = null;
|
|
845
|
-
this.emit({ type: 'videoBound', tag: null });
|
|
846
|
-
}
|
|
847
|
-
async destroy() {
|
|
848
|
-
if (!this.engineReady)
|
|
849
|
-
return;
|
|
850
|
-
await this.leave();
|
|
851
|
-
this.creating = null;
|
|
852
|
-
this.Engine.destroyEngine();
|
|
853
|
-
this.engineReady = false;
|
|
854
|
-
}
|
|
855
|
-
}
|
|
856
|
-
exports.engine = new NativeLiveEngine();
|
|
20
|
+
const streams_1 = require("./streams");
|
|
21
|
+
const zegoEngine_1 = require("./zegoEngine");
|
|
22
|
+
exports.engine = new zegoEngine_1.ZegoLiveEngine({
|
|
23
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
24
|
+
loadZego: () => require('zego-express-engine-reactnative'),
|
|
25
|
+
platform: react_native_1.Platform.OS,
|
|
26
|
+
pip: sdk_apptile_live_selling_native_1.livePip,
|
|
27
|
+
fetchToken: (viewerId, streamingId) => streams_1.streams.zegoToken(viewerId, streamingId),
|
|
28
|
+
});
|
|
857
29
|
//# sourceMappingURL=engine.native.js.map
|