@amityco/ts-sdk-react-native 6.34.1-b036e5d.0 → 6.35.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.
Files changed (37) hide show
  1. package/.env +26 -26
  2. package/dist/@types/domains/client.d.ts +2 -2
  3. package/dist/@types/domains/client.d.ts.map +1 -1
  4. package/dist/client/api/createClient.d.ts +2 -1
  5. package/dist/client/api/createClient.d.ts.map +1 -1
  6. package/dist/client/api/isConnected.d.ts.map +1 -1
  7. package/dist/client/api/logout.d.ts.map +1 -1
  8. package/dist/client/utils/modifyMqttConnection.d.ts.map +1 -1
  9. package/dist/core/subscription.d.ts.map +1 -1
  10. package/dist/index.cjs.js +130 -19
  11. package/dist/index.esm.js +130 -19
  12. package/dist/index.umd.js +3 -3
  13. package/dist/storyRepository/api/createImageStory.d.ts.map +1 -1
  14. package/dist/storyRepository/api/createVideoStory.d.ts.map +1 -1
  15. package/dist/storyRepository/internalApi/deleteStory.d.ts.map +1 -1
  16. package/dist/storyRepository/observers/getActiveStoriesByTarget.d.ts.map +1 -1
  17. package/dist/storyRepository/observers/getGlobalStoryTargets/GlobalStoryLiveCollectionController.d.ts.map +1 -1
  18. package/dist/storyRepository/utils/createOptimisticTarget.d.ts +5 -0
  19. package/dist/storyRepository/utils/createOptimisticTarget.d.ts.map +1 -0
  20. package/package.json +2 -2
  21. package/src/@types/domains/client.ts +2 -2
  22. package/src/client/api/createClient.ts +10 -2
  23. package/src/client/api/isConnected.ts +4 -1
  24. package/src/client/api/login.ts +1 -1
  25. package/src/client/api/logout.ts +6 -5
  26. package/src/client/utils/modifyMqttConnection.ts +2 -0
  27. package/src/client/utils/setClientToken.ts +1 -1
  28. package/src/core/events.ts +2 -2
  29. package/src/core/subscription.ts +2 -0
  30. package/src/core/transports/ws.ts +1 -1
  31. package/src/storyRepository/api/createImageStory.ts +3 -0
  32. package/src/storyRepository/api/createVideoStory.ts +3 -0
  33. package/src/storyRepository/internalApi/deleteStory.ts +74 -0
  34. package/src/storyRepository/observers/getActiveStoriesByTarget.ts +16 -1
  35. package/src/storyRepository/observers/getGlobalStoryTargets/GlobalStoryLiveCollectionController.ts +14 -2
  36. package/src/storyRepository/utils/StoryComputedValue.ts +2 -2
  37. package/src/storyRepository/utils/createOptimisticTarget.ts +46 -0
