@poolse/react 2.12.1 → 2.13.1

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
@@ -1069,22 +1069,28 @@ function useCallRoom(conversationId, opts) {
1069
1069
  const [participants, setParticipants] = react.useState([]);
1070
1070
  const [cameraEnabled, setCamera] = react.useState(false);
1071
1071
  const [micEnabled, setMic] = react.useState(false);
1072
+ const [facingMode, setFacing] = react.useState(opts.facing ?? "user");
1073
+ const [alone, setAlone] = react.useState(false);
1072
1074
  const [error, setError] = react.useState(null);
1073
1075
  const [sfuAvailable, setSfuAvailable] = react.useState(null);
1074
1076
  const optsRef = react.useRef(opts);
1077
+ optsRef.current = opts;
1075
1078
  const joined = react.useRef(false);
1076
1079
  const room = react.useMemo(() => {
1077
1080
  if (!conversationId) return null;
1078
1081
  return poolse.call(conversationId, {
1079
1082
  livekit: optsRef.current.livekit,
1080
1083
  ...optsRef.current.video !== void 0 ? { video: optsRef.current.video } : {},
1081
- ...optsRef.current.muted !== void 0 ? { muted: optsRef.current.muted } : {}
1084
+ ...optsRef.current.muted !== void 0 ? { muted: optsRef.current.muted } : {},
1085
+ ...optsRef.current.facing !== void 0 ? { facing: optsRef.current.facing } : {},
1086
+ ...optsRef.current.aloneGraceMs !== void 0 ? { aloneGraceMs: optsRef.current.aloneGraceMs } : {}
1082
1087
  });
1083
1088
  }, [poolse, conversationId]);
1084
1089
  const sync = react.useCallback((target) => {
1085
1090
  if (!target) return;
1086
1091
  setCamera(target.isCameraEnabled());
1087
1092
  setMic(target.isMicrophoneEnabled());
1093
+ setFacing(target.getFacingMode());
1088
1094
  }, []);
1089
1095
  react.useEffect(() => {
1090
1096
  if (!room) {
@@ -1094,15 +1100,18 @@ function useCallRoom(conversationId, opts) {
1094
1100
  }
1095
1101
  setStatus(room.getStatus());
1096
1102
  setParticipants(room.getParticipants());
1103
+ setAlone(false);
1097
1104
  const offStatus = room.onStatus(setStatus);
1098
1105
  const offRoster = room.onParticipants((next) => {
1099
1106
  setParticipants(next);
1100
1107
  sync(room);
1101
1108
  });
1109
+ const offAlone = room.onAlone(() => setAlone(true));
1102
1110
  const offError = room.onError(setError);
1103
1111
  return () => {
1104
1112
  offStatus();
1105
1113
  offRoster();
1114
+ offAlone();
1106
1115
  offError();
1107
1116
  if (joined.current) {
1108
1117
  joined.current = false;
@@ -1154,21 +1163,50 @@ function useCallRoom(conversationId, opts) {
1154
1163
  if (!room) return;
1155
1164
  await setMicrophoneEnabled(!room.isMicrophoneEnabled());
1156
1165
  }, [room, setMicrophoneEnabled]);
1166
+ const switchCamera = react.useCallback(async () => {
1167
+ if (!room) return;
1168
+ await room.switchCamera();
1169
+ setFacing(room.getFacingMode());
1170
+ }, [room]);
1157
1171
  return {
1158
1172
  status,
1159
1173
  participants,
1160
1174
  cameraEnabled,
1161
1175
  micEnabled,
1176
+ facingMode,
1177
+ alone,
1162
1178
  error,
1163
1179
  sfuAvailable,
1164
1180
  join,
1165
1181
  leave,
1166
1182
  setCameraEnabled,
1167
1183
  toggleCamera,
1184
+ switchCamera,
1168
1185
  setMicrophoneEnabled,
1169
1186
  toggleMic
1170
1187
  };
1171
1188
  }
1189
+ function useAloneWatch({ active, others, graceMs }) {
1190
+ const [alone, setAlone] = react.useState(false);
1191
+ const seenPeer = react.useRef(false);
1192
+ react.useEffect(() => {
1193
+ if (!active) {
1194
+ seenPeer.current = false;
1195
+ setAlone(false);
1196
+ return;
1197
+ }
1198
+ if (others > 0) {
1199
+ seenPeer.current = true;
1200
+ return;
1201
+ }
1202
+ if (graceMs <= 0 || !seenPeer.current) return;
1203
+ const timer = setTimeout(() => setAlone(true), graceMs);
1204
+ return () => clearTimeout(timer);
1205
+ }, [active, others, graceMs]);
1206
+ return alone;
1207
+ }
1208
+
1209
+ // src/use-voice-room.ts
1172
1210
  function useVoiceRoom(conversationId, opts = {}) {
1173
1211
  const poolse = usePoolse();
1174
1212
  const [status, setStatus] = react.useState("idle");
@@ -1218,7 +1256,12 @@ function useVoiceRoom(conversationId, opts = {}) {
1218
1256
  if (!room) return;
1219
1257
  setMuted(room.toggleMute());
1220
1258
  }, [room]);
1221
- return { status, participants, muted, error, join, leave, toggleMute };
1259
+ const alone = useAloneWatch({
1260
+ active: status === "connected",
1261
+ others: Math.max(0, participants.length - 1),
1262
+ graceMs: optsRef.current.aloneGraceMs ?? 1500
1263
+ });
1264
+ return { status, participants, muted, alone, error, join, leave, toggleMute };
1222
1265
  }
1223
1266
  function useCalls(userId, opts = {}) {
1224
1267
  const ringTimeoutMs = opts.ringTimeoutMs ?? 45e3;