@poolse/react 2.1.6 → 2.3.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/dist/index.cjs CHANGED
@@ -1063,6 +1063,185 @@ function formatDayLabel(iso, now = /* @__PURE__ */ new Date()) {
1063
1063
  }
1064
1064
  return d.toLocaleDateString(void 0, { day: "numeric", month: "short", year: "numeric" });
1065
1065
  }
1066
+ function useVoiceRoom(conversationId, opts = {}) {
1067
+ const poolse = usePoolse();
1068
+ const [status, setStatus] = react.useState("idle");
1069
+ const [participants, setParticipants] = react.useState([]);
1070
+ const [muted, setMuted] = react.useState(false);
1071
+ const [error, setError] = react.useState(null);
1072
+ const optsRef = react.useRef(opts);
1073
+ const room = react.useMemo(
1074
+ () => conversationId ? poolse.realtime.voice(conversationId, optsRef.current) : null,
1075
+ [poolse, conversationId]
1076
+ );
1077
+ react.useEffect(() => {
1078
+ if (!room) return;
1079
+ setStatus(room.getStatus());
1080
+ setParticipants(room.getParticipants());
1081
+ setMuted(room.isMuted());
1082
+ const offStatus = room.onStatus(setStatus);
1083
+ const offRoster = room.onParticipants(setParticipants);
1084
+ const offError = room.onError(setError);
1085
+ return () => {
1086
+ offStatus();
1087
+ offRoster();
1088
+ offError();
1089
+ room.leave();
1090
+ };
1091
+ }, [room]);
1092
+ const join = react.useCallback(async () => {
1093
+ if (!room) return;
1094
+ setError(null);
1095
+ try {
1096
+ await room.join();
1097
+ } catch (err) {
1098
+ setError(err instanceof Error ? err : new Error(String(err)));
1099
+ }
1100
+ }, [room]);
1101
+ const leave = react.useCallback(() => {
1102
+ room?.leave();
1103
+ }, [room]);
1104
+ const toggleMute = react.useCallback(() => {
1105
+ if (!room) return;
1106
+ setMuted(room.toggleMute());
1107
+ }, [room]);
1108
+ return { status, participants, muted, error, join, leave, toggleMute };
1109
+ }
1110
+ function useCalls(userId, opts = {}) {
1111
+ const ringTimeoutMs = opts.ringTimeoutMs ?? 45e3;
1112
+ const poolse = usePoolse();
1113
+ const [phase, setPhase] = react.useState("idle");
1114
+ const [incoming, setIncoming] = react.useState(null);
1115
+ const [outgoing, setOutgoing] = react.useState(null);
1116
+ const [activeConversationId, setActiveConversationId] = react.useState(null);
1117
+ const [error, setError] = react.useState(null);
1118
+ const actionsRef = react.useRef({
1119
+ cancel: async () => {
1120
+ },
1121
+ decline: async () => {
1122
+ }
1123
+ });
1124
+ const calls = react.useMemo(() => userId ? poolse.realtime.calls(userId) : null, [poolse, userId]);
1125
+ react.useEffect(() => {
1126
+ if (!calls) return;
1127
+ const offIncoming = calls.onIncoming((call2) => {
1128
+ setPhase((current) => {
1129
+ if (current !== "idle") {
1130
+ void calls.markBusy(call2).catch(() => {
1131
+ });
1132
+ return current;
1133
+ }
1134
+ setIncoming(call2);
1135
+ return "ringing-in";
1136
+ });
1137
+ });
1138
+ const offAccepted = calls.onAccepted((call2) => {
1139
+ setPhase("active");
1140
+ setActiveConversationId(call2.conversationId);
1141
+ });
1142
+ const offDeclined = calls.onDeclined(() => {
1143
+ setPhase("declined");
1144
+ setOutgoing(null);
1145
+ });
1146
+ const offBusy = calls.onBusy(() => {
1147
+ setPhase("busy");
1148
+ setOutgoing(null);
1149
+ });
1150
+ const offCancelled = calls.onCancelled((call2) => {
1151
+ setIncoming((current) => {
1152
+ if (current && current.callId !== call2.callId) return current;
1153
+ setPhase("idle");
1154
+ return null;
1155
+ });
1156
+ });
1157
+ return () => {
1158
+ offIncoming();
1159
+ offAccepted();
1160
+ offDeclined();
1161
+ offBusy();
1162
+ offCancelled();
1163
+ };
1164
+ }, [calls]);
1165
+ const call = react.useCallback(
1166
+ async (conversationId) => {
1167
+ if (!calls) return;
1168
+ setError(null);
1169
+ try {
1170
+ const placed = await calls.invite(conversationId);
1171
+ setOutgoing(placed);
1172
+ setPhase("ringing-out");
1173
+ } catch (err) {
1174
+ setError(err instanceof Error ? err : new Error(String(err)));
1175
+ setPhase("idle");
1176
+ }
1177
+ },
1178
+ [calls]
1179
+ );
1180
+ const accept = react.useCallback(async () => {
1181
+ if (!calls || !incoming) return;
1182
+ try {
1183
+ await calls.accept(incoming);
1184
+ setActiveConversationId(incoming.conversationId);
1185
+ setPhase("active");
1186
+ setIncoming(null);
1187
+ } catch (err) {
1188
+ setError(err instanceof Error ? err : new Error(String(err)));
1189
+ }
1190
+ }, [calls, incoming]);
1191
+ const decline = react.useCallback(async () => {
1192
+ if (!calls || !incoming) return;
1193
+ try {
1194
+ await calls.decline(incoming);
1195
+ } catch (err) {
1196
+ setError(err instanceof Error ? err : new Error(String(err)));
1197
+ } finally {
1198
+ setIncoming(null);
1199
+ setPhase("idle");
1200
+ }
1201
+ }, [calls, incoming]);
1202
+ const cancel = react.useCallback(async () => {
1203
+ if (!calls || !outgoing) return;
1204
+ try {
1205
+ await calls.cancel(outgoing);
1206
+ } catch (err) {
1207
+ setError(err instanceof Error ? err : new Error(String(err)));
1208
+ } finally {
1209
+ setOutgoing(null);
1210
+ setPhase("idle");
1211
+ }
1212
+ }, [calls, outgoing]);
1213
+ actionsRef.current = { cancel, decline };
1214
+ react.useEffect(() => {
1215
+ if (ringTimeoutMs <= 0) return;
1216
+ if (phase !== "ringing-out" && phase !== "ringing-in") return;
1217
+ const outbound = phase === "ringing-out";
1218
+ const timer = setTimeout(() => {
1219
+ void (outbound ? actionsRef.current.cancel() : actionsRef.current.decline()).finally(() => {
1220
+ if (outbound) setPhase("timed-out");
1221
+ });
1222
+ }, ringTimeoutMs);
1223
+ return () => clearTimeout(timer);
1224
+ }, [phase, ringTimeoutMs]);
1225
+ const reset = react.useCallback(() => {
1226
+ setPhase("idle");
1227
+ setIncoming(null);
1228
+ setOutgoing(null);
1229
+ setActiveConversationId(null);
1230
+ setError(null);
1231
+ }, []);
1232
+ return {
1233
+ phase,
1234
+ incoming,
1235
+ outgoing,
1236
+ activeConversationId,
1237
+ error,
1238
+ call,
1239
+ accept,
1240
+ decline,
1241
+ cancel,
1242
+ reset
1243
+ };
1244
+ }
1066
1245
 
1067
1246
  Object.defineProperty(exports, "ApiError", {
1068
1247
  enumerable: true,
@@ -1091,6 +1270,7 @@ exports.sameDay = sameDay;
1091
1270
  exports.sameGroup = sameGroup;
1092
1271
  exports.useAttachmentUpload = useAttachmentUpload;
1093
1272
  exports.useAttachmentUrl = useAttachmentUrl;
1273
+ exports.useCalls = useCalls;
1094
1274
  exports.useConversation = useConversation;
1095
1275
  exports.useConversations = useConversations;
1096
1276
  exports.useMe = useMe;
@@ -1103,5 +1283,6 @@ exports.useRealtimeStatus = useRealtimeStatus;
1103
1283
  exports.useThread = useThread;
1104
1284
  exports.useTyping = useTyping;
1105
1285
  exports.useUser = useUser;
1286
+ exports.useVoiceRoom = useVoiceRoom;
1106
1287
  //# sourceMappingURL=index.cjs.map
1107
1288
  //# sourceMappingURL=index.cjs.map