UNPKG

callskit

Version:

A toolkit for building call experience using Cloudflare Realtime

1,398 lines (1,366 loc) 48.9 kB
'use strict'; var React = require('react'); var client = require('partytracks/client'); var rxjs = require('rxjs'); var invariant2 = require('tiny-invariant'); var PartySocket = require('partysocket'); function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; } var React__default = /*#__PURE__*/_interopDefault(React); var invariant2__default = /*#__PURE__*/_interopDefault(invariant2); var PartySocket__default = /*#__PURE__*/_interopDefault(PartySocket); var __defProp = Object.defineProperty; var __defProps = Object.defineProperties; var __getOwnPropDescs = Object.getOwnPropertyDescriptors; var __getOwnPropSymbols = Object.getOwnPropertySymbols; var __hasOwnProp = Object.prototype.hasOwnProperty; var __propIsEnum = Object.prototype.propertyIsEnumerable; var __typeError = (msg) => { throw TypeError(msg); }; var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __spreadValues = (a, b) => { for (var prop in b || (b = {})) if (__hasOwnProp.call(b, prop)) __defNormalProp(a, prop, b[prop]); if (__getOwnPropSymbols) for (var prop of __getOwnPropSymbols(b)) { if (__propIsEnum.call(b, prop)) __defNormalProp(a, prop, b[prop]); } return a; }; var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b)); var __objRest = (source, exclude) => { var target = {}; for (var prop in source) if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0) target[prop] = source[prop]; if (source != null && __getOwnPropSymbols) for (var prop of __getOwnPropSymbols(source)) { if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop)) target[prop] = source[prop]; } return target; }; var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg); var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj)); var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value); var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), member.set(obj, value), value); var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method); var __async = (__this, __arguments, generator) => { return new Promise((resolve, reject) => { var fulfilled = (value) => { try { step(generator.next(value)); } catch (e) { reject(e); } }; var rejected = (value) => { try { step(generator.throw(value)); } catch (e) { reject(e); } }; var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected); step((generator = generator.apply(__this, __arguments)).next()); }); }; // src/utils/events-handler.ts var _callbacksMap, _globalCallbacks; var EventsHandler = class { constructor() { __privateAdd(this, _callbacksMap); __privateAdd(this, _globalCallbacks); __privateSet(this, _callbacksMap, /* @__PURE__ */ new Map()); __privateSet(this, _globalCallbacks, /* @__PURE__ */ new Set()); } emit(event, ...args) { var _a; (_a = __privateGet(this, _callbacksMap).get(event)) == null ? void 0 : _a.forEach((callback) => callback(...args)); __privateGet(this, _globalCallbacks).forEach((callback) => callback(event, ...args)); } addEventListener(event, callback) { if (!__privateGet(this, _callbacksMap).has(event)) { __privateGet(this, _callbacksMap).set(event, /* @__PURE__ */ new Set()); } __privateGet(this, _callbacksMap).get(event).add(callback); } removeEventListener(event, callback) { var _a; (_a = __privateGet(this, _callbacksMap).get(event)) == null ? void 0 : _a.delete(callback); } subscribe(event, callback) { this.addEventListener(event, callback); return () => this.removeEventListener(event, callback); } subscribeAll(callback) { __privateGet(this, _globalCallbacks).add(callback); return () => { __privateGet(this, _globalCallbacks).delete(callback); }; } unsubscribeAll(callback) { __privateGet(this, _globalCallbacks).delete(callback); } once(event, callback) { const wrapper = (...args) => { this.removeEventListener(event, wrapper); callback(...args); }; this.addEventListener(event, wrapper); return () => { this.removeEventListener(event, wrapper); }; } clearAll() { __privateGet(this, _callbacksMap).clear(); __privateGet(this, _globalCallbacks).clear(); } }; _callbacksMap = new WeakMap(); _globalCallbacks = new WeakMap(); // src/utils/logger.ts var _Logger = class _Logger { constructor(options = {}) { var _a, _b, _c; this.level = (_a = options.level) != null ? _a : "info"; this.prefix = (_b = options.prefix) != null ? _b : ""; this.enabled = (_c = options.enabled) != null ? _c : true; } shouldLog(level) { return this.enabled && _Logger.levels[level] >= _Logger.levels[this.level]; } formatMessage(level, args) { const prefix = this.prefix ? `[${this.prefix}]` : ""; return [prefix, ...args]; } debug(...args) { if (this.shouldLog("debug")) { console.debug(...this.formatMessage("debug", args)); } } info(...args) { if (this.shouldLog("info")) { console.info(...this.formatMessage("info", args)); } } warn(...args) { if (this.shouldLog("warn")) { console.warn(...this.formatMessage("warn", args)); } } error(...args) { if (this.shouldLog("error")) { console.error(...this.formatMessage("error", args)); } } setLevel(level) { this.level = level; } enable() { this.enabled = true; } disable() { this.enabled = false; } }; _Logger.levels = { debug: 0, info: 1, warn: 2, error: 3 }; var Logger = _Logger; var contextStack = []; function runWithContext(context, fn) { contextStack.push(context); try { return fn(); } finally { contextStack.pop(); } } function getCurrentCallContext() { const ctx = contextStack[contextStack.length - 1]; invariant2__default.default(ctx, "No active CallContext"); return ctx; } // src/lib/call-chat/call-chat.ts var _ctx, _CallChat_instances, sendMessage_fn; var CallChat = class extends EventsHandler { constructor() { super(); __privateAdd(this, _CallChat_instances); this.messages = []; __privateAdd(this, _ctx); __privateSet(this, _ctx, getCurrentCallContext()); } sendTextMessage(message) { __privateMethod(this, _CallChat_instances, sendMessage_fn).call(this, { type: "text", message: message.trim() }); } addMessage(message) { const parsedMessage = __spreadProps(__spreadValues({}, message), { created_at: new Date(message.created_at) }); this.messages = [...this.messages, parsedMessage]; this.emit("message", parsedMessage); } addMessagesInBulk(messages) { const parsed = messages.map((message) => __spreadProps(__spreadValues({}, message), { created_at: new Date(message.created_at) })); this.messages = [...this.messages, ...parsed]; this.emit("loaded", parsed); } }; _ctx = new WeakMap(); _CallChat_instances = new WeakSet(); sendMessage_fn = function(message) { __privateGet(this, _ctx).socket.sendAction({ action: "chat/message", message }); }; var _ctx2, _micEnabled$, _micTrackData$, _micEnabled, _micTrack, _cameraEnabled$, _cameraTrackData$, _cameraEnabled, _cameraTrack, _screenshareEnabled$, _screenshareVideoTrackData$, _screenshareAudioTrackData$, _screenshareEnabled, _screenshareVideoTrack, _screenshareAudioTrack; var _CallParticipant = class _CallParticipant extends EventsHandler { constructor(options) { super(); __privateAdd(this, _ctx2); __privateAdd(this, _micEnabled$); __privateAdd(this, _micTrackData$); __privateAdd(this, _micEnabled, false); __privateAdd(this, _micTrack); __privateAdd(this, _cameraEnabled$); __privateAdd(this, _cameraTrackData$); __privateAdd(this, _cameraEnabled, false); __privateAdd(this, _cameraTrack); __privateAdd(this, _screenshareEnabled$, new rxjs.BehaviorSubject(false)); __privateAdd(this, _screenshareVideoTrackData$); __privateAdd(this, _screenshareAudioTrackData$); __privateAdd(this, _screenshareEnabled, false); __privateAdd(this, _screenshareVideoTrack); __privateAdd(this, _screenshareAudioTrack); this.id = options.id; this.name = options.name; __privateSet(this, _ctx2, getCurrentCallContext()); __privateSet(this, _micEnabled$, new rxjs.BehaviorSubject( options.micEnabled || false )); __privateSet(this, _micTrackData$, new rxjs.BehaviorSubject( options.micEnabled ? options.micTrackData : void 0 )); __privateSet(this, _cameraEnabled$, new rxjs.BehaviorSubject( options.cameraEnabled || false )); __privateSet(this, _cameraTrackData$, new rxjs.BehaviorSubject( options.cameraEnabled ? options.cameraTrackData : void 0 )); __privateSet(this, _screenshareEnabled, options.screenshareEnabled || false); __privateSet(this, _screenshareVideoTrackData$, new rxjs.BehaviorSubject( options.screenshareEnabled ? options.screenshareVideoTrackData : void 0 )); __privateSet(this, _screenshareAudioTrackData$, new rxjs.BehaviorSubject( options.screenshareEnabled ? options.screenshareAudioTrackData : void 0 )); __privateGet(this, _micEnabled$).subscribe((enabled) => { if (!enabled) { __privateSet(this, _micEnabled, false); this.emit("micUpdate", { micEnabled: false }); __privateGet(this, _ctx2).call.participants.joined.emit("micUpdate", this); } else if (enabled && __privateGet(this, _micTrack)) { __privateSet(this, _micEnabled, true); this.emit("micUpdate", { micEnabled: true, micTrack: __privateGet(this, _micTrack) }); __privateGet(this, _ctx2).call.participants.joined.emit("micUpdate", this); __privateGet(this, _ctx2).call.participants.emit("micUpdate", this); } }); const micMetadata$ = __privateGet(this, _micTrackData$).pipe(rxjs.filter(Boolean)); const micTrack$ = __privateGet(this, _ctx2).partyTracks.pull(micMetadata$); micTrack$.subscribe((track) => { __privateSet(this, _micEnabled, true); __privateSet(this, _micTrack, track); this.emit("micUpdate", { micEnabled: true, micTrack: track }); __privateGet(this, _ctx2).call.participants.joined.emit("micUpdate", this); __privateGet(this, _ctx2).call.participants.emit("micUpdate", this); }); __privateGet(this, _cameraEnabled$).subscribe((enabled) => { if (!enabled) { __privateSet(this, _cameraEnabled, false); this.emit("cameraUpdate", { cameraEnabled: false }); __privateGet(this, _ctx2).call.participants.joined.emit("cameraUpdate", this); __privateGet(this, _ctx2).call.participants.emit("cameraUpdate", this); } else if (enabled && __privateGet(this, _cameraTrack)) { __privateSet(this, _cameraEnabled, true); this.emit("cameraUpdate", { cameraEnabled: true, cameraTrack: __privateGet(this, _cameraTrack) }); __privateGet(this, _ctx2).call.participants.joined.emit("cameraUpdate", this); __privateGet(this, _ctx2).call.participants.emit("cameraUpdate", this); } }); const cameraMetadata$ = __privateGet(this, _cameraTrackData$).pipe(rxjs.filter(Boolean)); const cameraTrack$ = __privateGet(this, _ctx2).partyTracks.pull(cameraMetadata$, { simulcast: { preferredRid$: __privateGet(this, _ctx2).cameraRid$.asObservable() } }); cameraTrack$.subscribe((track) => { __privateSet(this, _cameraEnabled, true); __privateSet(this, _cameraTrack, track); this.emit("cameraUpdate", { cameraEnabled: true, cameraTrack: track }); __privateGet(this, _ctx2).call.participants.joined.emit("cameraUpdate", this); __privateGet(this, _ctx2).call.participants.emit("cameraUpdate", this); }); const screenshareVideoMetadata$ = __privateGet(this, _screenshareVideoTrackData$).pipe( rxjs.filter(Boolean) ); const screenshareVideoTrack$ = __privateGet(this, _ctx2).partyTracks.pull( screenshareVideoMetadata$ ); screenshareVideoTrack$.subscribe((track) => { __privateSet(this, _screenshareVideoTrack, track); this.emit("screenshareUpdate", { screenshareEnabled: true, screenshareVideoTrack: track, screenshareAudioTrack: __privateGet(this, _screenshareAudioTrack) }); __privateGet(this, _ctx2).call.participants.joined.emit("screenshareUpdate", this); __privateGet(this, _ctx2).call.participants.emit("screenshareUpdate", this); }); const screenshareAudioMetadata$ = __privateGet(this, _screenshareAudioTrackData$).pipe( rxjs.filter(Boolean) ); const screenshareAudioTrack$ = __privateGet(this, _ctx2).partyTracks.pull( screenshareAudioMetadata$ ); screenshareAudioTrack$.subscribe((track) => { __privateSet(this, _screenshareAudioTrack, track); this.emit("screenshareUpdate", { screenshareEnabled: true, screenshareVideoTrack: __privateGet(this, _screenshareVideoTrack), screenshareAudioTrack: track }); __privateGet(this, _ctx2).call.participants.joined.emit("screenshareUpdate", this); __privateGet(this, _ctx2).call.participants.emit("screenshareUpdate", this); }); } updateMicState(updates) { __privateGet(this, _ctx2).logger.debug("\u{1F399}\uFE0F participant mic state updated", updates); if (updates.micEnabled && updates.micTrackData) { __privateGet(this, _micTrackData$).next(updates.micTrackData); __privateGet(this, _micEnabled$).next(true); } else { __privateGet(this, _micEnabled$).next(false); } } updateCameraState(updates) { __privateGet(this, _ctx2).logger.debug("\u{1F3A5} participant camera state updated", updates); if (updates.cameraEnabled && updates.cameraTrackData) { __privateGet(this, _cameraTrackData$).next(updates.cameraTrackData); __privateGet(this, _cameraEnabled$).next(true); } else { __privateGet(this, _cameraTrackData$).next(void 0); __privateGet(this, _cameraEnabled$).next(false); } } updateScreenshareState(updates) { __privateGet(this, _ctx2).logger.debug("\u{1F5A5}\uFE0F participant screenshare state updated", updates); if (updates.screenshareEnabled) { if (updates.screenshareVideoTrackData) { __privateGet(this, _screenshareVideoTrackData$).next( updates.screenshareVideoTrackData ); } if (updates.screenshareAudioTrackData) { __privateGet(this, _screenshareAudioTrackData$).next( updates.screenshareAudioTrackData ); } __privateGet(this, _screenshareEnabled$).next(true); __privateSet(this, _screenshareEnabled, true); } else { __privateGet(this, _screenshareEnabled$).next(false); __privateGet(this, _screenshareVideoTrackData$).next(void 0); __privateGet(this, _screenshareAudioTrackData$).next(void 0); __privateSet(this, _screenshareEnabled, false); this.emit("screenshareUpdate", { screenshareEnabled: false }); __privateGet(this, _ctx2).call.participants.joined.emit("screenshareUpdate", this); __privateGet(this, _ctx2).call.participants.emit("screenshareUpdate", this); } } get micEnabled() { return __privateGet(this, _micEnabled); } get micTrack() { return __privateGet(this, _micEnabled) ? __privateGet(this, _micTrack) : void 0; } get cameraEnabled() { return __privateGet(this, _cameraEnabled); } get cameraTrack() { return __privateGet(this, _cameraEnabled) ? __privateGet(this, _cameraTrack) : void 0; } get screenshareEnabled() { return __privateGet(this, _screenshareEnabled); } get screenshareTracks() { if (!this.screenshareEnabled) { return void 0; } return { video: __privateGet(this, _screenshareVideoTrack), audio: __privateGet(this, _screenshareAudioTrack) }; } toString() { return `CallParticipant::${this.id}::${this.name}`; } static fromJSON(obj) { return new _CallParticipant(obj); } }; _ctx2 = new WeakMap(); _micEnabled$ = new WeakMap(); _micTrackData$ = new WeakMap(); _micEnabled = new WeakMap(); _micTrack = new WeakMap(); _cameraEnabled$ = new WeakMap(); _cameraTrackData$ = new WeakMap(); _cameraEnabled = new WeakMap(); _cameraTrack = new WeakMap(); _screenshareEnabled$ = new WeakMap(); _screenshareVideoTrackData$ = new WeakMap(); _screenshareAudioTrackData$ = new WeakMap(); _screenshareEnabled = new WeakMap(); _screenshareVideoTrack = new WeakMap(); _screenshareAudioTrack = new WeakMap(); var CallParticipant = _CallParticipant; // src/lib/call-participant-map/call-participant-map.ts var _participants; var CallParticipantMap = class extends EventsHandler { constructor() { super(); __privateAdd(this, _participants, /* @__PURE__ */ new Map()); } get(id) { return __privateGet(this, _participants).get(id); } set(id, participant) { const isUpdate = __privateGet(this, _participants).has(id); __privateGet(this, _participants).set(id, participant); this.emit(isUpdate ? "updated" : "added", participant); return this; } delete(id) { const removed = __privateGet(this, _participants).get(id); const didDelete = __privateGet(this, _participants).delete(id); if (didDelete && removed) { this.emit("removed", removed); } return didDelete; } has(id) { return __privateGet(this, _participants).has(id); } values() { return __privateGet(this, _participants).values(); } keys() { return __privateGet(this, _participants).keys(); } entries() { return __privateGet(this, _participants).entries(); } forEach(callbackfn, thisArg) { return __privateGet(this, _participants).forEach(callbackfn, thisArg); } get size() { return __privateGet(this, _participants).size; } clear() { __privateGet(this, _participants).clear(); this.emit("cleared"); } toArray() { return Array.from(__privateGet(this, _participants).values()); } [Symbol.iterator]() { return __privateGet(this, _participants)[Symbol.iterator](); } get [Symbol.toStringTag]() { return "CallParticipantMap"; } }; _participants = new WeakMap(); // src/lib/participants-controller/participants-controller.ts var ParticipantsController = class extends EventsHandler { constructor() { super(); this.joined = new CallParticipantMap(); } addParticipant(participant) { this.joined.set(participant.id, participant); } removeParticipantById(participantId) { this.joined.delete(participantId); } }; var _ctx3, _mic, _camera, _screenshare, _micEnabled2, _micTrackData, _micTrack2, _cameraEnabled2, _cameraTrackData, _cameraTrack2, _screenshareEnabled2, _screenshareVideoTrackData, _screenshareVideoTrack2, _screenshareAudioTrackData, _screenshareAudioTrack2, _micDevice, _cameraDevice, _devices; var CallSelf = class extends EventsHandler { constructor(options) { var _a, _b; super(); this.id = crypto.randomUUID(); __privateAdd(this, _ctx3); __privateAdd(this, _mic); __privateAdd(this, _camera); __privateAdd(this, _screenshare); __privateAdd(this, _micEnabled2, false); __privateAdd(this, _micTrackData); __privateAdd(this, _micTrack2); __privateAdd(this, _cameraEnabled2, false); __privateAdd(this, _cameraTrackData); __privateAdd(this, _cameraTrack2); __privateAdd(this, _screenshareEnabled2, false); __privateAdd(this, _screenshareVideoTrackData); __privateAdd(this, _screenshareVideoTrack2); __privateAdd(this, _screenshareAudioTrackData); __privateAdd(this, _screenshareAudioTrack2); __privateAdd(this, _micDevice); __privateAdd(this, _cameraDevice); __privateAdd(this, _devices); this.name = options.name; __privateSet(this, _ctx3, getCurrentCallContext()); __privateSet(this, _mic, client.getMic()); __privateSet(this, _camera, client.getCamera()); __privateGet(this, _mic).isBroadcasting$.subscribe((enabled) => { __privateSet(this, _micEnabled2, enabled); }); __privateGet(this, _mic).broadcastTrack$.subscribe((track) => { __privateSet(this, _micTrack2, track); }); __privateGet(this, _camera).isBroadcasting$.subscribe((enabled) => { __privateSet(this, _cameraEnabled2, enabled); }); __privateGet(this, _camera).broadcastTrack$.subscribe((track) => { __privateSet(this, _cameraTrack2, track); }); __privateGet(this, _mic).activeDevice$.subscribe((device) => { __privateSet(this, _micDevice, device); this.emit("activeDeviceUpdate", "mic", device); }); __privateGet(this, _camera).activeDevice$.subscribe((device) => { __privateSet(this, _cameraDevice, device); this.emit("activeDeviceUpdate", "camera", device); }); client.devices$.subscribe((devices) => { __privateSet(this, _devices, devices); this.emit("devicesUpdate", devices); }); const micMetadata$ = __privateGet(this, _ctx3).partyTracks.push(__privateGet(this, _mic).broadcastTrack$, { sendEncodings$: rxjs.of([ { networkPriority: "high" } ]) }); micMetadata$.subscribe((metadata) => { if (__privateGet(this, _micEnabled2) && __privateGet(this, _micTrack2)) { __privateSet(this, _micTrackData, metadata); __privateGet(this, _ctx3).socket.sendAction({ action: "self/mic-update", updates: { micEnabled: true, micTrackData: metadata } }); this.emit("micUpdate", { micEnabled: true, micTrack: __privateGet(this, _micTrack2) }); } else if (!__privateGet(this, _micEnabled2)) { __privateGet(this, _ctx3).socket.sendAction({ action: "self/mic-update", updates: { micEnabled: false } }); this.emit("micUpdate", { micEnabled: false }); } }); const cameraMetadata$ = __privateGet(this, _ctx3).partyTracks.push( __privateGet(this, _camera).broadcastTrack$, { sendEncodings$: __privateGet(this, _ctx3).cameraEncodings$.asObservable() } ); cameraMetadata$.subscribe((metadata) => { if (__privateGet(this, _cameraEnabled2) && __privateGet(this, _cameraTrack2)) { __privateSet(this, _cameraTrackData, metadata); __privateGet(this, _ctx3).socket.sendAction({ action: "self/camera-update", updates: { cameraEnabled: true, cameraTrackData: metadata } }); this.emit("cameraUpdate", { cameraEnabled: true, cameraTrack: __privateGet(this, _cameraTrack2) }); } else if (!__privateGet(this, _cameraEnabled2)) { __privateSet(this, _cameraTrackData, void 0); __privateGet(this, _ctx3).socket.sendAction({ action: "self/camera-update", updates: { cameraEnabled: false } }); this.emit("cameraUpdate", { cameraEnabled: false }); } }); if ((_a = options.defaults) == null ? void 0 : _a.audio) { this.startMic(); } if ((_b = options.defaults) == null ? void 0 : _b.video) { this.startCamera(); } __privateSet(this, _screenshare, client.getScreenshare({ audio: true })); __privateGet(this, _screenshare).video.isBroadcasting$.subscribe((enabled) => { __privateSet(this, _screenshareEnabled2, enabled); }); __privateGet(this, _screenshare).video.broadcastTrack$.subscribe((track) => { __privateSet(this, _screenshareVideoTrack2, track); }); __privateGet(this, _screenshare).audio.broadcastTrack$.subscribe((track) => { __privateSet(this, _screenshareAudioTrack2, track); }); const screenshareVideoMetadata$ = __privateGet(this, _ctx3).partyTracks.push( __privateGet(this, _screenshare).video.broadcastTrack$ ); const screenshareAudioMetadata$ = __privateGet(this, _ctx3).partyTracks.push( __privateGet(this, _screenshare).audio.broadcastTrack$ ); screenshareVideoMetadata$.subscribe((metadata) => { if (!__privateGet(this, _screenshareEnabled2)) { __privateGet(this, _ctx3).socket.sendAction({ action: "self/screenshare-update", updates: { screenshareEnabled: false } }); this.emit("screenshareUpdate", { screenshareEnabled: false }); } else { __privateSet(this, _screenshareVideoTrackData, metadata); __privateGet(this, _ctx3).socket.sendAction({ action: "self/screenshare-update", updates: { screenshareEnabled: true, screenshareVideoTrackData: __privateGet(this, _screenshareVideoTrackData) } }); this.emit("screenshareUpdate", { screenshareEnabled: true, screenshareVideoTrack: __privateGet(this, _screenshareVideoTrack2) }); } }); screenshareAudioMetadata$.subscribe((metadata) => { if (!__privateGet(this, _screenshareEnabled2)) { __privateGet(this, _ctx3).socket.sendAction({ action: "self/screenshare-update", updates: { screenshareEnabled: false } }); this.emit("screenshareUpdate", { screenshareEnabled: false }); } else { __privateSet(this, _screenshareAudioTrackData, metadata); __privateGet(this, _ctx3).socket.sendAction({ action: "self/screenshare-update", updates: { screenshareEnabled: true, screenshareAudioTrackData: __privateGet(this, _screenshareAudioTrackData) } }); this.emit("screenshareUpdate", { screenshareEnabled: true, screenshareAudioTrack: __privateGet(this, _screenshareAudioTrack2) }); } }); } startMic() { __privateGet(this, _mic).startBroadcasting(); } stopMic() { __privateGet(this, _mic).stopBroadcasting(); } startCamera() { __privateGet(this, _camera).startBroadcasting(); } stopCamera() { __privateGet(this, _camera).stopBroadcasting(); } startScreenshare() { __privateGet(this, _screenshare).startBroadcasting(); } stopScreenshare() { __privateGet(this, _screenshare).stopBroadcasting(); } setCameraDevice(deviceId) { return __async(this, null, function* () { const devices = this.devices; const device = devices == null ? void 0 : devices.find((d) => d.deviceId === deviceId); if (!device) { throw new Error(`Camera device not found: ${deviceId}`); } __privateGet(this, _camera).setPreferredDevice(device); }); } setMicDevice(deviceId) { return __async(this, null, function* () { const devices = this.devices; const device = devices == null ? void 0 : devices.find((d) => d.deviceId === deviceId); if (!device) { throw new Error(`Microphone device not found: ${deviceId}`); } __privateGet(this, _mic).setPreferredDevice(device); }); } get micEnabled() { return __privateGet(this, _micEnabled2); } get micTrack() { return __privateGet(this, _micEnabled2) ? __privateGet(this, _micTrack2) : void 0; } get cameraEnabled() { return __privateGet(this, _cameraEnabled2); } get cameraTrack() { return __privateGet(this, _cameraEnabled2) ? __privateGet(this, _cameraTrack2) : void 0; } get screenshareEnabled() { return __privateGet(this, _screenshareEnabled2); } get screenshareTracks() { if (!this.screenshareEnabled) { return void 0; } return { video: __privateGet(this, _screenshareVideoTrack2), audio: __privateGet(this, _screenshareAudioTrack2) }; } get devices() { return __privateGet(this, _devices); } get activeDevices() { var _a, _b, _c, _d; return { mic: (_b = __privateGet(this, _micDevice)) != null ? _b : (_a = this.devices) == null ? void 0 : _a.find( (d) => d.deviceId === "default" && d.kind === "audioinput" ), camera: (_d = __privateGet(this, _cameraDevice)) != null ? _d : (_c = this.devices) == null ? void 0 : _c.find( (d) => d.deviceId === "default" && d.kind === "videoinput" ) }; } setName(name) { const oldName = this.name; this.name = name; this.emit("nameChange", this.name, oldName); } toJSON() { return { id: this.id, name: this.name, micEnabled: this.micEnabled, micTrackData: __privateGet(this, _micTrackData), cameraEnabled: this.cameraEnabled, cameraTrackData: __privateGet(this, _cameraTrackData), screenshareEnabled: this.screenshareEnabled, screenshareVideoTrackData: __privateGet(this, _screenshareVideoTrackData), screenshareAudioTrackData: __privateGet(this, _screenshareAudioTrackData) }; } toString() { return `CallSelf::${this.id}::${this.name}`; } }; _ctx3 = new WeakMap(); _mic = new WeakMap(); _camera = new WeakMap(); _screenshare = new WeakMap(); _micEnabled2 = new WeakMap(); _micTrackData = new WeakMap(); _micTrack2 = new WeakMap(); _cameraEnabled2 = new WeakMap(); _cameraTrackData = new WeakMap(); _cameraTrack2 = new WeakMap(); _screenshareEnabled2 = new WeakMap(); _screenshareVideoTrackData = new WeakMap(); _screenshareVideoTrack2 = new WeakMap(); _screenshareAudioTrackData = new WeakMap(); _screenshareAudioTrack2 = new WeakMap(); _micDevice = new WeakMap(); _cameraDevice = new WeakMap(); _devices = new WeakMap(); var _logger; var CallSocket = class extends PartySocket__default.default { constructor(options) { super(options); __privateAdd(this, _logger); __privateSet(this, _logger, options.logger); } sendAction(action) { __privateGet(this, _logger).debug("CallSocket:sendAction", action); return this.send(JSON.stringify(action)); } }; _logger = new WeakMap(); // src/lib/call-self/call-self-data.ts var cameraEncodings = [ { rid: "a", maxBitrate: 13e5, maxFramerate: 30 }, { rid: "b", scaleResolutionDownBy: 2, maxBitrate: 5e5, maxFramerate: 24 } ]; // src/lib/call-client/call-client.ts var _ctx4, _logger2, _autoJoin, _CallClient_instances, onMessage_fn; var CallClient = class extends EventsHandler { constructor(options) { var _a, _b, _c, _d; super(); __privateAdd(this, _CallClient_instances); this.state = void 0; __privateAdd(this, _ctx4); __privateAdd(this, _logger2); __privateAdd(this, _autoJoin); this.room = options.room; __privateSet(this, _autoJoin, options.autoJoin || false); __privateSet(this, _logger2, new Logger({ level: (_a = options.logLevel) != null ? _a : "warn", prefix: "callskit" })); client.setLogLevel((_b = options.logLevel) != null ? _b : "warn"); const socket = new CallSocket({ room: this.room, host: options.socketBaseUrl, logger: __privateGet(this, _logger2) }); socket.addEventListener("message", __privateMethod(this, _CallClient_instances, onMessage_fn).bind(this)); if (options.onError) { const onError = options.onError; socket.addEventListener("error", (e) => { onError(new Error("Error while connecting to server")); }); } const partyTracks = new client.PartyTracks({ prefix: options.apiBaseUrl + "/partytracks", headers: options.apiHeaders }); let unsubSession = partyTracks.session$.subscribe( () => { this.emit("mediaConnected"); unsubSession.unsubscribe(); unsubSession = void 0; } ); __privateSet(this, _ctx4, { socket, partyTracks, call: this, logger: __privateGet(this, _logger2), cameraRid$: new rxjs.BehaviorSubject( (_d = (_c = options.config) == null ? void 0 : _c.preferredCameraQuality) != null ? _d : "a" ), cameraEncodings$: new rxjs.BehaviorSubject( cameraEncodings ), onError: options.onError }); this.self = runWithContext( __privateGet(this, _ctx4), () => new CallSelf({ name: options.displayName, defaults: options.defaults }) ); this.participants = runWithContext( __privateGet(this, _ctx4), () => new ParticipantsController() ); this.chat = runWithContext(__privateGet(this, _ctx4), () => new CallChat()); } join() { if (this.state !== "connected") return; __privateGet(this, _ctx4).socket.sendAction({ action: "join", self: this.self.toJSON() }); } leave() { __privateGet(this, _ctx4).socket.close(); this.state = "left"; this.emit("left"); } get cameraTrackQuality() { return __privateGet(this, _ctx4).cameraRid$.value; } /** * Set the preferred remote camera track quality. * - `a` - full quality * - `b` - half quality */ setRemoteCameraTrackQuality(quality) { const qualities = ["a", "b"]; if (qualities.includes(quality)) { const oldQuality = __privateGet(this, _ctx4).cameraRid$.value; __privateGet(this, _ctx4).cameraRid$.next(quality); this.emit("cameraQualityChanged", quality, oldQuality); } } }; _ctx4 = new WeakMap(); _logger2 = new WeakMap(); _autoJoin = new WeakMap(); _CallClient_instances = new WeakSet(); onMessage_fn = function(event) { const ev = JSON.parse(event.data); __privateGet(this, _logger2).debug("\u{1F4E9} CallSocket:Event", ev); switch (ev.event) { case "connected": this.state = "connected"; this.emit("connected"); if (__privateGet(this, _autoJoin)) { this.join(); } break; case "room/init": { if (this.state !== "connected") return; const user_objects = ev.participants; runWithContext( __privateGet(this, _ctx4), () => user_objects.map((obj) => CallParticipant.fromJSON(obj)) ).forEach((participant) => { this.participants.addParticipant(participant); }); this.started_at = new Date(ev.started_at); this.chat.addMessagesInBulk(ev.chatMessages); this.state = "joined"; this.emit("joined"); break; } case "participant/joined": { const participant = runWithContext( __privateGet(this, _ctx4), () => CallParticipant.fromJSON(ev.participant) ); this.participants.addParticipant(participant); break; } case "participant/left": { this.participants.removeParticipantById(ev.participantId); break; } case "participant/mic-update": { const _a = ev.data, { participantId } = _a, updates = __objRest(_a, ["participantId"]); const participant = this.participants.joined.get(participantId); participant == null ? void 0 : participant.updateMicState(updates); break; } case "participant/camera-update": { const _b = ev.data, { participantId } = _b, updates = __objRest(_b, ["participantId"]); const participant = this.participants.joined.get(participantId); participant == null ? void 0 : participant.updateCameraState(updates); break; } case "participant/screenshare-update": { const _c = ev.data, { participantId } = _c, updates = __objRest(_c, ["participantId"]); const participant = this.participants.joined.get(participantId); participant == null ? void 0 : participant.updateScreenshareState(updates); break; } case "chat/new-message": { this.chat.addMessage(ev.message); break; } default: __privateGet(this, _logger2).info("Received unknown event:", ev); break; } }; // src/index.ts function createCallClient(options) { return __async(this, null, function* () { return new Promise((resolve, reject) => { const client = new CallClient(options); let socketConnected = false, mediaConnected = false; const checkConnection = () => { if (socketConnected && mediaConnected) { resolve(client); } }; client.once("connected", () => { socketConnected = true; checkConnection(); }); client.once("mediaConnected", () => { mediaConnected = true; checkConnection(); }); setTimeout(() => { if (!socketConnected && !mediaConnected) { reject(new Error("Both socket and media connections timed out")); } else if (!socketConnected) { reject(new Error("Socket connection timed out")); } else if (!mediaConnected) { reject(new Error("Media connection timed out")); } }, 1e4); }); }); } // ../node_modules/lodash-es/isObject.js function isObject(value) { var type = typeof value; return value != null && (type == "object" || type == "function"); } var isObject_default = isObject; // ../node_modules/lodash-es/_freeGlobal.js var freeGlobal = typeof global == "object" && global && global.Object === Object && global; var freeGlobal_default = freeGlobal; // ../node_modules/lodash-es/_root.js var freeSelf = typeof self == "object" && self && self.Object === Object && self; var root = freeGlobal_default || freeSelf || Function("return this")(); var root_default = root; // ../node_modules/lodash-es/now.js var now = function() { return root_default.Date.now(); }; var now_default = now; // ../node_modules/lodash-es/_trimmedEndIndex.js var reWhitespace = /\s/; function trimmedEndIndex(string) { var index = string.length; while (index-- && reWhitespace.test(string.charAt(index))) { } return index; } var trimmedEndIndex_default = trimmedEndIndex; // ../node_modules/lodash-es/_baseTrim.js var reTrimStart = /^\s+/; function baseTrim(string) { return string ? string.slice(0, trimmedEndIndex_default(string) + 1).replace(reTrimStart, "") : string; } var baseTrim_default = baseTrim; // ../node_modules/lodash-es/_Symbol.js var Symbol2 = root_default.Symbol; var Symbol_default = Symbol2; // ../node_modules/lodash-es/_getRawTag.js var objectProto = Object.prototype; var hasOwnProperty = objectProto.hasOwnProperty; var nativeObjectToString = objectProto.toString; var symToStringTag = Symbol_default ? Symbol_default.toStringTag : void 0; function getRawTag(value) { var isOwn = hasOwnProperty.call(value, symToStringTag), tag = value[symToStringTag]; try { value[symToStringTag] = void 0; var unmasked = true; } catch (e) { } var result = nativeObjectToString.call(value); if (unmasked) { if (isOwn) { value[symToStringTag] = tag; } else { delete value[symToStringTag]; } } return result; } var getRawTag_default = getRawTag; // ../node_modules/lodash-es/_objectToString.js var objectProto2 = Object.prototype; var nativeObjectToString2 = objectProto2.toString; function objectToString(value) { return nativeObjectToString2.call(value); } var objectToString_default = objectToString; // ../node_modules/lodash-es/_baseGetTag.js var nullTag = "[object Null]"; var undefinedTag = "[object Undefined]"; var symToStringTag2 = Symbol_default ? Symbol_default.toStringTag : void 0; function baseGetTag(value) { if (value == null) { return value === void 0 ? undefinedTag : nullTag; } return symToStringTag2 && symToStringTag2 in Object(value) ? getRawTag_default(value) : objectToString_default(value); } var baseGetTag_default = baseGetTag; // ../node_modules/lodash-es/isObjectLike.js function isObjectLike(value) { return value != null && typeof value == "object"; } var isObjectLike_default = isObjectLike; // ../node_modules/lodash-es/isSymbol.js var symbolTag = "[object Symbol]"; function isSymbol(value) { return typeof value == "symbol" || isObjectLike_default(value) && baseGetTag_default(value) == symbolTag; } var isSymbol_default = isSymbol; // ../node_modules/lodash-es/toNumber.js var NAN = 0 / 0; var reIsBadHex = /^[-+]0x[0-9a-f]+$/i; var reIsBinary = /^0b[01]+$/i; var reIsOctal = /^0o[0-7]+$/i; var freeParseInt = parseInt; function toNumber(value) { if (typeof value == "number") { return value; } if (isSymbol_default(value)) { return NAN; } if (isObject_default(value)) { var other = typeof value.valueOf == "function" ? value.valueOf() : value; value = isObject_default(other) ? other + "" : other; } if (typeof value != "string") { return value === 0 ? value : +value; } value = baseTrim_default(value); var isBinary = reIsBinary.test(value); return isBinary || reIsOctal.test(value) ? freeParseInt(value.slice(2), isBinary ? 2 : 8) : reIsBadHex.test(value) ? NAN : +value; } var toNumber_default = toNumber; // ../node_modules/lodash-es/debounce.js var FUNC_ERROR_TEXT = "Expected a function"; var nativeMax = Math.max; var nativeMin = Math.min; function debounce(func, wait, options) { var lastArgs, lastThis, maxWait, result, timerId, lastCallTime, lastInvokeTime = 0, leading = false, maxing = false, trailing = true; if (typeof func != "function") { throw new TypeError(FUNC_ERROR_TEXT); } wait = toNumber_default(wait) || 0; if (isObject_default(options)) { leading = !!options.leading; maxing = "maxWait" in options; maxWait = maxing ? nativeMax(toNumber_default(options.maxWait) || 0, wait) : maxWait; trailing = "trailing" in options ? !!options.trailing : trailing; } function invokeFunc(time) { var args = lastArgs, thisArg = lastThis; lastArgs = lastThis = void 0; lastInvokeTime = time; result = func.apply(thisArg, args); return result; } function leadingEdge(time) { lastInvokeTime = time; timerId = setTimeout(timerExpired, wait); return leading ? invokeFunc(time) : result; } function remainingWait(time) { var timeSinceLastCall = time - lastCallTime, timeSinceLastInvoke = time - lastInvokeTime, timeWaiting = wait - timeSinceLastCall; return maxing ? nativeMin(timeWaiting, maxWait - timeSinceLastInvoke) : timeWaiting; } function shouldInvoke(time) { var timeSinceLastCall = time - lastCallTime, timeSinceLastInvoke = time - lastInvokeTime; return lastCallTime === void 0 || timeSinceLastCall >= wait || timeSinceLastCall < 0 || maxing && timeSinceLastInvoke >= maxWait; } function timerExpired() { var time = now_default(); if (shouldInvoke(time)) { return trailingEdge(time); } timerId = setTimeout(timerExpired, remainingWait(time)); } function trailingEdge(time) { timerId = void 0; if (trailing && lastArgs) { return invokeFunc(time); } lastArgs = lastThis = void 0; return result; } function cancel() { if (timerId !== void 0) { clearTimeout(timerId); } lastInvokeTime = 0; lastArgs = lastCallTime = lastThis = timerId = void 0; } function flush() { return timerId === void 0 ? result : trailingEdge(now_default()); } function debounced() { var time = now_default(), isInvoking = shouldInvoke(time); lastArgs = arguments; lastThis = this; lastCallTime = time; if (isInvoking) { if (timerId === void 0) { return leadingEdge(lastCallTime); } if (maxing) { clearTimeout(timerId); timerId = setTimeout(timerExpired, wait); return invokeFunc(lastCallTime); } } if (timerId === void 0) { timerId = setTimeout(timerExpired, wait); } return result; } debounced.cancel = cancel; debounced.flush = flush; return debounced; } var debounce_default = debounce; // ../node_modules/lodash-es/throttle.js var FUNC_ERROR_TEXT2 = "Expected a function"; function throttle(func, wait, options) { var leading = true, trailing = true; if (typeof func != "function") { throw new TypeError(FUNC_ERROR_TEXT2); } if (isObject_default(options)) { leading = "leading" in options ? !!options.leading : leading; trailing = "trailing" in options ? !!options.trailing : trailing; } return debounce_default(func, wait, { "leading": leading, "maxWait": wait, "trailing": trailing }); } var throttle_default = throttle; // src/react/shallow.ts var isIterable = (obj) => Symbol.iterator in obj; var hasIterableEntries = (value) => ( // HACK: avoid checking entries type "entries" in value ); var compareEntries = (valueA, valueB) => { const mapA = valueA instanceof Map ? valueA : new Map(valueA.entries()); const mapB = valueB instanceof Map ? valueB : new Map(valueB.entries()); if (mapA.size !== mapB.size) { return false; } for (const [key, value] of mapA) { if (!Object.is(value, mapB.get(key))) { return false; } } return true; }; var compareIterables = (valueA, valueB) => { const iteratorA = valueA[Symbol.iterator](); const iteratorB = valueB[Symbol.iterator](); let nextA = iteratorA.next(); let nextB = iteratorB.next(); while (!nextA.done && !nextB.done) { if (!Object.is(nextA.value, nextB.value)) { return false; } nextA = iteratorA.next(); nextB = iteratorB.next(); } return !!nextA.done && !!nextB.done; }; function shallow(valueA, valueB) { if (Object.is(valueA, valueB)) { return true; } if (typeof valueA !== "object" || valueA === null || typeof valueB !== "object" || valueB === null) { return false; } if (!isIterable(valueA) || !isIterable(valueB)) { return compareEntries( { entries: () => Object.entries(valueA) }, { entries: () => Object.entries(valueB) } ); } if (hasIterableEntries(valueA) && hasIterableEntries(valueB)) { return compareEntries(valueA, valueB); } return compareIterables(valueA, valueB); } // src/react/context.tsx var CallContext = React__default.default.createContext(void 0); function CallProvider({ call, fallback, children }) { const callbacks = React__default.default.useRef(/* @__PURE__ */ new Set()); const subscribe = React__default.default.useCallback((callback) => { callbacks.current.add(callback); return () => callbacks.current.delete(callback); }, []); React__default.default.useEffect(() => { if (!call) return; const onCallback = throttle_default(() => { callbacks.current.forEach((cb) => cb()); }, 180); const unsubscribeCall = call.subscribeAll(onCallback); const unsubscribeSelf = call.self.subscribeAll(onCallback); const unsubscribeChat = call.chat.subscribeAll(onCallback); return () => { unsubscribeCall(); unsubscribeSelf(); unsubscribeChat(); }; }, [call]); return /* @__PURE__ */ React__default.default.createElement(CallContext.Provider, { value: { call, subscribe } }, call ? children : fallback); } function useCall() { const ctx = React__default.default.useContext(CallContext); invariant2__default.default(ctx == null ? void 0 : ctx.call, "useCall must be used within a CallProvider"); return ctx.call; } function useCallSelector(selector) { const ctx = React__default.default.useContext(CallContext); invariant2__default.default(ctx == null ? void 0 : ctx.call, "useCallSelector must be used within a CallProvider"); const { call, subscribe } = ctx; const [, forceUpdate] = React__default.default.useReducer((x) => x + 1, 0); const selectorRef = React__default.default.useRef(selector); selectorRef.current = selector; const slice = selectorRef.current(call); const sliceRef = React__default.default.useRef(slice); sliceRef.current = slice; React__default.default.useEffect(() => { const unsubscribe = subscribe(() => { const nextSlice = selectorRef.current(call); if (!shallow(sliceRef.current, nextSlice)) { forceUpdate(); } }); return unsubscribe; }, [subscribe, call]); React__default.default.useEffect(() => { if (slice instanceof EventsHandler) { const unsubscribe = slice.subscribeAll(() => { forceUpdate(); }); return unsubscribe; } }, [slice]); return slice; } // src/react/index.ts function useCreateCall() { const [call, setCall] = React.useState(); const createCall = React.useCallback((options) => __async(null, null, function* () { const call2 = yield createCallClient(options); setCall(call2); return call2; }), []); return [call, createCall]; } exports.CallProvider = CallProvider; exports.useCall = useCall; exports.useCallSelector = useCallSelector; exports.useCreateCall = useCreateCall;