@pedi/chika-sdk 1.0.7 → 1.0.9

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.js CHANGED
@@ -445,8 +445,7 @@ async function createChatSession(config, channelId, profile, callbacks, networkM
445
445
  body: JSON.stringify({
446
446
  participant_id: profile.id,
447
447
  message_id: messageId
448
- }),
449
- signal: sessionAbort.signal
448
+ })
450
449
  });
451
450
  if (!res.ok) {
452
451
  await throwHttpError(res);
@@ -454,7 +453,7 @@ async function createChatSession(config, channelId, profile, callbacks, networkM
454
453
  };
455
454
  if (retryConfig) {
456
455
  try {
457
- await withRetry(readFn, MARK_READ_RETRY_CONFIG, sessionAbort.signal);
456
+ await withRetry(readFn, MARK_READ_RETRY_CONFIG);
458
457
  } catch (err) {
459
458
  if (err instanceof HttpError) {
460
459
  callbacks.onError(err);
@@ -770,6 +769,7 @@ var MessageQueue = class {
770
769
  entry.status = "failed";
771
770
  entry.error = err instanceof Error ? err : new Error(String(err));
772
771
  entry.retryCount++;
772
+ entry.reject(entry.error);
773
773
  this.config.onStatusChange?.();
774
774
  this.persist();
775
775
  }
@@ -826,7 +826,9 @@ function useChat({ config, channelId, profile, onMessage }) {
826
826
  onMessageRef.current = onMessage;
827
827
  const startingRef = (0, import_react.useRef)(false);
828
828
  const pendingOptimisticIds = (0, import_react.useRef)(/* @__PURE__ */ new Set());
829
+ const markReadTimerRef = (0, import_react.useRef)(null);
829
830
  const [monitor, setMonitor] = (0, import_react.useState)(null);
831
+ const [monitorReady, setMonitorReady] = (0, import_react.useState)(false);
830
832
  const monitorRef = (0, import_react.useRef)(null);
831
833
  monitorRef.current = monitor;
832
834
  const queueRef = (0, import_react.useRef)(null);
@@ -839,19 +841,50 @@ function useChat({ config, channelId, profile, onMessage }) {
839
841
  (0, import_react.useEffect)(() => {
840
842
  if (!resilienceEnabled) {
841
843
  setMonitor(null);
844
+ setMonitorReady(true);
842
845
  return;
843
846
  }
844
847
  if (injectedMonitor) {
845
848
  setMonitor(injectedMonitor);
849
+ setMonitorReady(true);
846
850
  return;
847
851
  }
848
- const m = createNetworkMonitor();
849
- setMonitor(m);
850
- return () => {
851
- m.dispose();
852
+ try {
853
+ const m = createNetworkMonitor();
854
+ setMonitor(m);
855
+ setMonitorReady(true);
856
+ return () => {
857
+ m.dispose();
858
+ setMonitor(null);
859
+ };
860
+ } catch {
852
861
  setMonitor(null);
853
- };
862
+ setMonitorReady(true);
863
+ }
854
864
  }, [resilienceEnabled, injectedMonitor]);
865
+ function scheduleMarkAsRead(messageId) {
866
+ if (markReadTimerRef.current) clearTimeout(markReadTimerRef.current);
867
+ markReadTimerRef.current = setTimeout(() => {
868
+ markReadTimerRef.current = null;
869
+ sessionRef.current?.markAsRead(messageId).catch(() => {
870
+ });
871
+ }, 500);
872
+ }
873
+ function flushMarkReadAndDisconnect() {
874
+ if (markReadTimerRef.current) {
875
+ clearTimeout(markReadTimerRef.current);
876
+ markReadTimerRef.current = null;
877
+ }
878
+ if (sessionRef.current) {
879
+ const lastMsg = messagesRef.current[messagesRef.current.length - 1];
880
+ if (lastMsg) {
881
+ sessionRef.current.markAsRead(lastMsg.id).catch(() => {
882
+ });
883
+ }
884
+ }
885
+ sessionRef.current?.disconnect();
886
+ sessionRef.current = null;
887
+ }
855
888
  const callbacks = {
856
889
  onMessage: (message) => {
857
890
  if (disposedRef.current) return;
@@ -878,6 +911,9 @@ function useChat({ config, channelId, profile, onMessage }) {
878
911
  queueRef.current?.cancel(matchedOptimisticId);
879
912
  }
880
913
  }
914
+ if (message.sender_id !== profileRef.current.id) {
915
+ scheduleMarkAsRead(message.id);
916
+ }
881
917
  onMessageRef.current?.(message);
882
918
  },
883
919
  onStatusChange: (nextStatus) => {
@@ -928,6 +964,10 @@ function useChat({ config, channelId, profile, onMessage }) {
928
964
  } else {
929
965
  setMessages(session.initialMessages);
930
966
  }
967
+ const lastInitMsg = session.initialMessages[session.initialMessages.length - 1];
968
+ if (lastInitMsg) {
969
+ scheduleMarkAsRead(lastInitMsg.id);
970
+ }
931
971
  } catch (err) {
932
972
  if (disposedRef.current) return;
933
973
  if (err instanceof ChannelClosedError) {
@@ -943,25 +983,17 @@ function useChat({ config, channelId, profile, onMessage }) {
943
983
  }
944
984
  (0, import_react.useEffect)(() => {
945
985
  disposedRef.current = false;
946
- if (resilienceEnabled && !monitor) return;
986
+ if (!monitorReady) return;
947
987
  startSession();
948
988
  return () => {
949
989
  disposedRef.current = true;
950
- if (statusRef.current === "connected" && sessionRef.current) {
951
- const lastMsg = messagesRef.current[messagesRef.current.length - 1];
952
- if (lastMsg) {
953
- sessionRef.current.markAsRead(lastMsg.id).catch(() => {
954
- });
955
- }
956
- }
990
+ flushMarkReadAndDisconnect();
957
991
  if (backgroundTimerRef.current) {
958
992
  clearTimeout(backgroundTimerRef.current);
959
993
  backgroundTimerRef.current = null;
960
994
  }
961
- sessionRef.current?.disconnect();
962
- sessionRef.current = null;
963
995
  };
964
- }, [channelId, monitor]);
996
+ }, [channelId, monitorReady]);
965
997
  (0, import_react.useEffect)(() => {
966
998
  if (!queueEnabled || !monitor || !retryConfig) return;
967
999
  let entry = queueRegistry.get(channelId);
@@ -1009,8 +1041,7 @@ function useChat({ config, channelId, profile, onMessage }) {
1009
1041
  }, [channelId, resilienceEnabled, monitor]);
1010
1042
  (0, import_react.useEffect)(() => {
1011
1043
  function teardownSession() {
1012
- sessionRef.current?.disconnect();
1013
- sessionRef.current = null;
1044
+ flushMarkReadAndDisconnect();
1014
1045
  setStatus("disconnected");
1015
1046
  }
1016
1047
  const subscription = import_react_native.AppState.addEventListener("change", (nextAppState) => {
@@ -1137,8 +1168,7 @@ function useChat({ config, channelId, profile, onMessage }) {
1137
1168
  []
1138
1169
  );
1139
1170
  const disconnect = (0, import_react.useCallback)(() => {
1140
- sessionRef.current?.disconnect();
1141
- sessionRef.current = null;
1171
+ flushMarkReadAndDisconnect();
1142
1172
  setStatus("disconnected");
1143
1173
  }, []);
1144
1174
  return {
@@ -1170,24 +1200,33 @@ function useUnread(options) {
1170
1200
  const appStateRef = (0, import_react2.useRef)(import_react_native2.AppState.currentState);
1171
1201
  const backgroundTimerRef = (0, import_react2.useRef)(null);
1172
1202
  const backgroundGraceMs = config.backgroundGraceMs ?? (import_react_native2.Platform.OS === "android" ? DEFAULT_BACKGROUND_GRACE_MS2 : 0);
1173
- const [monitor, setMonitor] = (0, import_react2.useState)(null);
1203
+ const [monitorReady, setMonitorReady] = (0, import_react2.useState)(false);
1204
+ const monitorRef = (0, import_react2.useRef)(null);
1174
1205
  const resilienceEnabled = config.resilience !== false;
1175
1206
  const injectedMonitor = typeof config.resilience === "object" ? config.resilience.networkMonitor : void 0;
1176
1207
  (0, import_react2.useEffect)(() => {
1177
1208
  if (!resilienceEnabled) {
1178
- setMonitor(null);
1209
+ monitorRef.current = null;
1210
+ setMonitorReady(true);
1179
1211
  return;
1180
1212
  }
1181
1213
  if (injectedMonitor) {
1182
- setMonitor(injectedMonitor);
1214
+ monitorRef.current = injectedMonitor;
1215
+ setMonitorReady(true);
1183
1216
  return;
1184
1217
  }
1185
- const m = createNetworkMonitor();
1186
- setMonitor(m);
1187
- return () => {
1188
- m.dispose();
1189
- setMonitor(null);
1190
- };
1218
+ try {
1219
+ const m = createNetworkMonitor();
1220
+ monitorRef.current = m;
1221
+ setMonitorReady(true);
1222
+ return () => {
1223
+ m.dispose();
1224
+ monitorRef.current = null;
1225
+ };
1226
+ } catch {
1227
+ monitorRef.current = null;
1228
+ setMonitorReady(true);
1229
+ }
1191
1230
  }, [resilienceEnabled, injectedMonitor]);
1192
1231
  const connect = (0, import_react2.useCallback)(() => {
1193
1232
  connRef.current?.close();
@@ -1201,7 +1240,7 @@ function useUnread(options) {
1201
1240
  headers: customHeaders,
1202
1241
  reconnectDelayMs: configRef.current.reconnectDelayMs,
1203
1242
  customEvents: UNREAD_CUSTOM_EVENTS,
1204
- networkMonitor: monitor ?? void 0
1243
+ networkMonitor: monitorRef.current ?? void 0
1205
1244
  },
1206
1245
  {
1207
1246
  onOpen: () => {
@@ -1233,7 +1272,7 @@ function useUnread(options) {
1233
1272
  }
1234
1273
  }
1235
1274
  );
1236
- }, [channelId, participantId, monitor]);
1275
+ }, [channelId, participantId]);
1237
1276
  const disconnect = (0, import_react2.useCallback)(() => {
1238
1277
  connRef.current?.close();
1239
1278
  connRef.current = null;
@@ -1246,7 +1285,7 @@ function useUnread(options) {
1246
1285
  disconnect();
1247
1286
  return;
1248
1287
  }
1249
- if (resilienceEnabled && !monitor) return;
1288
+ if (!monitorReady) return;
1250
1289
  connect();
1251
1290
  return () => {
1252
1291
  disconnect();
@@ -1255,7 +1294,7 @@ function useUnread(options) {
1255
1294
  backgroundTimerRef.current = null;
1256
1295
  }
1257
1296
  };
1258
- }, [channelId, participantId, enabled, connect, disconnect]);
1297
+ }, [channelId, participantId, enabled, monitorReady, connect, disconnect]);
1259
1298
  (0, import_react2.useEffect)(() => {
1260
1299
  if (!enabled) return;
1261
1300
  const subscription = import_react_native2.AppState.addEventListener("change", (nextAppState) => {