@amityco/ts-sdk 0.0.1-beta.21 → 0.0.1-beta.24

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 (53) hide show
  1. package/dist/@types/domains/channel.d.ts +1 -2
  2. package/dist/@types/domains/channel.d.ts.map +1 -1
  3. package/dist/@types/domains/content.d.ts +5 -2
  4. package/dist/@types/domains/content.d.ts.map +1 -1
  5. package/dist/@types/domains/message.d.ts +2 -2
  6. package/dist/@types/domains/message.d.ts.map +1 -1
  7. package/dist/@types/domains/reaction.d.ts +1 -1
  8. package/dist/@types/domains/reaction.d.ts.map +1 -1
  9. package/dist/channel/api/queryChannelMembers.d.ts +2 -1
  10. package/dist/channel/api/queryChannelMembers.d.ts.map +1 -1
  11. package/dist/channel/api/queryChannels.d.ts +1 -0
  12. package/dist/channel/api/queryChannels.d.ts.map +1 -1
  13. package/dist/channel/api/updateChannel.d.ts +1 -1
  14. package/dist/channel/api/updateChannel.d.ts.map +1 -1
  15. package/dist/client/api/connectClient.d.ts +3 -1
  16. package/dist/client/api/connectClient.d.ts.map +1 -1
  17. package/dist/comment/api/queryComments.d.ts +1 -0
  18. package/dist/comment/api/queryComments.d.ts.map +1 -1
  19. package/dist/core/model/identifyModel.d.ts +1 -0
  20. package/dist/core/model/identifyModel.d.ts.map +1 -1
  21. package/dist/core/query/query.d.ts.map +1 -1
  22. package/dist/index.cjs.js +204 -68
  23. package/dist/index.esm.js +203 -68
  24. package/dist/index.umd.js +5 -5
  25. package/dist/message/api/createMessage.d.ts +2 -2
  26. package/dist/message/api/createMessage.d.ts.map +1 -1
  27. package/dist/message/api/updateMessage.d.ts +2 -2
  28. package/dist/message/api/updateMessage.d.ts.map +1 -1
  29. package/dist/message/events/onMessageUpdated.d.ts.map +1 -1
  30. package/dist/reaction/events/onReactionAdded.d.ts.map +1 -1
  31. package/dist/reaction/utils/index.d.ts +1 -0
  32. package/dist/reaction/utils/index.d.ts.map +1 -1
  33. package/dist/reaction/utils/prepareMessagePayloadForCache.d.ts +3 -0
  34. package/dist/reaction/utils/prepareMessagePayloadForCache.d.ts.map +1 -0
  35. package/package.json +1 -1
  36. package/src/@types/domains/channel.ts +1 -2
  37. package/src/@types/domains/content.ts +7 -1
  38. package/src/@types/domains/message.ts +2 -1
  39. package/src/@types/domains/reaction.ts +1 -1
  40. package/src/channel/api/queryChannelMembers.ts +4 -4
  41. package/src/channel/api/queryChannels.ts +1 -0
  42. package/src/channel/api/updateChannel.ts +1 -1
  43. package/src/client/api/connectClient.ts +12 -7
  44. package/src/comment/api/queryComments.ts +6 -3
  45. package/src/core/model/identifyModel.ts +18 -0
  46. package/src/core/query/paging.ts +3 -3
  47. package/src/core/query/query.ts +19 -1
  48. package/src/message/api/createMessage.ts +24 -8
  49. package/src/message/api/updateMessage.ts +2 -2
  50. package/src/message/events/onMessageUpdated.ts +9 -1
  51. package/src/reaction/events/onReactionAdded.ts +4 -0
  52. package/src/reaction/utils/index.ts +1 -0
  53. package/src/reaction/utils/prepareMessagePayloadForCache.ts +40 -0
@@ -16,7 +16,7 @@
16
16
  * @async
17
17
  */