@@ -1 +1 @@
1
- {"version":3,"file":"createImageStory.d.ts","sourceRoot":"","sources":["../../../src/storyRepository/api/createImageStory.ts"],"names":[],"mappings":"AASA;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,gBAAgB,eACf,MAAM,aAAa,CAAC,YAAY,CAAC,YACnC,MAAM,aAAa,CAAC,UAAU,CAAC,YAC/B,QAAQ,aACR,MAAM,QAAQ,qBACN,MAAM,gBAAgB,UACjC,MAAM,SAAS,EAAE,KACvB,QAAQ,MAAM,MAAM,CAAC,MAAM,KAAK,GAAG,SAAS,CAAC,CA2E/C,CAAC"}
1
+ {"version":3,"file":"createImageStory.d.ts","sourceRoot":"","sources":["../../../src/storyRepository/api/createImageStory.ts"],"names":[],"mappings":"AAUA;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,gBAAgB,eACf,MAAM,aAAa,CAAC,YAAY,CAAC,YACnC,MAAM,aAAa,CAAC,UAAU,CAAC,YAC/B,QAAQ,aACR,MAAM,QAAQ,qBACN,MAAM,gBAAgB,UACjC,MAAM,SAAS,EAAE,KACvB,QAAQ,MAAM,MAAM,CAAC,MAAM,KAAK,GAAG,SAAS,CAAC,CA6E/C,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"createVideoStory.d.ts","sourceRoot":"","sources":["../../../src/storyRepository/api/createVideoStory.ts"],"names":[],"mappings":"AAUA;;;;;;;;;;;;GAYG;AAEH,eAAO,MAAM,gBAAgB,eACf,MAAM,aAAa,CAAC,YAAY,CAAC,YACnC,MAAM,aAAa,CAAC,UAAU,CAAC,YAC/B,QAAQ,aACR,MAAM,QAAQ,UACjB,MAAM,SAAS,EAAE,KACvB,QAAQ,MAAM,MAAM,CAAC,MAAM,KAAK,GAAG,SAAS,CAAC,CA0E/C,CAAC"}
1
+ {"version":3,"file":"createVideoStory.d.ts","sourceRoot":"","sources":["../../../src/storyRepository/api/createVideoStory.ts"],"names":[],"mappings":"AAWA;;;;;;;;;;;;GAYG;AAEH,eAAO,MAAM,gBAAgB,eACf,MAAM,aAAa,CAAC,YAAY,CAAC,YACnC,MAAM,aAAa,CAAC,UAAU,CAAC,YAC/B,QAAQ,aACR,MAAM,QAAQ,UACjB,MAAM,SAAS,EAAE,KACvB,QAAQ,MAAM,MAAM,CAAC,MAAM,KAAK,GAAG,SAAS,CAAC,CA4E/C,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"deleteStory.d.ts","sourceRoot":"","sources":["../../../src/storyRepository/internalApi/deleteStory.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,WAAW,YACb,MAAM,KAAK,CAAC,SAAS,CAAC,0BAE9B,QAAQ,OAAO,CA2BjB,CAAC"}
1
+ {"version":3,"file":"deleteStory.d.ts","sourceRoot":"","sources":["../../../src/storyRepository/internalApi/deleteStory.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,WAAW,YACb,MAAM,KAAK,CAAC,SAAS,CAAC,0BAE9B,QAAQ,OAAO,CAmGjB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"getActiveStoriesByTarget.d.ts","sourceRoot":"","sources":["../../../src/storyRepository/observers/getActiveStoriesByTarget.ts"],"names":[],"mappings":"AA6BA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,wBAAwB,WAC3B,MAAM,uBAAuB,YAC3B,MAAM,sBAAsB,CAAC,MAAM,KAAK,GAAG,SAAS,CAAC,eA+KhE,CAAC"}
1
+ {"version":3,"file":"getActiveStoriesByTarget.d.ts","sourceRoot":"","sources":["../../../src/storyRepository/observers/getActiveStoriesByTarget.ts"],"names":[],"mappings":"AA8BA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,wBAAwB,WAC3B,MAAM,uBAAuB,YAC3B,MAAM,sBAAsB,CAAC,MAAM,KAAK,GAAG,SAAS,CAAC,eA6LhE,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"GlobalStoryLiveCollectionController.d.ts","sourceRoot":"","sources":["../../../../src/storyRepository/observers/getGlobalStoryTargets/GlobalStoryLiveCollectionController.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,wBAAwB,EAAE,MAAM,gDAAgD,CAAC;AAU1F,OAAO,EAAE,yBAAyB,EAAE,MAAM,6BAA6B,CAAC;AASxE,qBAAa,mCAAoC,SAAQ,wBAAwB,CAC/E,iBAAiB,EACjB,KAAK,CAAC,gBAAgB,EACtB,KAAK,CAAC,WAAW,EACjB,yBAAyB,CAC1B;IACC,OAAO,CAAC,qBAAqB,CAAmC;IAEhE,OAAO,CAAC,KAAK,CAAyB;gBAGpC,KAAK,EAAE,KAAK,CAAC,gBAAgB,EAC7B,QAAQ,EAAE,KAAK,CAAC,sBAAsB,CAAC,KAAK,CAAC,WAAW,CAAC;IA0B3D,SAAS,CAAC,KAAK;IAUf,SAAS,CAAC,YAAY,CAAC,QAAQ,EAAE,KAAK,CAAC,sBAAsB;IAI7D,SAAS,CAAC,kBAAkB,CAAC,EAC3B,QAAQ,EACR,SAAS,EACT,OAAO,GACR,EAAE,KAAK,CAAC,sCAAsC,CAAC,iBAAiB,CAAC;IAIlE,YAAY,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,KAAK,CAAC,0BAA0B;IA6BzE,OAAO,CAAC,WAAW;IAkCnB,iBAAiB;CAalB"}
1
+ {"version":3,"file":"GlobalStoryLiveCollectionController.d.ts","sourceRoot":"","sources":["../../../../src/storyRepository/observers/getGlobalStoryTargets/GlobalStoryLiveCollectionController.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,wBAAwB,EAAE,MAAM,gDAAgD,CAAC;AAU1F,OAAO,EAAE,yBAAyB,EAAE,MAAM,6BAA6B,CAAC;AASxE,qBAAa,mCAAoC,SAAQ,wBAAwB,CAC/E,iBAAiB,EACjB,KAAK,CAAC,gBAAgB,EACtB,KAAK,CAAC,WAAW,EACjB,yBAAyB,CAC1B;IACC,OAAO,CAAC,qBAAqB,CAAmC;IAEhE,OAAO,CAAC,KAAK,CAAyB;gBAGpC,KAAK,EAAE,KAAK,CAAC,gBAAgB,EAC7B,QAAQ,EAAE,KAAK,CAAC,sBAAsB,CAAC,KAAK,CAAC,WAAW,CAAC;IA0B3D,SAAS,CAAC,KAAK;IAUf,SAAS,CAAC,YAAY,CAAC,QAAQ,EAAE,KAAK,CAAC,sBAAsB;IAI7D,SAAS,CAAC,kBAAkB,CAAC,EAC3B,QAAQ,EACR,SAAS,EACT,OAAO,GACR,EAAE,KAAK,CAAC,sCAAsC,CAAC,iBAAiB,CAAC;IAIlE,YAAY,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,KAAK,CAAC,0BAA0B;IAyCzE,OAAO,CAAC,WAAW;IAkCnB,iBAAiB;CAalB"}
@@ -0,0 +1,5 @@
1
+ export declare const createOptimisticTarget: ({ targetId, targetType, }: {
2
+ targetType: string;
3
+ targetId: string;
4
+ }) => Promise<void>;
5
+ //# sourceMappingURL=createOptimisticTarget.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createOptimisticTarget.d.ts","sourceRoot":"","sources":["../../../src/storyRepository/utils/createOptimisticTarget.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,sBAAsB;gBAIrB,MAAM;cACR,MAAM;mBAmCjB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@amityco/ts-sdk-react-native",
3
- "version": "6.34.1-b036e5d.0",
3
+ "version": "6.35.1",
4
4
  "license": "CC-BY-ND-4.0",
5
5
  "author": "amity.co <developers@amity.co> (https://amity.co)",
6
6
  "description": "Amity Social Cloud Typescript SDK",
@@ -80,6 +80,6 @@
80
80
  "ts-jest": "^28.0.3"
81
81
  },
82
82
  "peerDependencies": {
83
- "react-native": "*"
83
+ "react-native": ">=0.70.13"
84
84
  }
85
85
  }
@@ -36,8 +36,8 @@ declare global {
36
36
 
37
37
  log: Logger;
38
38
  http: AxiosInstance;
39
- mqtt: Amity.MqttClient;
40
- ws: SocketIOClient.Socket;
39
+ mqtt?: Amity.MqttClient;
40
+ ws?: SocketIOClient.Socket;
41
41
  emitter: Emitter<Amity.Events>;
42
42
 
43
43
  hasPermission: (permission: string) => Amity.PermissionChecker;
@@ -47,10 +47,12 @@ export const createClient = (
47
47
  debugSession = DEFAULT_DEBUG_SESSION,
48
48
  apiEndpoint,
49
49
  prefixDeviceIdKey,
50
+ rteEnabled = true,
50
51
  }: {
51
52
  debugSession?: string;
52
53
  apiEndpoint?: { http?: string; mqtt?: string };
53
54
  prefixDeviceIdKey?: string;
55
+ rteEnabled?: boolean;
54
56
  } = {},
55
57
  ): Amity.Client => {
56
58
  const log = createLogger(debugSession);
@@ -64,8 +66,14 @@ export const createClient = (
64
66
  const mqttEndpoint = apiEndpoint?.mqtt ?? computeUrl('mqtt', apiRegion);
65
67
 
66
68
  const http = createHttpTransport(httpEndpoint);
67
- const ws = createWebsocketTransport(httpEndpoint);
68
- const mqtt = createMqttTransport(mqttEndpoint);
69
+
70
+ let ws;
71
+ let mqtt;
72
+
73
+ if (rteEnabled) {
74
+ ws = createWebsocketTransport(httpEndpoint);
75
+ mqtt = createMqttTransport(mqttEndpoint);
76
+ }
69
77
 
70
78
  const emitter = createEventEmitter();
71
79
 
@@ -16,9 +16,12 @@ export const isConnected = (): boolean => {
16
16
  const client = getActiveClient();
17
17
  client.log('client/api/isConnected', client);
18
18
 
19
+ // if client is connected to ws, it means client is connected. If ws is undefined, it means ws is not used.
20
+ const isWsConnected = (client.ws && client.ws.connected) || !!client.ws;
21
+
19
22
  return !!(
20
23
  client.userId &&
21
24
  String(client.http.defaults.headers.common?.Authorization)?.length &&
22
- client.ws.connected
25
+ isWsConnected
23
26
  );
24
27
  };
@@ -125,7 +125,7 @@ export const login = async (
125
125
  // wire websocket events to our event emitter
126
126
  proxyWebsocketEvents(client.ws, client.emitter);
127
127
 
128
- client.ws.open();
128
+ client.ws?.open();
129
129
 
130
130
  client.userId = user.userId;
131
131
 
@@ -22,11 +22,11 @@ export const logout = async (): Promise<boolean> => {
22
22
 
23
23
  client.log('client/api/disconnectClient');
24
24
 
25
- if (client.mqtt.connected) {
25
+ if (client.mqtt && client.mqtt.connected) {
26
26
  client.mqtt.disconnect();
27
27
  }
28
28
 
29
- if (client.ws.connected) {
29
+ if (client.ws && client.ws.connected) {
30
30
  client.ws.disconnect();
31
31
  }
32
32
 
@@ -47,8 +47,8 @@ export const logout = async (): Promise<boolean> => {
47
47
 
48
48
  client.emitter.all.clear();
49
49
  // FIXME: it removes listener in ws.ts, it breaks global ban event
50
- client.ws.removeAllListeners();
51
- client.mqtt.removeAllListeners();
50
+ client.ws?.removeAllListeners();
51
+ client.mqtt?.removeAllListeners();
52
52
  client.userId = undefined;
53
53
  client.token = undefined;
54
54
 
@@ -58,7 +58,8 @@ export const logout = async (): Promise<boolean> => {
58
58
  isGlobalBanned: false,
59
59
  isUserDeleted: false,
60
60
  };
61
- client.ws.io.opts.query = { token: '' };
61
+
62
+ if (client.ws) client.ws.io.opts.query = { token: '' };
62
63
 
63
64
  if (typeof document !== 'undefined') {
64
65
  document.cookie = '_ascSession=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;';
@@ -7,6 +7,8 @@ let mqttUserId: string;
7
7
 
8
8
  export async function modifyMqttConnection() {
9
9
  const { mqtt, emitter, token } = getActiveClient();
10
+ if (!mqtt) return;
11
+
10
12
  const accessToken = token?.accessToken ?? '';
11
13
 
12
14
  const user = getActiveUser();
@@ -31,7 +31,7 @@ export const setClientToken = async (params: Parameters<typeof getToken>[0]) =>
31
31
  };
32
32
 
33
33
  // manually setup the token for ws transport
34
- client.ws.io.opts.query = { token: accessToken };
34
+ if (client.ws) client.ws.io.opts.query = { token: accessToken };
35
35
 
36
36
  client.token = { accessToken, issuedAt, expiresAt };
37
37
 
@@ -50,7 +50,7 @@ export const createEventEmitter = () => {
50
50
  */
51
51
  export const proxyWebsocketEvents = (ws: Amity.Client['ws'], emitter: Amity.Client['emitter']) => {
52
52
  WS_EVENTS.forEach(event => {
53
- ws.on(event, (param: Amity.Events[typeof event]) => {
53
+ ws?.on(event, (param: Amity.Events[typeof event]) => {
54
54
  emitter.emit(event, param);
55
55
  });
56
56
  });
@@ -61,7 +61,7 @@ export const proxyMqttEvents = (
61
61
  emitter: Amity.Client['emitter'],
62
62
  ) => {
63
63
  MQTT_EVENTS.forEach(event => {
64
- mqttClient.on(event, (...params: any[]) => {
64
+ mqttClient?.on(event, (...params: any[]) => {
65
65
  emitter.emit(event, params.length === 1 ? params[0] : params);
66
66
  });
67
67
  });
@@ -162,6 +162,8 @@ export function subscribeTopic(
162
162
  callback?: Amity.Listener<ASCError | void>,
163
163
  ): Amity.Unsubscriber {
164
164
  const { mqtt } = getActiveClient();
165
+ if (!mqtt) return () => null;
166
+
165
167
  modifyMqttConnection();
166
168
 
167
169
  return mqtt.subscribe(topic, callback);
@@ -47,7 +47,7 @@ export const synchronousWSCall = async <T>(
47
47
  const { ws } = client;
48
48
 
49
49
  const value = await new Promise<T | undefined>((resolve, reject) => {
50
- ws.emit(event, data, (response: Amity.Response<T>) => {
50
+ ws?.emit(event, data, (response: Amity.Response<T>) => {
51
51
  try {
52
52
  resolve(unwrapPayload(response));
53
53
  } catch (error) {
@@ -6,6 +6,7 @@ import { LinkedObject } from '~/utils/linkedObject';
6
6
  import { pushToCache } from '~/cache/api';
7
7
  import { STORY_KEY_CACHE } from '~/storyRepository/constants';
8
8
  import { createStory } from '../internalApi/createStory';
9
+ import { createOptimisticTarget } from '../utils/createOptimisticTarget';
9
10
 
10
11
  /**
11
12
  * ```js
@@ -79,6 +80,8 @@ export const createImageStory = async (
79
80
  },
80
81
  };
81
82
 
83
+ createOptimisticTarget({ targetId, targetType });
84
+
82
85
  // Fire optimistic event - update fileId
83
86
  createOptimisticEvent({ payload, formData }, optimisticData => {
84
87
  fireEvent('local.story.created', optimisticData);
@@ -7,6 +7,7 @@ import { LinkedObject } from '~/utils/linkedObject';
7
7
  import { pushToCache } from '~/cache/api';
8
8
  import { STORY_KEY_CACHE } from '~/storyRepository/constants';
9
9
  import { createStory } from '../internalApi/createStory';
10
+ import { createOptimisticTarget } from '../utils/createOptimisticTarget';
10
11
 
11
12
  /**
12
13
  * ```js
@@ -56,6 +57,8 @@ export const createVideoStory = async (
56
57
  new Date(date.setFullYear(date.getFullYear() + 1)),
57
58
  );
58
59
 
60
+ createOptimisticTarget({ targetId, targetType });
61
+
59
62
  // Fire optimistic event
60
63
  createOptimisticEvent({ payload, formData, isVideo: true }, optimisticData => {
61
64
  fireEvent('local.story.created', optimisticData);
@@ -1,6 +1,8 @@
1
1
  import { getActiveClient } from '~/client';
2
2
  import { fireEvent } from '~/core/events';
3
3
  import { getStoryCache } from '../utils/getStoryCache';
4
+ import { dropFromCache, pullFromCache, pushToCache, queryCache } from '~/cache/api';
5
+ import { STORY_KEY_CACHE } from '../constants';
4
6
 
5
7
  export const deleteStory = async (
6
8
  storyId: Amity.Story['storyId'],
@@ -24,6 +26,78 @@ export const deleteStory = async (
24
26
  users: [],
25
27
  stories: [{ ...data, isDeleted: true }],
26
28
  });
29
+
30
+ /* ------ Unsynced story case ------ */
31
+ if (data.syncState !== Amity.SyncState.Synced) {
32
+ if (permanent) {
33
+ dropFromCache([STORY_KEY_CACHE.STORY, 'get', storyId]);
34
+ } else {
35
+ pushToCache([STORY_KEY_CACHE.STORY, 'get', storyId], { ...cached.data, isDeleted: true });
36
+ }
37
+
38
+ const unsyncedStoriesCache = queryCache<Amity.InternalStory>([
39
+ STORY_KEY_CACHE.STORY,
40
+ 'get',
41
+ ])?.filter(
42
+ story =>
43
+ story.data.syncState !== Amity.SyncState.Synced &&
44
+ story.data.targetId === data.targetId &&
45
+ story.data.isDeleted !== true,
46
+ );
47
+
48
+ // update localLastStoryExpiresAt to be the last story expires
49
+
50
+ if (unsyncedStoriesCache && unsyncedStoriesCache.length > 0) {
51
+ const lastStoryExpires = unsyncedStoriesCache.reduce((acc, story) => {
52
+ const expireAt = new Date(story.data.expiresAt || 0);
53
+ return expireAt > acc ? expireAt : acc;
54
+ }, new Date(0));
55
+
56
+ pushToCache(
57
+ [STORY_KEY_CACHE.EXPIRE, cached.data.targetId],
58
+ lastStoryExpires.toISOString(),
59
+ );
60
+ } else {
61
+ // if no unsynced stories, remove last story expires since there is no more story
62
+ dropFromCache([STORY_KEY_CACHE.EXPIRE, cached.data.targetId]);
63
+ }
64
+
65
+ return true;
66
+ }
67
+
68
+ /* ------ Synced story case ------ */
69
+ const targetCache = pullFromCache<Amity.RawStoryTarget>([
70
+ STORY_KEY_CACHE.STORY_TARGET,
71
+ 'get',
72
+ data.targetId,
73
+ ])?.data;
74
+
75
+ const syncedStoriesCache = queryCache<Amity.InternalStory>([
76
+ STORY_KEY_CACHE.STORY,
77
+ 'get',
78
+ ])?.filter(
79
+ story =>
80
+ story.data.syncState === Amity.SyncState.Synced &&
81
+ story.data.targetId === data.targetId &&
82
+ story.data.isDeleted !== true,
83
+ );
84
+
85
+ let lastStoryExpiresAt;
86
+
87
+ if (syncedStoriesCache && syncedStoriesCache.length > 0) {
88
+ lastStoryExpiresAt = syncedStoriesCache?.reduce((acc, story) => {
89
+ const expireAt = new Date(story.data.expiresAt || 0);
90
+ return expireAt > acc ? expireAt : acc;
91
+ }, new Date(0));
92
+ }
93
+
94
+ // update lastStoryExpiresAt from lastest synced story
95
+ if (targetCache) {
96
+ pushToCache([STORY_KEY_CACHE.STORY_TARGET, 'get', data.targetId], {
97
+ ...targetCache,
98
+ lastStoryExpiresAt,
99
+ });
100
+ }
27
101
  }
28
102
  }
29
103
 
@@ -1,6 +1,6 @@
1
1
  import { getActiveClient } from '~/client';
2
2
  import { ENABLE_CACHE_MESSAGE } from '~/utils/constants';
3
- import { dropFromCache, pullFromCache, pushToCache } from '~/cache/api';
3
+ import { dropFromCache, pullFromCache, pushToCache, queryCache } from '~/cache/api';
4
4
  import {
5
5
  createQuery,
6
6
  runQuery,
@@ -26,6 +26,7 @@ import { onStoryCreated, onStoryCreatedLocal } from '../events/onStoryCreated';
26
26
  import { onStoryDeleted, onStoryDeletedLocal } from '../events/onStoryDeleted';
27
27
  import { onStoryError } from '../events/onStoryError';
28
28
  import { onStoryLocalDataUpdated } from '../events/onStoryLocalDataUpdated';
29
+ import { STORY_KEY_CACHE } from '../constants';
29
30
 
30
31
  /**
31
32
  * ```js
@@ -162,6 +163,20 @@ export const getActiveStoriesByTarget = (
162
163
  }
163
164
  }
164
165
 
166
+ const unSyncedStories = queryCache<Amity.InternalStory>([STORY_KEY_CACHE.STORY, 'get'])
167
+ ?.filter(
168
+ story =>
169
+ story.data.targetId === params.targetId &&
170
+ story.data.syncState !== Amity.SyncState.Synced,
171
+ )
172
+ .map(story => getResolver('story')(story.data));
173
+
174
+ if (unSyncedStories && unSyncedStories?.length > 0) {
175
+ unSyncedStories.forEach(referenceId => {
176
+ if (!data.data.includes(referenceId)) data.data.push(referenceId);
177
+ });
178
+ }
179
+
165
180
  pushToCache(cacheKey, data.data);
166
181
 
167
182
  responder(data);
@@ -1,6 +1,6 @@
1
1
  import hash from 'object-hash';
2
2
  import { LiveCollectionController } from '~/core/liveCollection/LiveCollectionController';
3
- import { pullFromCache, pushToCache } from '~/cache/api';
3
+ import { pullFromCache, pushToCache, queryCache } from '~/cache/api';
4
4
  import { LinkedObject } from '~/utils/linkedObject';
5
5
  import { STORY_KEY_CACHE } from '~/storyRepository/constants';
6
6
  import { sortByLocalSortingDate } from '~/core/query';
@@ -82,7 +82,17 @@ export class GlobalStoryLiveCollectionController extends LiveCollectionControlle
82
82
  const collection = pullFromCache<Amity.StoryTargetLiveCollectionCache>(this.cacheKey)?.data;
83
83
  if (!collection) return;
84
84
 
85
- let data = collection.data
85
+ const targetIds = collection.data;
86
+
87
+ const cachedTargets = queryCache<Amity.RawStoryTarget>([STORY_KEY_CACHE.STORY_TARGET]);
88
+
89
+ if (cachedTargets && cachedTargets?.length > 0) {
90
+ cachedTargets?.forEach(({ key }) => {
91
+ if (!collection.data.includes(key[2] as string)) targetIds.push(key[2] as string);
92
+ });
93
+ }
94
+
95
+ let data = targetIds
86
96
  .map(
87
97
  targetId =>
88
98
  pullFromCache<Amity.RawStoryTarget>([STORY_KEY_CACHE.STORY_TARGET, 'get', targetId])!,
@@ -93,6 +103,8 @@ export class GlobalStoryLiveCollectionController extends LiveCollectionControlle
93
103
  if (!this.shouldNotify(data) && origin === 'event') return;
94
104
 
95
105
  data = this.applyFilter(data)
106
+ // exclude story targets with invalid stories
107
+ .filter(({ localSortingDate }) => !!localSortingDate)
96
108
  // Remove internal fields
97
109
  .map(
98
110
  ({ localFilter, localLastExpires, localLastSeen, localSortingDate, ...rest }) => rest,
@@ -106,10 +106,10 @@ export class StoryComputedValue {
106
106
  const groupByType = stories.reduce(
107
107
  (acc, story) => {
108
108
  const {
109
- data: { targetId, syncState },
109
+ data: { targetId, syncState, isDeleted },
110
110
  } = story;
111
111
 
112
- if (targetId === this._targetId) {
112
+ if (targetId === this._targetId && !isDeleted) {
113
113
  acc[syncState!] += 1;
114
114
  }
115
115
 
@@ -0,0 +1,46 @@
1
+ import { pullFromCache, pushToCache } from '~/cache/api';
2
+ import { getUser } from '~/userRepository/internalApi/getUser';
3
+ import { getCommunity } from '~/communityRepository/api/getCommunity';
4
+ import { STORY_KEY_CACHE } from '../constants';
5
+
6
+ export const createOptimisticTarget = async ({
7
+ targetId,
8
+ targetType,
9
+ }: {
10
+ targetType: string;
11
+ targetId: string;
12
+ }) => {
13
+ const targetCache = pullFromCache<Amity.RawStoryTarget>([
14
+ STORY_KEY_CACHE.STORY_TARGET,
15
+ 'get',
16
+ targetId,
17
+ ]);
18
+
19
+ if (!targetCache) {
20
+ let optimisticTarget = {
21
+ targetId,
22
+ targetType,
23
+ };
24
+
25
+ if (targetType === 'community') {
26
+ const community = await getCommunity(targetId);
27
+ optimisticTarget = {
28
+ ...optimisticTarget,
29
+ targetPublicId: community.data.communityId,
30
+ targetUpdatedAt: community.data.updatedAt ?? new Date().toISOString(),
31
+ } as Amity.RawStoryTarget;
32
+ }
33
+
34
+ if (targetType === 'user') {
35
+ const user = await getUser(targetId);
36
+
37
+ optimisticTarget = {
38
+ ...optimisticTarget,
39
+ targetPublicId: user.data.userPublicId,
40
+ targetUpdatedAt: user.data.updatedAt ?? new Date().toISOString(),
41
+ } as Amity.RawStoryTarget;
42
+ }
43
+
44
+ pushToCache([STORY_KEY_CACHE.STORY_TARGET, 'get', targetId], optimisticTarget);
45
+ }
46
+ };