UNPKG

callskit

Version:

A toolkit for building call experience using Cloudflare Realtime

1,114 lines (1,102 loc) 39.2 kB
import { setLogLevel, PartyTracks, getMic, getCamera, devices$, getScreenshare } from 'partytracks/client'; import { Observable, BehaviorSubject, of, filter, switchMap } from 'rxjs'; import invariant from 'tiny-invariant'; import PartySocket from '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]; invariant(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 }); }; new Observable( (subscriber) => { const canvas = document.createElement("canvas"); canvas.height = 720; canvas.width = 1280; const ctx = canvas.getContext("2d"); invariant(ctx); ctx.fillStyle = "black"; ctx.fillRect(0, 0, canvas.width, canvas.height); const interval = setInterval(() => { ctx.fillStyle = "black"; ctx.fillRect(0, 0, canvas.width, canvas.height); }, 1e3); subscriber.next(canvas.captureStream().getVideoTracks()[0]); return () => { clearInterval(interval); }; } ); function getInaudibleTrack() { const audioContext = new AudioContext(); audioContext.resume(); const oscillator = audioContext.createOscillator(); oscillator.type = "triangle"; oscillator.frequency.setValueAtTime(20, audioContext.currentTime); const gainNode = audioContext.createGain(); gainNode.gain.setValueAtTime(0, audioContext.currentTime); oscillator.connect(gainNode); const destination = audioContext.createMediaStreamDestination(); gainNode.connect(destination); oscillator.start(); const track = destination.stream.getAudioTracks()[0]; return { track, audioContext }; } new Observable( (subscriber) => { const { audioContext, track } = getInaudibleTrack(); subscriber.next(track); return () => { track.stop(); audioContext.close(); }; } ); function createTrackId(metadata) { return `${metadata.sessionId}/${metadata.trackName}`; } function parseTrackId(trackId) { const [sessionId, trackName] = trackId.split("/"); return { sessionId, trackName }; } // src/lib/call-participant/call-participant.ts var _ctx2, _micEnabled$, _micTrackId$, _micEnabled, _micTrack, _cameraEnabled$, _cameraTrackId$, _cameraEnabled, _cameraTrack, _screenshareEnabled$, _screenshareVideoTrackId$, _screenshareAudioTrackId$, _screenshareEnabled, _screenshareVideoTrack, _screenshareAudioTrack; var _CallParticipant = class _CallParticipant extends EventsHandler { constructor(options) { super(); __privateAdd(this, _ctx2); __privateAdd(this, _micEnabled$); __privateAdd(this, _micTrackId$); __privateAdd(this, _micEnabled, false); __privateAdd(this, _micTrack); __privateAdd(this, _cameraEnabled$); __privateAdd(this, _cameraTrackId$); __privateAdd(this, _cameraEnabled, false); __privateAdd(this, _cameraTrack); __privateAdd(this, _screenshareEnabled$, new BehaviorSubject(false)); __privateAdd(this, _screenshareVideoTrackId$); __privateAdd(this, _screenshareAudioTrackId$); __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 BehaviorSubject( options.micEnabled || false )); __privateSet(this, _micTrackId$, new BehaviorSubject( options.micEnabled ? options.micTrackId : void 0 )); __privateSet(this, _cameraEnabled$, new BehaviorSubject( options.cameraEnabled || false )); __privateSet(this, _cameraTrackId$, new BehaviorSubject( options.cameraEnabled ? options.cameraTrackId : void 0 )); __privateSet(this, _screenshareEnabled, options.screenshareEnabled || false); __privateSet(this, _screenshareVideoTrackId$, new BehaviorSubject( options.screenshareEnabled ? options.screenshareVideoTrackId : void 0 )); __privateSet(this, _screenshareAudioTrackId$, new BehaviorSubject( options.screenshareEnabled ? options.screenshareAudioTrackId : 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, _micTrackId$).pipe( filter((id) => typeof id === "string"), switchMap((id) => { const { sessionId, trackName } = parseTrackId(id); return of({ sessionId, trackName, location: "remote" }); }) ); 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, _cameraTrackId$).pipe( filter((id) => typeof id === "string"), switchMap((id) => { const { sessionId, trackName } = parseTrackId(id); return of({ sessionId, trackName, location: "remote" }); }) ); const cameraTrack$ = __privateGet(this, _ctx2).partyTracks.pull(cameraMetadata$, { simulcast: { preferredRid$: __privateGet(this, _ctx2).cameraRid$ } }); 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, _screenshareVideoTrackId$).pipe( filter((id) => typeof id === "string"), switchMap((id) => { const { sessionId, trackName } = parseTrackId(id); return of({ sessionId, trackName, location: "remote" }); }) ); 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, _screenshareAudioTrackId$).pipe( filter((id) => typeof id === "string"), switchMap((id) => { const { sessionId, trackName } = parseTrackId(id); return of({ sessionId, trackName, location: "remote" }); }) ); 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.micTrackId) { __privateGet(this, _micTrackId$).next(updates.micTrackId); __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.cameraTrackId) { __privateGet(this, _cameraTrackId$).next(updates.cameraTrackId); __privateGet(this, _cameraEnabled$).next(true); } else { __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.screenshareVideoTrackId) { __privateGet(this, _screenshareVideoTrackId$).next(updates.screenshareVideoTrackId); } if (updates.screenshareAudioTrackId) { __privateGet(this, _screenshareAudioTrackId$).next(updates.screenshareAudioTrackId); } __privateGet(this, _screenshareEnabled$).next(true); __privateSet(this, _screenshareEnabled, true); } else { __privateGet(this, _screenshareEnabled$).next(false); __privateGet(this, _screenshareVideoTrackId$).next(void 0); __privateGet(this, _screenshareAudioTrackId$).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(); _micTrackId$ = new WeakMap(); _micEnabled = new WeakMap(); _micTrack = new WeakMap(); _cameraEnabled$ = new WeakMap(); _cameraTrackId$ = new WeakMap(); _cameraEnabled = new WeakMap(); _cameraTrack = new WeakMap(); _screenshareEnabled$ = new WeakMap(); _screenshareVideoTrackId$ = new WeakMap(); _screenshareAudioTrackId$ = 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, _micTrackId, _micTrack2, _cameraEnabled2, _cameraTrackId, _cameraTrack2, _screenshareEnabled2, _screenshareVideoTrackId, _screenshareVideoTrack2, _screenshareAudioTrackId, _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, _micTrackId); __privateAdd(this, _micTrack2); __privateAdd(this, _cameraEnabled2, false); __privateAdd(this, _cameraTrackId); __privateAdd(this, _cameraTrack2); __privateAdd(this, _screenshareEnabled2, false); __privateAdd(this, _screenshareVideoTrackId); __privateAdd(this, _screenshareVideoTrack2); __privateAdd(this, _screenshareAudioTrackId); __privateAdd(this, _screenshareAudioTrack2); __privateAdd(this, _micDevice); __privateAdd(this, _cameraDevice); __privateAdd(this, _devices); this.name = options.name; __privateSet(this, _ctx3, getCurrentCallContext()); __privateSet(this, _mic, getMic()); __privateSet(this, _camera, 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); }); devices$.subscribe((devices) => { __privateSet(this, _devices, devices); this.emit("devicesUpdate", devices); }); const micMetadata$ = __privateGet(this, _ctx3).partyTracks.push(__privateGet(this, _mic).broadcastTrack$, { sendEncodings$: of([ { networkPriority: "high" } ]) }); micMetadata$.subscribe((metadata) => { if (__privateGet(this, _micEnabled2) && __privateGet(this, _micTrack2)) { const micTrackId = createTrackId(metadata); __privateSet(this, _micTrackId, micTrackId); __privateGet(this, _ctx3).socket.sendAction({ action: "self/mic-update", updates: { micEnabled: true, micTrackId } }); 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$ } ); cameraMetadata$.subscribe((metadata) => { if (__privateGet(this, _cameraEnabled2) && __privateGet(this, _cameraTrack2)) { const cameraTrackId = createTrackId(metadata); __privateSet(this, _cameraTrackId, cameraTrackId); __privateGet(this, _ctx3).socket.sendAction({ action: "self/camera-update", updates: { cameraEnabled: true, cameraTrackId } }); this.emit("cameraUpdate", { cameraEnabled: true, cameraTrack: __privateGet(this, _cameraTrack2) }); } else if (!__privateGet(this, _cameraEnabled2)) { __privateSet(this, _cameraTrackId, 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, 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, _screenshareVideoTrackId, createTrackId(metadata)); __privateGet(this, _ctx3).socket.sendAction({ action: "self/screenshare-update", updates: { screenshareEnabled: true, screenshareVideoTrackId: __privateGet(this, _screenshareVideoTrackId) } }); 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, _screenshareAudioTrackId, createTrackId(metadata)); __privateGet(this, _ctx3).socket.sendAction({ action: "self/screenshare-update", updates: { screenshareEnabled: true, screenshareAudioTrackId: __privateGet(this, _screenshareAudioTrackId) } }); 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, micTrackId: __privateGet(this, _micTrackId), cameraEnabled: this.cameraEnabled, cameraTrackId: __privateGet(this, _cameraTrackId), screenshareEnabled: this.screenshareEnabled, screenshareVideoTrackId: __privateGet(this, _screenshareVideoTrackId), screenshareAudioTrackId: __privateGet(this, _screenshareAudioTrackId) }; } toString() { return `CallSelf::${this.id}::${this.name}`; } }; _ctx3 = new WeakMap(); _mic = new WeakMap(); _camera = new WeakMap(); _screenshare = new WeakMap(); _micEnabled2 = new WeakMap(); _micTrackId = new WeakMap(); _micTrack2 = new WeakMap(); _cameraEnabled2 = new WeakMap(); _cameraTrackId = new WeakMap(); _cameraTrack2 = new WeakMap(); _screenshareEnabled2 = new WeakMap(); _screenshareVideoTrackId = new WeakMap(); _screenshareVideoTrack2 = new WeakMap(); _screenshareAudioTrackId = new WeakMap(); _screenshareAudioTrack2 = new WeakMap(); _micDevice = new WeakMap(); _cameraDevice = new WeakMap(); _devices = new WeakMap(); var _logger; var CallSocket = class extends PartySocket { 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, active: true }, { rid: "b", scaleResolutionDownBy: 2, maxBitrate: 5e5, maxFramerate: 24, active: true } ]; // src/lib/call-client/call-client.ts setLogLevel("debug"); var _ctx4, _logger2, _autoJoin, _CallClient_instances, onMessage_fn; var CallClient = class extends EventsHandler { constructor(options) { var _a, _b, _c; 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', })); 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 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 BehaviorSubject( (_c = (_b = options.config) == null ? void 0 : _b.preferredCameraQuality) != null ? _c : "a" ), cameraEncodings$: new 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 remote camera track quality. * - `f` - full quality * - `h` - 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); }); }); } export { EventsHandler, __async, createCallClient };