18
18
  export declare const createMessage: {
19
- <T extends Amity.MessageContentType>(bundle: Pick<Amity.Message<T>, "type" | "channelId" | "parentId" | "data" | "metadata" | "mentionees">): Promise<Amity.Cached<Amity.Message>>;
19
+ <T extends Amity.MessageContentType>(bundle: Pick<Amity.Message<T>, "type" | "channelId" | "parentId" | "data" | "tags" | "metadata" | "mentionees">): Promise<Amity.Cached<Amity.Message>>;
20
20
  /**
21
21
  * ```js
22
22
  * import { createMessage } from '@amityco/ts-sdk'
@@ -33,6 +33,6 @@ export declare const createMessage: {
33
33
  *
34
34
  * @category Message API
35
35
  */
36
- optimistically(bundle: Pick<Amity.Message, 'channelId' | 'parentId' | 'type' | 'data' | 'metadata' | 'mentionees'>): Amity.Cached<Amity.Message> | undefined;
36
+ optimistically(bundle: Pick<Amity.Message, 'channelId' | 'parentId' | 'type' | 'data' | 'tags' | 'metadata' | 'mentionees'>): Amity.Cached<Amity.Message> | undefined;
37
37
  };
38
38
  //# sourceMappingURL=createMessage.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"createMessage.d.ts","sourceRoot":"","sources":["../../../src/message/api/createMessage.ts"],"names":[],"mappings":"AAMA;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,aAAa;kJAKvB,QAAQ,MAAM,MAAM,CAAC,MAAM,OAAO,CAAC,CAAC;IAkBvC;;;;;;;;;;;;;;;OAeG;2BAEO,KACN,MAAM,OAAO,EACb,WAAW,GAAG,UAAU,GAAG,MAAM,GAAG,MAAM,GAAG,UAAU,GAAG,YAAY,CACvE,GACA,MAAM,MAAM,CAAC,MAAM,OAAO,CAAC,GAAG,SAAS;CAvBzC,CAAC"}
1
+ {"version":3,"file":"createMessage.d.ts","sourceRoot":"","sources":["../../../src/message/api/createMessage.ts"],"names":[],"mappings":"AAOA;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,aAAa;2JAKvB,QAAQ,MAAM,MAAM,CAAC,MAAM,OAAO,CAAC,CAAC;IAmBvC;;;;;;;;;;;;;;;OAeG;2BAEO,KACN,MAAM,OAAO,EACb,WAAW,GAAG,UAAU,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,UAAU,GAAG,YAAY,CAChF,GACA,MAAM,MAAM,CAAC,MAAM,OAAO,CAAC,GAAG,SAAS;CAvBzC,CAAC"}
@@ -16,7 +16,7 @@
16
16
  * @async
17
17
  */
18
18
  export declare const updateMessage: {
19
- (messageId: Amity.Message['messageId'], patch: Patch<Amity.Message, 'data' | 'metadata' | 'mentionees'>): Promise<Amity.Cached<Amity.Message>>;
19
+ (messageId: Amity.Message['messageId'], patch: Patch<Amity.Message, 'data' | 'tags' | 'metadata' | 'mentionees'>): Promise<Amity.Cached<Amity.Message>>;
20
20
  /**
21
21
  * ```js
22
22
  * import { updateMessage } from '@amityco/ts-sdk'
@@ -33,6 +33,6 @@ export declare const updateMessage: {
33
33
  *
34
34
  * @category Message API
35
35
  */
36
- optimistically(messageId: Amity.Message['messageId'], patch: Patch<Amity.Message, 'data' | 'metadata' | 'mentionees'>): Amity.Cached<Amity.Message> | undefined;
36
+ optimistically(messageId: Amity.Message['messageId'], patch: Patch<Amity.Message, 'data' | 'tags' | 'metadata' | 'mentionees'>): Amity.Cached<Amity.Message> | undefined;
37
37
  };
38
38
  //# sourceMappingURL=updateMessage.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"updateMessage.d.ts","sourceRoot":"","sources":["../../../src/message/api/updateMessage.ts"],"names":[],"mappings":"AAMA;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,aAAa;gBACb,MAAM,OAAO,CAAC,WAAW,CAAC,SAC9B,MAAM,MAAM,OAAO,EAAE,MAAM,GAAG,UAAU,GAAG,YAAY,CAAC,GAC9D,QAAQ,MAAM,MAAM,CAAC,MAAM,OAAO,CAAC,CAAC;IAoBvC;;;;;;;;;;;;;;;OAeG;8BAEU,MAAM,OAAO,CAAC,WAAW,CAAC,SAC9B,MAAM,MAAM,OAAO,EAAE,MAAM,GAAG,UAAU,GAAG,YAAY,CAAC,GAC9D,MAAM,MAAM,CAAC,MAAM,OAAO,CAAC,GAAG,SAAS;CArBzC,CAAC"}
1
+ {"version":3,"file":"updateMessage.d.ts","sourceRoot":"","sources":["../../../src/message/api/updateMessage.ts"],"names":[],"mappings":"AAMA;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,aAAa;gBACb,MAAM,OAAO,CAAC,WAAW,CAAC,SAC9B,MAAM,MAAM,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,UAAU,GAAG,YAAY,CAAC,GACvE,QAAQ,MAAM,MAAM,CAAC,MAAM,OAAO,CAAC,CAAC;IAoBvC;;;;;;;;;;;;;;;OAeG;8BAEU,MAAM,OAAO,CAAC,WAAW,CAAC,SAC9B,MAAM,MAAM,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,UAAU,GAAG,YAAY,CAAC,GACvE,MAAM,MAAM,CAAC,MAAM,OAAO,CAAC,GAAG,SAAS;CArBzC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"onMessageUpdated.d.ts","sourceRoot":"","sources":["../../../src/message/events/onMessageUpdated.ts"],"names":[],"mappings":"AAKA;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,gBAAgB,aAAc,MAAM,QAAQ,CAAC,MAAM,OAAO,CAAC,KAAG,MAAM,YAShF,CAAC"}
1
+ {"version":3,"file":"onMessageUpdated.d.ts","sourceRoot":"","sources":["../../../src/message/events/onMessageUpdated.ts"],"names":[],"mappings":"AAMA;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,gBAAgB,aAAc,MAAM,QAAQ,CAAC,MAAM,OAAO,CAAC,KAAG,MAAM,YAgBhF,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"onReactionAdded.d.ts","sourceRoot":"","sources":["../../../src/reaction/events/onReactionAdded.ts"],"names":[],"mappings":"AAQA;;;;;;;;;;;;;;;;KAgBK;AACL,eAAO,MAAM,eAAe,kBACX,MAAM,aAAa,eACrB,MAAM,QAAQ,CAAC,aAAa,CAAC,0FAEzC,MAAM,YAsCR,CAAC"}
1
+ {"version":3,"file":"onReactionAdded.d.ts","sourceRoot":"","sources":["../../../src/reaction/events/onReactionAdded.ts"],"names":[],"mappings":"AAQA;;;;;;;;;;;;;;;;KAgBK;AACL,eAAO,MAAM,eAAe,kBACX,MAAM,aAAa,eACrB,MAAM,QAAQ,CAAC,aAAa,CAAC,0FAEzC,MAAM,YA0CR,CAAC"}
@@ -1,4 +1,5 @@
1
1
  export * from './dispatchReactable';
2
2
  export * from './fetchReference';
3
3
  export * from './preparePayloadForCache';
4
+ export * from './prepareMessagePayloadForCache';
4
5
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/reaction/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAC;AACpC,cAAc,kBAAkB,CAAC;AACjC,cAAc,0BAA0B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/reaction/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAC;AACpC,cAAc,kBAAkB,CAAC;AACjC,cAAc,0BAA0B,CAAC;AACzC,cAAc,iCAAiC,CAAC"}
@@ -0,0 +1,3 @@
1
+ /** @hidden */
2
+ export declare const prepareMessagePayloadForCache: (payload: Amity.Message) => void;
3
+ //# sourceMappingURL=prepareMessagePayloadForCache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prepareMessagePayloadForCache.d.ts","sourceRoot":"","sources":["../../../src/reaction/utils/prepareMessagePayloadForCache.ts"],"names":[],"mappings":"AAGA,cAAc;AAKd,eAAO,MAAM,6BAA6B,YAAa,MAAM,OAAO,SA+BnE,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@amityco/ts-sdk",
3
- "version": "0.0.1-beta.21",
3
+ "version": "0.0.1-beta.24",
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",
@@ -2,13 +2,12 @@ export {};
2
2
 
3
3
  declare global {
4
4
  namespace Amity {
5
- type ChannelType = 'standard' | 'live' | 'conversation' | 'broadcast';
5
+ type ChannelType = 'broadcast' | 'conversation' | 'community' | 'live';
6
6
 
7
7
  type Channel<T extends ChannelType = any> = {
8
8
  channelId: string;
9
9
  displayName?: string;
10
10
  avatarFileId?: File<'image'>['fileId'];
11
- description?: string;
12
11
  type: T;
13
12
 
14
13
  isDistinct?: boolean;
@@ -2,7 +2,7 @@ export {};
2
2
 
3
3
  declare global {
4
4
  namespace Amity {
5
- type ContentType = 'text' | 'image' | 'file' | 'video' | 'json' | string;
5
+ type ContentType = 'text' | 'image' | 'file' | 'video' | 'poll' | 'json' | string;
6
6
 
7
7
  type ContentDataText = {
8
8
  text: string;
@@ -20,6 +20,10 @@ declare global {
20
20
  videoId: Amity.File<'file'>['fileId'];
21
21
  };
22
22
 
23
+ type ContentDataPoll = {
24
+ pollId: Amity.Poll['pollId'];
25
+ };
26
+
23
27
  type ContentData<T extends ContentType> = T extends 'text'
24
28
  ? ContentDataText
25
29
  : T extends 'file'
@@ -28,6 +32,8 @@ declare global {
28
32
  ? ContentDataImage
29
33
  : T extends 'video'
30
34
  ? ContentDataVideo
35
+ : T extends 'poll'
36
+ ? ContentDataPoll
31
37
  : T extends 'json'
32
38
  ? Record<string, unknown>
33
39
  : T extends string
@@ -10,7 +10,7 @@ declare global {
10
10
  | 'video'
11
11
  | 'audio'
12
12
  ? { fileId: string }
13
- : never;
13
+ : unknown;
14
14
 
15
15
  type Message<T extends Amity.MessageContentType = any> = {
16
16
  messageId: string;
@@ -29,6 +29,7 @@ declare global {
29
29
  Amity.Metadata &
30
30
  Amity.Timestamps &
31
31
  Amity.SoftDelete &
32
+ Amity.Taggable &
32
33
  Amity.Reactable &
33
34
  Amity.Mentionable<'user' | 'channel'>;
34
35
  }
@@ -18,7 +18,7 @@ declare global {
18
18
  myReactions?: string[];
19
19
 
20
20
  latestReaction?: Amity.Reaction & {
21
- eventName: 'added' | 'removed';
21
+ eventName: 'add' | 'remove';
22
22
  };
23
23
  };
24
24
 
@@ -19,22 +19,22 @@ import { ingestInCache } from '~/cache/api/ingestInCache';
19
19
  * */
20
20
  export const queryChannelMembers = async (query: {
21
21
  channelId: string;
22
- membership?: 'all' | 'muted' | 'banned' | 'member&banned';
22
+ memberships?: ('muted' | 'banned' | 'member')[];
23
23
  roles?: string[];
24
24
  sortBy?: 'firstCreated' | 'lastCreated';
25
+ search?: string;
25
26
  page?: Amity.Page;
26
27
  }): Promise<Amity.Cached<Amity.Paged<Amity.Membership<'channel'>>>> => {
27
28
  const client = getActiveClient();
28
29
  client.log('channel/queryChannelMembers', query);
29
30
 
30
- const { page, channelId, membership, ...params } = query ?? {};
31
+ const { page, channelId, ...params } = query ?? {};
31
32
 
32
33
  const { data } = await client.http.get<Amity.ChannelMembershipPayload & Amity.Pagination>(
33
- `/api/v3/channels/${encodeURIComponent(channelId)}/users`,
34
+ `/api/v4/channels/${encodeURIComponent(channelId)}/users`,
34
35
  {
35
36
  params: {
36
37
  ...params,
37
- filter: membership,
38
38
  options: {
39
39
  token: toToken(page, 'skiplimit'),
40
40
  },
@@ -25,6 +25,7 @@ export const queryChannels = async (query?: {
25
25
  membership?: 'all' | 'member' | 'notMember';
26
26
  sortBy?: 'displayName' | 'firstCreated' | 'lastCreated';
27
27
  types?: Amity.ChannelType;
28
+ isDeleted?: Amity.Channel['isDeleted'];
28
29
  tags?: Amity.Taggable['tags'];
29
30
  excludeTags?: Amity.Taggable['tags'];
30
31
  page?: Amity.Page;
@@ -19,7 +19,7 @@ import { ingestInCache } from '~/cache/api/ingestInCache';
19
19
  */
20
20
  export const updateChannel = async (
21
21
  channelId: Amity.Channel['channelId'],
22
- patch: Patch<Amity.Channel, 'displayName' | 'description' | 'avatarFileId' | 'metadata'>,
22
+ patch: Patch<Amity.Channel, 'displayName' | 'avatarFileId' | 'tags' | 'metadata'>,
23
23
  ): Promise<Amity.Cached<Amity.Channel>> => {
24
24
  const client = getActiveClient();
25
25
  client.log('channel/updateChannel', channelId, patch);
@@ -32,12 +32,15 @@ import { onUserDeleted } from '~/user/events/onUserDeleted';
32
32
  * @category Client API
33
33
  * @async
34
34
  */
35
- export const connectClient = async (params: {
36
- userId: Amity.User['userId'];
37
- displayName?: Amity.User['displayName'];
38
- authToken?: string;
39
- deviceId?: Amity.Device['deviceId'];
40
- }): Promise<boolean> => {
35
+ export const connectClient = async (
36
+ params: {
37
+ userId: Amity.User['userId'];
38
+ displayName?: Amity.User['displayName'];
39
+ authToken?: string;
40
+ deviceId?: Amity.Device['deviceId'];
41
+ },
42
+ config?: { disableRTE: boolean },
43
+ ): Promise<boolean> => {
41
44
  const client = getActiveClient();
42
45
  client.log('client/api/connectClient', { apiKey: client.apiKey, ...params });
43
46
 
@@ -70,7 +73,9 @@ export const connectClient = async (params: {
70
73
 
71
74
  setActiveUser(users[0]);
72
75
 
73
- subscribeTopic(getNetworkTopic());
76
+ if (config?.disableRTE !== true) {
77
+ subscribeTopic(getNetworkTopic());
78
+ }
74
79
 
75
80
  const subscriptions = [
76
81
  onClientBanned(() => {
@@ -22,6 +22,7 @@ import { getResolver } from '~/core/model';
22
22
  export const queryComments = async (query: {
23
23
  referenceType: Amity.Comment['referenceType'];
24
24
  referenceId: Amity.Comment['referenceId'];
25
+ sortBy?: 'lastCreated' | 'firstCreated' | 'lastUpdated' | 'firstUpdated';
25
26
  parentId?: Amity.Comment['commentId'] | null;
26
27
  hasFlag?: boolean;
27
28
  isDeleted?: Amity.Comment['isDeleted'];
@@ -32,6 +33,10 @@ export const queryComments = async (query: {
32
33
 
33
34
  const { page = { limit: 10 }, ...params } = query;
34
35
 
36
+ const options = {
37
+ type: params.sortBy ? 'pagination' : undefined,
38
+ token: toToken(page, params.sortBy ? 'skiplimit' : 'afterbefore'),
39
+ };
35
40
  // const filterByParentId = query.parentId !== undefined
36
41
 
37
42
  // API-FIX: parameters should be querystring. (1)
@@ -43,9 +48,7 @@ export const queryComments = async (query: {
43
48
  params: {
44
49
  ...params,
45
50
  // filterByParentId, API-FIX: backend does not support this boolean LOL. what the hell seriously.
46
- options: {
47
- token: toToken(page, 'afterbefore'),
48
- },
51
+ options,
49
52
  },
50
53
  },
51
54
  );
@@ -57,3 +57,21 @@ export const identifyModel = (model: Record<string, unknown>) => {
57
57
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
58
58
  return criterias.find(([_, keys]) => hasKeys(model, keys))?.[0];
59
59
  };
60
+
61
+ /*
62
+ * Identify the modal key for a model
63
+ * Used to get args for optimistic updates
64
+ * Example: createMessage: get messageId on optimistic message creation
65
+ *
66
+ * @param model to be recognized
67
+ * @returns model key array if one if found or undefined
68
+ */
69
+ export const identifyModelKey = (model: Record<string, unknown>): string | undefined => {
70
+ const modalKey = identifyModel(model);
71
+
72
+ if (!modalKey) {
73
+ return undefined;
74
+ }
75
+
76
+ return CRITERIAS[modalKey]?.[0];
77
+ };
@@ -80,17 +80,17 @@ export const toToken = (
80
80
  "before" or "after" value. if that would change,
81
81
  we'd need to move toward a more simple: `!paging.before`
82
82
  */
83
- if (!Number.isNaN(paging?.before!)) {
83
+ if (!Number.isNaN(Number(paging?.before!))) {
84
84
  payload = {
85
85
  before: paging.before,
86
86
  last: paging.limit,
87
87
  };
88
- } else if (!Number.isNaN(paging?.after!)) {
88
+ } else if (!Number.isNaN(Number(paging?.after!))) {
89
89
  payload = {
90
90
  after: paging.after,
91
91
  first: paging.limit,
92
92
  };
93
- } else if (!Number.isNaN(paging?.limit!)) {
93
+ } else if (!Number.isNaN(Number(paging?.limit!))) {
94
94
  payload = {
95
95
  last: paging.limit,
96
96
  };
@@ -1,5 +1,6 @@
1
1
  /* eslint-disable no-use-before-define */
2
2
  import { isPaged } from './paging';
3
+ import { identifyModelKey } from '~/core/model';
3
4
 
4
5
  /**
5
6
  * Type guard to check and cast that a given async function is has the ".locally" property
@@ -201,7 +202,24 @@ export const runQuery = <Args extends any[], Returned extends any>(
201
202
  );
202
203
  }
203
204
 
204
- func(...args)
205
+ let optimisticArgs = args;
206
+ /* get args for optimistic method calls
207
+ *
208
+ * On optimistic updates, the modal key for the update needs to be passed to
209
+ * the server so as to avoid duplicate modal creation
210
+ *
211
+ * ex: on creating a new message pass the modalKey is messageId, pass this
212
+ * id onto the server so that a duplicate with seperate messageId is not
213
+ * created.
214
+ */
215
+ if (isMutator(func)) {
216
+ // @ts-ignore
217
+ const modelKey = local && local.data && identifyModelKey(local.data);
218
+ // @ts-ignore
219
+ optimisticArgs = modelKey ? [{ ...args[0], [modelKey]: local.data[modelKey] }] : args;
220
+ }
221
+
222
+ func(...optimisticArgs)
205
223
  .then(fresh => {
206
224
  // @ts-ignore i know.
207
225
  // isLocal(local) && syncInCache(local, fresh)
@@ -3,6 +3,7 @@ import { getActiveClient } from '~/client/api';
3
3
  import { upsertInCache, pullFromCache, pushToCache } from '~/cache/api';
4
4
  import { ingestInCache } from '~/cache/api/ingestInCache';
5
5
  import { fireEvent } from '~/core/events';
6
+ import { uuid } from '~/core/uuid';
6
7
 
7
8
  /**
8
9
  * ```js
@@ -24,10 +25,11 @@ import { fireEvent } from '~/core/events';
24
25
  export const createMessage = async <T extends Amity.MessageContentType>(
25
26
  bundle: Pick<
26
27
  Amity.Message<T>,
27
- 'channelId' | 'parentId' | 'type' | 'data' | 'metadata' | 'mentionees'
28
+ 'channelId' | 'parentId' | 'type' | 'data' | 'tags' | 'metadata' | 'mentionees'
28
29
  >,
29
30
  ): Promise<Amity.Cached<Amity.Message>> => {
30
31
  const client = getActiveClient();
32
+
31
33
  client.log('user/createMessage', bundle);
32
34
 
33
35
  const { data } = await client.http.post<Amity.MessagePayload>('/api/v3/messages', bundle);
@@ -63,27 +65,41 @@ export const createMessage = async <T extends Amity.MessageContentType>(
63
65
  createMessage.optimistically = (
64
66
  bundle: Pick<
65
67
  Amity.Message,
66
- 'channelId' | 'parentId' | 'type' | 'data' | 'metadata' | 'mentionees'
68
+ 'channelId' | 'parentId' | 'type' | 'data' | 'tags' | 'metadata' | 'mentionees'
67
69
  >,
68
70
  ): Amity.Cached<Amity.Message> | undefined => {
69
71
  const client = getActiveClient();
70
- client.log('user/createMessage.locally', bundle);
71
72
 
72
73
  if (!client.cache) return;
73
74
 
74
- const channel = pullFromCache<Amity.Channel>(['channel', 'get', bundle.channelId]);
75
+ /*
76
+ * when creating messages optimistically a messageId needs to be added by the
77
+ * client, created a new variable so as to allow backward compatibility of API
78
+ *
79
+ * Updated to handle client requirement to add messageId while uploading
80
+ * message with image. Temporary!
81
+ */
82
+ const bundleWithMessageId = { messageId: uuid(), ...bundle };
83
+
84
+ // only log if cache is enabled
85
+ client.log('user/createMessage.locally', bundleWithMessageId);
75
86
 
76
- upsertInCache(['channel', 'get', bundle.channelId], {
87
+ const channel = pullFromCache<Amity.Channel>(['channel', 'get', bundleWithMessageId.channelId]);
88
+
89
+ upsertInCache(['channel', 'get', bundleWithMessageId.channelId], {
77
90
  ...channel?.data,
78
91
  messageCount: (channel?.data.messageCount ?? 0) + 1,
79
92
  });
80
93
 
94
+ // as reused to update created and updated time, which should be the same
95
+ const createdTime = new Date().toISOString();
96
+
81
97
  const message = {
82
- messageId: Math.random().toString(16),
83
98
  userId: client.userId,
84
99
  channelSegment: (channel?.data.messageCount ?? 0) + 1,
85
- createdAt: new Date().toISOString(),
86
- ...bundle,
100
+ createdAt: createdTime,
101
+ updatedAt: createdTime,
102
+ ...bundleWithMessageId,
87
103
  } as Amity.Message;
88
104
 
89
105
  pushToCache(['message', 'get', message.messageId], message, { cachedAt: -1 });
@@ -23,7 +23,7 @@ import { fireEvent } from '~/core/events';
23
23
  */
24
24
  export const updateMessage = async (
25
25
  messageId: Amity.Message['messageId'],
26
- patch: Patch<Amity.Message, 'data' | 'metadata' | 'mentionees'>,
26
+ patch: Patch<Amity.Message, 'data' | 'tags' | 'metadata' | 'mentionees'>,
27
27
  ): Promise<Amity.Cached<Amity.Message>> => {
28
28
  const client = getActiveClient();
29
29
  client.log('user/updateMessage', patch);
@@ -62,7 +62,7 @@ export const updateMessage = async (
62
62
  */
63
63
  updateMessage.optimistically = (
64
64
  messageId: Amity.Message['messageId'],
65
- patch: Patch<Amity.Message, 'data' | 'metadata' | 'mentionees'>,
65
+ patch: Patch<Amity.Message, 'data' | 'tags' | 'metadata' | 'mentionees'>,
66
66
  ): Amity.Cached<Amity.Message> | undefined => {
67
67
  const client = getActiveClient();
68
68
  client.log('user/updateMessage', patch);
@@ -2,6 +2,7 @@ import { getActiveClient } from '~/client/api';
2
2
  import { createEventSubscriber } from '~/core/events';
3
3
 
4
4
  import { ingestInCache } from '~/cache/api/ingestInCache';
5
+ import { prepareMessagePayloadForCache } from '~/reaction/utils';
5
6
 
6
7
  /**
7
8
  * ```js
@@ -23,7 +24,14 @@ export const onMessageUpdated = (callback: Amity.Listener<Amity.Message>): Amity
23
24
 
24
25
  const filter = (payload: Amity.MessagePayload) => {
25
26
  ingestInCache(payload);
26
- callback(payload.messages[0]);
27
+ const message = payload.messages[0];
28
+
29
+ // if payload does not have myReactions
30
+ if (!message?.myReactions) {
31
+ prepareMessagePayloadForCache(message);
32
+ }
33
+
34
+ callback(message);
27
35
  };
28
36
 
29
37
  return createEventSubscriber(client, 'message/onMessageUpdated', 'v3.message.didUpdate', filter);
@@ -34,6 +34,10 @@ export const onReactionAdded = (
34
34
  }
35
35
  };
36
36
 
37
+ /*
38
+ * Important: Want to point out that reference type will never be 'message'
39
+ * for onReactionAdded
40
+ */
37
41
  if (referenceType === 'message') {
38
42
  const client = getActiveClient();
39
43
 
@@ -1,3 +1,4 @@
1
1
  export * from './dispatchReactable';
2
2
  export * from './fetchReference';
3
3
  export * from './preparePayloadForCache';
4
+ export * from './prepareMessagePayloadForCache';
@@ -0,0 +1,40 @@
1
+ import { pullFromCache } from '~/cache/api';
2
+ import { getActiveClient } from '~/client/api';
3
+
4
+ /** @hidden */
5
+ /*
6
+ * @param message payload from http request without myReactions
7
+ * add myReactions to http response if the event was a reaction event
8
+ */
9
+ export const prepareMessagePayloadForCache = (payload: Amity.Message) => {
10
+ const client = getActiveClient();
11
+
12
+ const cached = pullFromCache<Amity.Message>(['message', 'get', payload.messageId]);
13
+ // '[]' in cases where the new reaction is the first one
14
+ const myReactions = cached?.data.myReactions || [];
15
+
16
+ // add myReactions to the payload
17
+ Object.assign(payload, { myReactions });
18
+
19
+ // check if there are any updates to the reactions
20
+ const latestReaction = payload?.latestReaction;
21
+ const isLatestReactionMine = latestReaction && latestReaction.userId === client.userId;
22
+
23
+ if (!isLatestReactionMine) {
24
+ return;
25
+ }
26
+
27
+ // new reaction added
28
+ if (latestReaction.eventName === 'add' && !myReactions.includes(latestReaction.reactionName)) {
29
+ Object.assign(payload, {
30
+ myReactions: [...myReactions, latestReaction.reactionName],
31
+ });
32
+ }
33
+
34
+ // existing reaction removed
35
+ if (latestReaction.eventName === 'remove' && myReactions.includes(latestReaction.reactionName)) {
36
+ Object.assign(payload, {
37
+ myReactions: myReactions.filter(x => x !== latestReaction.reactionName),
38
+ });
39
+ }
40
+ };