@amityco/ts-sdk-react-native 7.23.1-c573a00.0 → 7.24.1-c018455.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.esm.js CHANGED
@@ -300,8 +300,8 @@ var NotificationRolesFilterTypeEnum;
300
300
 
301
301
  function getVersion() {
302
302
  try {
303
- // the string ''v7.23.0-esm'' should be replaced by actual value by @rollup/plugin-replace
304
- return 'v7.23.0-esm';
303
+ // the string ''v7.24.0-esm'' should be replaced by actual value by @rollup/plugin-replace
304
+ return 'v7.24.0-esm';
305
305
  }
306
306
  catch (error) {
307
307
  return '__dev__';
@@ -29564,562 +29564,571 @@ var index$r = /*#__PURE__*/Object.freeze({
29564
29564
  getMyFollowInfo: getMyFollowInfo
29565
29565
  });
29566
29566
 
29567
- class StoryComputedValue {
29568
- constructor(targetId, lastStoryExpiresAt, lastStorySeenExpiresAt) {
29569
- this._syncingStoriesCount = 0;
29570
- this._errorStoriesCount = 0;
29571
- this._targetId = targetId;
29572
- this._lastStoryExpiresAt = lastStoryExpiresAt;
29573
- this._lastStorySeenExpiresAt = lastStorySeenExpiresAt;
29574
- this.cacheStoryExpireTime = pullFromCache([
29575
- "story-expire" /* STORY_KEY_CACHE.EXPIRE */,
29576
- this._targetId,
29577
- ]);
29578
- this.cacheStoreSeenTime = pullFromCache([
29579
- "story-last-seen" /* STORY_KEY_CACHE.LAST_SEEN */,
29580
- this._targetId,
29581
- ]);
29582
- this.getTotalStoryByStatus();
29583
- }
29584
- get lastStoryExpiresAt() {
29585
- return this._lastStoryExpiresAt ? new Date(this._lastStoryExpiresAt).getTime() : 0;
29586
- }
29587
- get lastStorySeenExpiresAt() {
29588
- return this._lastStorySeenExpiresAt ? new Date(this._lastStorySeenExpiresAt).getTime() : 0;
29589
- }
29590
- get localLastStoryExpires() {
29591
- var _a, _b;
29592
- return ((_a = this.cacheStoryExpireTime) === null || _a === void 0 ? void 0 : _a.data)
29593
- ? new Date((_b = this.cacheStoryExpireTime) === null || _b === void 0 ? void 0 : _b.data).getTime()
29594
- : 0;
29595
- }
29596
- get localLastStorySeenExpiresAt() {
29597
- var _a, _b;
29598
- return ((_a = this.cacheStoreSeenTime) === null || _a === void 0 ? void 0 : _a.data) ? new Date((_b = this.cacheStoreSeenTime) === null || _b === void 0 ? void 0 : _b.data).getTime() : 0;
29599
- }
29600
- get isContainUnSyncedStory() {
29601
- const currentSyncingState = pullFromCache([
29602
- "story-sync-state" /* STORY_KEY_CACHE.SYNC_STATE */,
29603
- this._targetId,
29604
- ]);
29605
- if (!(currentSyncingState === null || currentSyncingState === void 0 ? void 0 : currentSyncingState.data))
29606
- return false;
29607
- return ["syncing" /* Amity.SyncState.Syncing */, "error" /* Amity.SyncState.Error */].includes(currentSyncingState.data);
29608
- }
29609
- getLocalLastSortingDate() {
29610
- if (this.isContainUnSyncedStory) {
29611
- return this.localLastStoryExpires;
29612
- }
29613
- return this.lastStoryExpiresAt;
29614
- }
29615
- getHasUnseenFlag() {
29616
- const now = new Date().getTime();
29617
- const highestSeen = Math.max(this.lastStorySeenExpiresAt, this.localLastStorySeenExpiresAt);
29618
- pullFromCache([
29619
- "story-sync-state" /* STORY_KEY_CACHE.SYNC_STATE */,
29620
- this._targetId,
29567
+ /*
29568
+ * verifies membership status
29569
+ */
29570
+ function isMember(membership) {
29571
+ return membership !== 'none';
29572
+ }
29573
+ /*
29574
+ * checks if currently logged in user is part of the community
29575
+ */
29576
+ function isCurrentUserPartOfCommunity(c, m) {
29577
+ const { userId } = getActiveUser();
29578
+ return c.communityId === m.communityId && m.userId === userId;
29579
+ }
29580
+ /*
29581
+ * For mqtt events server will not send user specific data as it's broadcasted
29582
+ * to multiple users and it also does not include communityUser
29583
+ *
29584
+ * Client SDK needs to check for the existing isJoined field in cache data before calculating.
29585
+ * Althought this can be calculated, it's not scalable.
29586
+ */
29587
+ function updateMembershipStatus(communities, communityUsers) {
29588
+ return communities.map(c => {
29589
+ const cachedCommunity = pullFromCache([
29590
+ 'community',
29591
+ 'get',
29592
+ c.communityId,
29621
29593
  ]);
29622
- if (this.isContainUnSyncedStory) {
29623
- return this.localLastStoryExpires > now && this.localLastStoryExpires > highestSeen;
29624
- }
29625
- return this.lastStoryExpiresAt > now && this.lastStoryExpiresAt > highestSeen;
29626
- }
29627
- getTotalStoryByStatus() {
29628
- const stories = queryCache(["story" /* STORY_KEY_CACHE.STORY */, 'get']);
29629
- if (!stories) {
29630
- this._errorStoriesCount = 0;
29631
- this._syncingStoriesCount = 0;
29632
- return;
29594
+ if ((cachedCommunity === null || cachedCommunity === void 0 ? void 0 : cachedCommunity.data) && (cachedCommunity === null || cachedCommunity === void 0 ? void 0 : cachedCommunity.data.hasOwnProperty('isJoined'))) {
29595
+ return Object.assign(Object.assign({}, cachedCommunity.data), c);
29633
29596
  }
29634
- const groupByType = stories.reduce((acc, story) => {
29635
- const { data: { targetId, syncState, isDeleted }, } = story;
29636
- if (targetId === this._targetId && !isDeleted) {
29637
- acc[syncState] += 1;
29638
- }
29639
- return acc;
29640
- }, {
29641
- syncing: 0,
29642
- error: 0,
29643
- synced: 0,
29597
+ const isJoined = c.isJoined !== undefined
29598
+ ? c.isJoined
29599
+ : communityUsers.some(m => isCurrentUserPartOfCommunity(c, m) && isMember(m.communityMembership));
29600
+ return Object.assign(Object.assign({}, c), { isJoined });
29601
+ });
29602
+ }
29603
+
29604
+ const getMatchPostSetting = (value) => {
29605
+ var _a;
29606
+ return (_a = Object.keys(CommunityPostSettingMaps).find(key => value.needApprovalOnPostCreation ===
29607
+ CommunityPostSettingMaps[key].needApprovalOnPostCreation &&
29608
+ value.onlyAdminCanPost === CommunityPostSettingMaps[key].onlyAdminCanPost)) !== null && _a !== void 0 ? _a : DefaultCommunityPostSetting;
29609
+ };
29610
+ function addPostSetting({ communities }) {
29611
+ return communities.map((_a) => {
29612
+ var { needApprovalOnPostCreation, onlyAdminCanPost } = _a, restCommunityPayload = __rest(_a, ["needApprovalOnPostCreation", "onlyAdminCanPost"]);
29613
+ return (Object.assign({ postSetting: getMatchPostSetting({
29614
+ needApprovalOnPostCreation,
29615
+ onlyAdminCanPost,
29616
+ }) }, restCommunityPayload));
29617
+ });
29618
+ }
29619
+ const prepareCommunityPayload = (rawPayload) => {
29620
+ const communitiesWithPostSetting = addPostSetting({ communities: rawPayload.communities });
29621
+ // Convert users to internal format
29622
+ const internalUsers = rawPayload.users.map(convertRawUserToInternalUser);
29623
+ // map users with community
29624
+ const mappedCommunityUsers = rawPayload.communityUsers.map(communityUser => {
29625
+ const user = internalUsers.find(user => user.userId === communityUser.userId);
29626
+ return Object.assign(Object.assign({}, communityUser), { user });
29627
+ });
29628
+ const communityWithMembershipStatus = updateMembershipStatus(communitiesWithPostSetting, mappedCommunityUsers);
29629
+ return Object.assign(Object.assign({}, rawPayload), { users: rawPayload.users.map(convertRawUserToInternalUser), communities: communityWithMembershipStatus, communityUsers: mappedCommunityUsers });
29630
+ };
29631
+ const prepareCommunityJoinRequestPayload = (rawPayload) => {
29632
+ const mappedJoinRequests = rawPayload.joinRequests.map(joinRequest => {
29633
+ return Object.assign(Object.assign({}, joinRequest), { joinRequestId: joinRequest._id });
29634
+ });
29635
+ const users = rawPayload.users.map(convertRawUserToInternalUser);
29636
+ return Object.assign(Object.assign({}, rawPayload), { joinRequests: mappedJoinRequests, users });
29637
+ };
29638
+ const prepareCommunityMembershipPayload = (rawPayload) => {
29639
+ const communitiesWithPostSetting = addPostSetting({ communities: rawPayload.communities });
29640
+ // map users with community
29641
+ const mappedCommunityUsers = rawPayload.communityUsers.map(communityUser => {
29642
+ const user = rawPayload.users.find(user => user.userId === communityUser.userId);
29643
+ return Object.assign(Object.assign({}, communityUser), { user });
29644
+ });
29645
+ const communityWithMembershipStatus = updateMembershipStatus(communitiesWithPostSetting, mappedCommunityUsers);
29646
+ return Object.assign(Object.assign({}, rawPayload), { communities: communityWithMembershipStatus, communityUsers: mappedCommunityUsers });
29647
+ };
29648
+ const prepareCommunityRequest = (params) => {
29649
+ const { postSetting = undefined, storySetting } = params, restParam = __rest(params, ["postSetting", "storySetting"]);
29650
+ return Object.assign(Object.assign(Object.assign({}, restParam), (postSetting ? CommunityPostSettingMaps[postSetting] : undefined)), {
29651
+ // Convert story setting to the actual value. (Allow by default)
29652
+ allowCommentInStory: typeof (storySetting === null || storySetting === void 0 ? void 0 : storySetting.enableComment) === 'boolean' ? storySetting.enableComment : true });
29653
+ };
29654
+ const prepareSemanticSearchCommunityPayload = (_a) => {
29655
+ var communityPayload = __rest(_a, ["searchResult"]);
29656
+ const processedCommunityPayload = prepareCommunityPayload(communityPayload);
29657
+ return Object.assign({}, processedCommunityPayload);
29658
+ };
29659
+
29660
+ /* begin_public_function
29661
+ id: joinRequest.approve
29662
+ */
29663
+ /**
29664
+ * ```js
29665
+ * import { joinRequest } from '@amityco/ts-sdk-react-native'
29666
+ * const isAccepted = await joinRequest.approve()
29667
+ * ```
29668
+ *
29669
+ * Accepts a {@link Amity.JoinRequest} object
29670
+ *
29671
+ * @param joinRequest the {@link Amity.JoinRequest} to accept
29672
+ * @returns A success boolean if the {@link Amity.JoinRequest} was accepted
29673
+ *
29674
+ * @category Join Request API
29675
+ * @async
29676
+ */
29677
+ const approveJoinRequest = async (joinRequest) => {
29678
+ var _a;
29679
+ const client = getActiveClient();
29680
+ client.log('joinRequest/approveJoinRequest', joinRequest.joinRequestId);
29681
+ const { data } = await client.http.post(`/api/v4/communities/${joinRequest.targetId}/join/approve`, {
29682
+ userId: joinRequest.requestorInternalId,
29683
+ });
29684
+ const joinRequestCache = (_a = pullFromCache([
29685
+ 'joinRequest',
29686
+ 'get',
29687
+ joinRequest.joinRequestId,
29688
+ ])) === null || _a === void 0 ? void 0 : _a.data;
29689
+ if (joinRequestCache) {
29690
+ upsertInCache(['joinRequest', 'get', joinRequest.joinRequestId], {
29691
+ status: "approved" /* JoinRequestStatusEnum.Approved */,
29644
29692
  });
29645
- this._errorStoriesCount = groupByType.error;
29646
- this._syncingStoriesCount = groupByType.syncing;
29647
- }
29648
- get syncingStoriesCount() {
29649
- return this._syncingStoriesCount;
29650
- }
29651
- get failedStoriesCount() {
29652
- return this._errorStoriesCount;
29693
+ fireEvent('local.joinRequest.updated', [joinRequestCache]);
29653
29694
  }
29654
- }
29695
+ return data.success;
29696
+ };
29697
+ /* end_public_function */
29655
29698
 
29656
- const storyTargetLinkedObject = (storyTarget) => {
29657
- const { targetType, targetId, lastStoryExpiresAt, lastStorySeenExpiresAt, targetUpdatedAt, localFilter, } = storyTarget;
29658
- const computedValue = new StoryComputedValue(targetId, lastStoryExpiresAt, lastStorySeenExpiresAt);
29659
- return {
29660
- targetType,
29661
- targetId,
29662
- lastStoryExpiresAt,
29663
- updatedAt: targetUpdatedAt,
29664
- // Additional data
29665
- hasUnseen: computedValue.getHasUnseenFlag(),
29666
- syncingStoriesCount: computedValue.syncingStoriesCount,
29667
- failedStoriesCount: computedValue.failedStoriesCount,
29668
- localFilter,
29669
- localLastExpires: computedValue.localLastStoryExpires,
29670
- localLastSeen: computedValue.localLastStorySeenExpiresAt,
29671
- localSortingDate: computedValue.getLocalLastSortingDate(),
29672
- };
29699
+ /* begin_public_function
29700
+ id: joinRequest.cancel
29701
+ */
29702
+ /**
29703
+ * ```js
29704
+ * import { joinRequest } from '@amityco/ts-sdk-react-native'
29705
+ * const isCanceled = await joinRequest.cancel()
29706
+ * ```
29707
+ *
29708
+ * Cancels a {@link Amity.JoinRequest} object
29709
+ *
29710
+ * @param joinRequest the {@link Amity.JoinRequest} to cancel
29711
+ * @returns A success boolean if the {@link Amity.JoinRequest} was canceled
29712
+ *
29713
+ * @category Join Request API
29714
+ * @async
29715
+ */
29716
+ const cancelJoinRequest = async (joinRequest) => {
29717
+ var _a;
29718
+ const client = getActiveClient();
29719
+ client.log('joinRequest/cancelJoinRequest', joinRequest.joinRequestId);
29720
+ const { data } = await client.http.delete(`/api/v4/communities/${joinRequest.targetId}/join`);
29721
+ const joinRequestCache = (_a = pullFromCache([
29722
+ 'joinRequest',
29723
+ 'get',
29724
+ joinRequest.joinRequestId,
29725
+ ])) === null || _a === void 0 ? void 0 : _a.data;
29726
+ if (joinRequestCache) {
29727
+ upsertInCache(['joinRequest', 'get', joinRequest.joinRequestId], {
29728
+ status: "cancelled" /* JoinRequestStatusEnum.Cancelled */,
29729
+ });
29730
+ fireEvent('local.joinRequest.deleted', [joinRequestCache]);
29731
+ }
29732
+ return data.success;
29673
29733
  };
29734
+ /* end_public_function */
29674
29735
 
29675
- const storyLinkedObject = (story) => {
29676
- const analyticsEngineInstance = AnalyticsEngine$1.getInstance();
29677
- const storyTargetCache = pullFromCache([
29678
- "storyTarget" /* STORY_KEY_CACHE.STORY_TARGET */,
29736
+ /* begin_public_function
29737
+ id: joinRequest.reject
29738
+ */
29739
+ /**
29740
+ * ```js
29741
+ * import { joinRequest } from '@amityco/ts-sdk-react-native'
29742
+ * const isRejected = await joinRequest.reject()
29743
+ * ```
29744
+ *
29745
+ * Rejects a {@link Amity.JoinRequest} object
29746
+ *
29747
+ * @param joinRequest the {@link Amity.JoinRequest} to reject
29748
+ * @returns A success boolean if the {@link Amity.JoinRequest} was rejected
29749
+ *
29750
+ * @category Join Request API
29751
+ * @async
29752
+ */
29753
+ const rejectJoinRequest = async (joinRequest) => {
29754
+ var _a;
29755
+ const client = getActiveClient();
29756
+ client.log('joinRequest/rejectJoinRequest', joinRequest.joinRequestId);
29757
+ const { data } = await client.http.post(`/api/v4/communities/${joinRequest.targetId}/join/reject`, {
29758
+ userId: joinRequest.requestorInternalId,
29759
+ });
29760
+ const joinRequestCache = (_a = pullFromCache([
29761
+ 'joinRequest',
29679
29762
  'get',
29680
- story.targetId,
29681
- ]);
29682
- const communityCacheData = pullFromCache(['community', 'get', story.targetId]);
29683
- return Object.assign(Object.assign({}, story), { analytics: {
29684
- markAsSeen: () => {
29685
- if (!story.expiresAt)
29686
- return;
29687
- if (story.syncState !== "synced" /* Amity.SyncState.Synced */)
29688
- return;
29689
- analyticsEngineInstance.markStoryAsViewed(story);
29690
- },
29691
- markLinkAsClicked: () => {
29692
- if (!story.expiresAt)
29693
- return;
29694
- if (story.syncState !== "synced" /* Amity.SyncState.Synced */)
29695
- return;
29696
- analyticsEngineInstance.markStoryAsClicked(story);
29697
- },
29698
- }, get videoData() {
29699
- var _a, _b;
29700
- const cache = pullFromCache([
29701
- 'file',
29702
- 'get',
29703
- (_b = (_a = story.data) === null || _a === void 0 ? void 0 : _a.videoFileId) === null || _b === void 0 ? void 0 : _b.original,
29704
- ]);
29705
- if (!cache)
29706
- return undefined;
29707
- const { data } = cache;
29708
- return data || undefined;
29709
- },
29710
- get imageData() {
29711
- var _a, _b;
29712
- if (!((_a = story.data) === null || _a === void 0 ? void 0 : _a.fileId))
29713
- return undefined;
29714
- const cache = pullFromCache(['file', 'get', (_b = story.data) === null || _b === void 0 ? void 0 : _b.fileId]);
29715
- if (!cache)
29716
- return undefined;
29717
- const { data } = cache;
29718
- if (!data)
29719
- return undefined;
29720
- return Object.assign(Object.assign({}, data), { fileUrl: `${data.fileUrl}?size=full` });
29721
- },
29722
- get community() {
29723
- if (story.targetType !== 'community')
29724
- return undefined;
29725
- if (!communityCacheData)
29726
- return undefined;
29727
- return (communityCacheData === null || communityCacheData === void 0 ? void 0 : communityCacheData.data) || undefined;
29728
- },
29729
- get communityCategories() {
29730
- if (story.targetType !== 'community')
29731
- return undefined;
29732
- if (!communityCacheData)
29733
- return undefined;
29734
- const { data: { categoryIds }, } = communityCacheData;
29735
- if (categoryIds.length === 0)
29763
+ joinRequest.joinRequestId,
29764
+ ])) === null || _a === void 0 ? void 0 : _a.data;
29765
+ if (joinRequestCache) {
29766
+ upsertInCache(['joinRequest', 'get', joinRequest.joinRequestId], {
29767
+ status: "rejected" /* JoinRequestStatusEnum.Rejected */,
29768
+ });
29769
+ fireEvent('local.joinRequest.updated', [joinRequestCache]);
29770
+ }
29771
+ return data.success;
29772
+ };
29773
+ /* end_public_function */
29774
+
29775
+ const joinRequestLinkedObject = (joinRequest) => {
29776
+ return Object.assign(Object.assign({}, joinRequest), { get user() {
29777
+ var _a;
29778
+ const user = (_a = pullFromCache([
29779
+ 'user',
29780
+ 'get',
29781
+ joinRequest.requestorPublicId,
29782
+ ])) === null || _a === void 0 ? void 0 : _a.data;
29783
+ if (!user)
29736
29784
  return undefined;
29737
- return categoryIds
29738
- .map(categoryId => {
29739
- const categoryCacheData = pullFromCache(['category', 'get', categoryId]);
29740
- return (categoryCacheData === null || categoryCacheData === void 0 ? void 0 : categoryCacheData.data) || undefined;
29741
- })
29742
- .filter(category => category !== undefined);
29743
- },
29744
- get creator() {
29745
- const cacheData = pullFromCache(['user', 'get', story.creatorPublicId]);
29746
- if (!(cacheData === null || cacheData === void 0 ? void 0 : cacheData.data))
29747
- return;
29748
- return userLinkedObject(cacheData.data);
29749
- },
29750
- get storyTarget() {
29751
- if (!(storyTargetCache === null || storyTargetCache === void 0 ? void 0 : storyTargetCache.data))
29752
- return;
29753
- return storyTargetLinkedObject(storyTargetCache.data);
29754
- },
29755
- get isSeen() {
29756
- const cacheData = pullFromCache(["story-last-seen" /* STORY_KEY_CACHE.LAST_SEEN */, story.targetId]);
29757
- if (!(storyTargetCache === null || storyTargetCache === void 0 ? void 0 : storyTargetCache.data))
29758
- return false;
29759
- const localLastSeen = (cacheData === null || cacheData === void 0 ? void 0 : cacheData.data) ? new Date(cacheData.data).getTime() : 0;
29760
- const serverLastSeen = new Date(storyTargetCache === null || storyTargetCache === void 0 ? void 0 : storyTargetCache.data.lastStorySeenExpiresAt).getTime() || 0;
29761
- const expiresAt = new Date(story.expiresAt).getTime();
29762
- return Math.max(localLastSeen, serverLastSeen) >= expiresAt;
29785
+ return userLinkedObject(user);
29786
+ }, cancel: async () => {
29787
+ await cancelJoinRequest(joinRequest);
29788
+ }, approve: async () => {
29789
+ await approveJoinRequest(joinRequest);
29790
+ }, reject: async () => {
29791
+ await rejectJoinRequest(joinRequest);
29763
29792
  } });
29764
29793
  };
29765
29794
 
29766
29795
  /* begin_public_function
29767
- id: channel.create
29796
+ id: community.getMyJoinRequest
29768
29797
  */
29769
29798
  /**
29770
29799
  * ```js
29771
- * import { createChannel } from '@amityco/ts-sdk-react-native'
29772
- * const created = await createChannel({ displayName: 'foobar' })
29800
+ * import { community } from '@amityco/ts-sdk-react-native'
29801
+ * const isJoined = await community.getMyJoinRequest('foobar')
29773
29802
  * ```
29774
29803
  *
29775
- * Creates an {@link Amity.Channel}
29804
+ * Joins a {@link Amity.Community} object
29776
29805
  *
29777
- * @param bundle The data necessary to create a new {@link Amity.Channel}
29778
- * @returns The newly created {@link Amity.Channel}
29806
+ * @param communityId the {@link Amity.Community} to join
29807
+ * @returns A success boolean if the {@link Amity.Community} was joined
29779
29808
  *
29780
- * @category Channel API
29809
+ * @category Community API
29781
29810
  * @async
29782
29811
  */
29783
- const createChannel = async (bundle) => {
29812
+ const getMyJoinRequest = async (communityId) => {
29784
29813
  const client = getActiveClient();
29785
- client.log('user/createChannel', bundle);
29786
- let payload;
29787
- /* c8 ignore next */
29788
- if ((bundle === null || bundle === void 0 ? void 0 : bundle.type) === 'conversation') {
29789
- payload = await client.http.post('/api/v3/channels/conversation', Object.assign(Object.assign({}, bundle), { isDistinct: true }));
29790
- }
29791
- else {
29792
- const { isPublic } = bundle, restParams = __rest(bundle, ["isPublic"]);
29793
- payload = await client.http.post('/api/v3/channels', Object.assign(Object.assign({}, restParams), {
29794
- /* c8 ignore next */
29795
- isPublic: (bundle === null || bundle === void 0 ? void 0 : bundle.type) === 'community' ? isPublic : undefined }));
29796
- }
29797
- const data = await prepareChannelPayload(payload.data);
29814
+ client.log('community/myJoinRequest', communityId);
29815
+ const { data: payload } = await client.http.get(`/api/v4/communities/${communityId}/join/me`);
29816
+ const data = prepareCommunityJoinRequestPayload(payload);
29798
29817
  const cachedAt = client.cache && Date.now();
29799
29818
  if (client.cache)
29800
29819
  ingestInCache(data, { cachedAt });
29801
- const { channels } = data;
29802
29820
  return {
29803
- data: constructChannelObject(channels[0]),
29821
+ data: data.joinRequests[0] ? joinRequestLinkedObject(data.joinRequests[0]) : undefined,
29804
29822
  cachedAt,
29805
29823
  };
29806
29824
  };
29807
29825
  /* end_public_function */
29808
29826
 
29827
+ /* begin_public_function
29828
+ id: community.join
29829
+ */
29809
29830
  /**
29810
29831
  * ```js
29811
- * import { getChannel } from '@amityco/ts-sdk-react-native'
29812
- * const channel = await getChannel('foobar')
29832
+ * import { community } from '@amityco/ts-sdk-react-native'
29833
+ * const isJoined = await community.join('foobar')
29813
29834
  * ```
29814
29835
  *
29815
- * Fetches a {@link Amity.Channel} object
29836
+ * Joins a {@link Amity.Community} object
29816
29837
  *
29817
- * @param channelId the ID of the {@link Amity.Channel} to fetch
29818
- * @returns the associated {@link Amity.Channel} object
29838
+ * @param communityId the {@link Amity.Community} to join
29839
+ * @returns A status join result
29819
29840
  *
29820
- * @category Channel API
29841
+ * @category Community API
29821
29842
  * @async
29822
29843
  */
29823
- const getChannel$1 = async (channelId) => {
29844
+ const joinRequest = async (communityId) => {
29845
+ var _a;
29824
29846
  const client = getActiveClient();
29825
- client.log('channel/getChannel', channelId);
29826
- isInTombstone('channel', channelId);
29827
- let data;
29828
- try {
29829
- const { data: payload } = await client.http.get(`/api/v3/channels/${encodeURIComponent(channelId)}`);
29830
- data = await prepareChannelPayload(payload);
29831
- if (client.isUnreadCountEnabled && client.getMarkerSyncConsistentMode()) {
29832
- prepareUnreadCountInfo(payload);
29847
+ client.log('community/joinRequest', communityId);
29848
+ const { data: payload } = await client.http.post(`/api/v4/communities/${communityId}/join`);
29849
+ const data = prepareCommunityJoinRequestPayload(payload);
29850
+ const cachedAt = client.cache && Date.now();
29851
+ if (client.cache)
29852
+ ingestInCache(data, { cachedAt });
29853
+ const status = data.joinRequests[0].status === "approved" /* JoinRequestStatusEnum.Approved */
29854
+ ? "success" /* JoinResultStatusEnum.Success */
29855
+ : "pending" /* JoinResultStatusEnum.Pending */;
29856
+ if (status === "success" /* JoinResultStatusEnum.Success */ && client.cache) {
29857
+ const community = (_a = pullFromCache(['community', 'get', communityId])) === null || _a === void 0 ? void 0 : _a.data;
29858
+ if (community) {
29859
+ const updatedCommunity = Object.assign(Object.assign({}, community), { isJoined: true });
29860
+ upsertInCache(['community', 'get', communityId], updatedCommunity);
29833
29861
  }
29834
29862
  }
29835
- catch (error) {
29836
- if (checkIfShouldGoesToTombstone(error === null || error === void 0 ? void 0 : error.code)) {
29837
- // NOTE: use channelPublicId as tombstone cache key since we cannot get the channelPrivateId that come along with channel data from server
29838
- pushToTombstone('channel', channelId);
29863
+ fireEvent('v4.local.community.joined', data.joinRequests);
29864
+ return status === "success" /* JoinResultStatusEnum.Success */
29865
+ ? { status }
29866
+ : { status, request: joinRequestLinkedObject(data.joinRequests[0]) };
29867
+ };
29868
+ /* end_public_function */
29869
+
29870
+ /**
29871
+ * TODO: handle cache receive cache option, and cache policy
29872
+ * TODO: check if querybyIds is supported
29873
+ */
29874
+ class JoinRequestsPaginationController extends PaginationController {
29875
+ async getRequest(queryParams, token) {
29876
+ const { limit = 20, communityId } = queryParams, params = __rest(queryParams, ["limit", "communityId"]);
29877
+ const options = token ? { token } : { limit };
29878
+ const { data: queryResponse } = await this.http.get(`/api/v4/communities/${communityId}/join`, {
29879
+ params: Object.assign(Object.assign({}, params), { options }),
29880
+ });
29881
+ return queryResponse;
29882
+ }
29883
+ }
29884
+
29885
+ var EnumJoinRequestAction$1;
29886
+ (function (EnumJoinRequestAction) {
29887
+ EnumJoinRequestAction["OnLocalJoinRequestCreated"] = "OnLocalJoinRequestCreated";
29888
+ EnumJoinRequestAction["OnLocalJoinRequestUpdated"] = "OnLocalJoinRequestUpdated";
29889
+ EnumJoinRequestAction["OnLocalJoinRequestDeleted"] = "OnLocalJoinRequestDeleted";
29890
+ })(EnumJoinRequestAction$1 || (EnumJoinRequestAction$1 = {}));
29891
+
29892
+ class JoinRequestsQueryStreamController extends QueryStreamController {
29893
+ constructor(query, cacheKey, notifyChange, preparePayload) {
29894
+ super(query, cacheKey);
29895
+ this.notifyChange = notifyChange;
29896
+ this.preparePayload = preparePayload;
29897
+ }
29898
+ async saveToMainDB(response) {
29899
+ const processedPayload = await this.preparePayload(response);
29900
+ const client = getActiveClient();
29901
+ const cachedAt = client.cache && Date.now();
29902
+ if (client.cache) {
29903
+ ingestInCache(processedPayload, { cachedAt });
29839
29904
  }
29840
- throw error;
29841
29905
  }
29842
- const cachedAt = client.cache && Date.now();
29843
- if (client.cache)
29844
- ingestInCache(data, { cachedAt });
29845
- const { channels } = data;
29846
- return {
29847
- data: channels.find(channel => channel.channelId === channelId),
29848
- cachedAt,
29906
+ appendToQueryStream(response, direction, refresh = false) {
29907
+ var _a, _b;
29908
+ if (refresh) {
29909
+ pushToCache(this.cacheKey, {
29910
+ data: response.joinRequests.map(joinRequest => getResolver('joinRequest')({ joinRequestId: joinRequest._id })),
29911
+ });
29912
+ }
29913
+ else {
29914
+ const collection = (_a = pullFromCache(this.cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
29915
+ const joinRequests = (_b = collection === null || collection === void 0 ? void 0 : collection.data) !== null && _b !== void 0 ? _b : [];
29916
+ pushToCache(this.cacheKey, Object.assign(Object.assign({}, collection), { data: [
29917
+ ...new Set([
29918
+ ...joinRequests,
29919
+ ...response.joinRequests.map(joinRequest => getResolver('joinRequest')({ joinRequestId: joinRequest._id })),
29920
+ ]),
29921
+ ] }));
29922
+ }
29923
+ }
29924
+ reactor(action) {
29925
+ return (joinRequest) => {
29926
+ var _a;
29927
+ const collection = (_a = pullFromCache(this.cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
29928
+ if (!collection)
29929
+ return;
29930
+ if (action === EnumJoinRequestAction$1.OnLocalJoinRequestUpdated) {
29931
+ const isExist = collection.data.find(id => id === joinRequest[0].joinRequestId);
29932
+ if (!isExist)
29933
+ return;
29934
+ }
29935
+ if (action === EnumJoinRequestAction$1.OnLocalJoinRequestCreated) {
29936
+ collection.data = [
29937
+ ...new Set([
29938
+ ...joinRequest.map(joinRequest => joinRequest.joinRequestId),
29939
+ ...collection.data,
29940
+ ]),
29941
+ ];
29942
+ }
29943
+ if (action === EnumJoinRequestAction$1.OnLocalJoinRequestDeleted) {
29944
+ collection.data = collection.data.filter(id => id !== joinRequest[0].joinRequestId);
29945
+ }
29946
+ pushToCache(this.cacheKey, collection);
29947
+ this.notifyChange({ origin: "event" /* Amity.LiveDataOrigin.EVENT */, loading: false });
29948
+ };
29949
+ }
29950
+ subscribeRTE(createSubscriber) {
29951
+ return createSubscriber.map(subscriber => subscriber.fn(this.reactor(subscriber.action)));
29952
+ }
29953
+ }
29954
+
29955
+ /**
29956
+ * ```js
29957
+ * import { onJoinRequestCreated } from '@amityco/ts-sdk-react-native'
29958
+ * const dispose = onJoinRequestCreated(data => {
29959
+ * // ...
29960
+ * })
29961
+ * ```
29962
+ *
29963
+ * Fired when an {@link Amity.CommunityJoinRequestPayload} has been created
29964
+ *
29965
+ * @param callback The function to call when the event was fired
29966
+ * @returns an {@link Amity.Unsubscriber} function to stop listening
29967
+ *
29968
+ * @category JoinRequest Events
29969
+ */
29970
+ const onJoinRequestCreated = (callback) => {
29971
+ const client = getActiveClient();
29972
+ const disposers = [
29973
+ createEventSubscriber(client, 'onJoinRequestCreated', 'local.joinRequest.created', payload => callback(payload)),
29974
+ ];
29975
+ return () => {
29976
+ disposers.forEach(fn => fn());
29849
29977
  };
29850
29978
  };
29979
+
29851
29980
  /**
29852
- * ```js
29853
- * import { getChannel } from '@amityco/ts-sdk-react-native'
29854
- * const channel = getChannel.locally('foobar')
29981
+ * ```js
29982
+ * import { onJoinRequestUpdated } from '@amityco/ts-sdk-react-native'
29983
+ * const dispose = onJoinRequestUpdated(data => {
29984
+ * // ...
29985
+ * })
29855
29986
  * ```
29856
29987
  *
29857
- * Fetches a {@link Amity.Channel} object from cache
29988
+ * Fired when an {@link Amity.CommunityJoinRequestPayload} has been created
29858
29989
  *
29859
- * @param channelId the ID of the {@link Amity.Channel} to fetch
29860
- * @returns the associated {@link Amity.Channel} object
29990
+ * @param callback The function to call when the event was fired
29991
+ * @returns an {@link Amity.Unsubscriber} function to stop listening
29861
29992
  *
29862
- * @category Channel API
29993
+ * @category JoinRequest Events
29863
29994
  */
29864
- getChannel$1.locally = (channelId) => {
29865
- var _a;
29995
+ const onJoinRequestUpdated = (callback) => {
29866
29996
  const client = getActiveClient();
29867
- client.log('channel/getChannel.locally', channelId);
29868
- if (!client.cache)
29869
- return;
29870
- // use queryCache to get all channel caches and filter by channelPublicId since we use channelPrivateId as cache key
29871
- const cached = (_a = queryCache(['channel', 'get'])) === null || _a === void 0 ? void 0 : _a.filter(({ data }) => {
29872
- return data.channelPublicId === channelId;
29873
- });
29874
- if (!cached || (cached === null || cached === void 0 ? void 0 : cached.length) === 0)
29875
- return;
29876
- return {
29877
- data: cached[0].data,
29878
- cachedAt: cached[0].cachedAt,
29997
+ const disposers = [
29998
+ createEventSubscriber(client, 'onJoinRequestUpdated', 'local.joinRequest.updated', payload => callback(payload)),
29999
+ ];
30000
+ return () => {
30001
+ disposers.forEach(fn => fn());
29879
30002
  };
29880
30003
  };
29881
30004
 
29882
30005
  /**
29883
30006
  * ```js
29884
- * import { getStream } from '@amityco/ts-sdk-react-native'
29885
- * const stream = await getStream('foobar')
30007
+ * import { onJoinRequestDeleted } from '@amityco/ts-sdk-react-native'
30008
+ * const dispose = onJoinRequestDeleted(data => {
30009
+ * // ...
30010
+ * })
29886
30011
  * ```
29887
30012
  *
29888
- * Fetches a {@link Amity.Channel} object linked with a current stream
30013
+ * Fired when an {@link Amity.CommunityJoinRequestPayload} has been created
29889
30014
  *
29890
- * @param stream {@link Amity.Stream} that has linked live channel
29891
- * @returns the associated {@link Amity.Channel<'live'>} object
30015
+ * @param callback The function to call when the event was fired
30016
+ * @returns an {@link Amity.Unsubscriber} function to stop listening
29892
30017
  *
29893
- * @category Stream API
29894
- * @async
30018
+ * @category JoinRequest Events
29895
30019
  */
29896
- const getLiveChat$1 = async (stream) => {
29897
- var _a;
30020
+ const onJoinRequestDeleted = (callback) => {
29898
30021
  const client = getActiveClient();
29899
- client.log('stream/getLiveChat', stream.streamId);
29900
- if (stream.channelId) {
29901
- const channel = (_a = pullFromCache([
29902
- 'channel',
29903
- 'get',
29904
- stream.channelId,
29905
- ])) === null || _a === void 0 ? void 0 : _a.data;
29906
- if (channel)
29907
- return channelLinkedObject(constructChannelObject(channel));
29908
- const { data } = await getChannel$1(stream.channelId);
29909
- return channelLinkedObject(constructChannelObject(data));
29910
- }
29911
- // No Channel ID
29912
- // streamer: create a new live channel
29913
- if (stream.userId === client.userId) {
29914
- const { data: channel } = await createChannel({
29915
- type: 'live',
29916
- postId: stream.postId,
29917
- videoStreamId: stream.streamId,
29918
- });
29919
- // Update channelId to stream object in cache
29920
- mergeInCache(['stream', 'get', stream.streamId], {
29921
- channelId: channel.channelId,
29922
- });
29923
- return channel;
29924
- }
29925
- // watcher: return undefined
29926
- return undefined;
29927
- };
29928
-
29929
- const GET_WATCHER_URLS = Symbol('getWatcherUrls');
29930
- const streamLinkedObject = (stream) => {
29931
- return Object.assign(Object.assign({}, stream), { get moderation() {
29932
- var _a;
29933
- return (_a = pullFromCache(['streamModeration', 'get', stream.streamId])) === null || _a === void 0 ? void 0 : _a.data;
29934
- },
29935
- get post() {
29936
- var _a;
29937
- if (stream.referenceType !== 'post')
29938
- return;
29939
- return (_a = pullFromCache(['post', 'get', stream.referenceId])) === null || _a === void 0 ? void 0 : _a.data;
29940
- },
29941
- get community() {
29942
- var _a;
29943
- if (stream.targetType !== 'community')
29944
- return;
29945
- return (_a = pullFromCache(['community', 'get', stream.targetId])) === null || _a === void 0 ? void 0 : _a.data;
29946
- },
29947
- get user() {
29948
- var _a;
29949
- return (_a = pullFromCache(['user', 'get', stream.userId])) === null || _a === void 0 ? void 0 : _a.data;
29950
- },
29951
- get childStreams() {
29952
- if (!stream.childStreamIds || stream.childStreamIds.length === 0)
29953
- return [];
29954
- return stream.childStreamIds
29955
- .map(id => {
29956
- var _a;
29957
- const streamCache = (_a = pullFromCache(['stream', 'get', id])) === null || _a === void 0 ? void 0 : _a.data;
29958
- if (!streamCache)
29959
- return undefined;
29960
- return streamLinkedObject(streamCache);
29961
- })
29962
- .filter(isNonNullable);
29963
- }, getLiveChat: () => getLiveChat$1(stream), isBanned: !stream.watcherUrl, watcherUrl: null, get [GET_WATCHER_URLS]() {
29964
- return stream.watcherUrl;
29965
- } });
29966
- };
29967
-
29968
- const categoryLinkedObject = (category) => {
29969
- return Object.assign(Object.assign({}, category), { get avatar() {
29970
- var _a;
29971
- if (!category.avatarFileId)
29972
- return undefined;
29973
- const avatar = (_a = pullFromCache([
29974
- 'file',
29975
- 'get',
29976
- `${category.avatarFileId}`,
29977
- ])) === null || _a === void 0 ? void 0 : _a.data;
29978
- return avatar;
29979
- } });
29980
- };
29981
-
29982
- const commentLinkedObject = (comment) => {
29983
- return Object.assign(Object.assign({}, comment), { get target() {
29984
- const commentTypes = {
29985
- type: comment.targetType,
29986
- };
29987
- if (comment.targetType === 'user') {
29988
- return Object.assign(Object.assign({}, commentTypes), { userId: comment.targetId });
29989
- }
29990
- if (commentTypes.type === 'content') {
29991
- return Object.assign(Object.assign({}, commentTypes), { contentId: comment.targetId });
29992
- }
29993
- if (commentTypes.type === 'community') {
29994
- const cacheData = pullFromCache([
29995
- 'communityUsers',
29996
- 'get',
29997
- `${comment.targetId}#${comment.userId}`,
29998
- ]);
29999
- return Object.assign(Object.assign({}, commentTypes), { communityId: comment.targetId, creatorMember: cacheData === null || cacheData === void 0 ? void 0 : cacheData.data });
30000
- }
30001
- return {
30002
- type: 'unknown',
30003
- };
30004
- },
30005
- get creator() {
30006
- const cacheData = pullFromCache(['user', 'get', comment.userId]);
30007
- if (cacheData === null || cacheData === void 0 ? void 0 : cacheData.data)
30008
- return userLinkedObject(cacheData.data);
30009
- return undefined;
30010
- },
30011
- get childrenComment() {
30012
- return comment.children
30013
- .map(childCommentId => {
30014
- const commentCache = pullFromCache([
30015
- 'comment',
30016
- 'get',
30017
- childCommentId,
30018
- ]);
30019
- if (!(commentCache === null || commentCache === void 0 ? void 0 : commentCache.data))
30020
- return;
30021
- return commentCache === null || commentCache === void 0 ? void 0 : commentCache.data;
30022
- })
30023
- .filter(isNonNullable)
30024
- .map(item => commentLinkedObject(item));
30025
- } });
30022
+ const disposers = [
30023
+ createEventSubscriber(client, 'onJoinRequestDeleted', 'local.joinRequest.deleted', payload => callback(payload)),
30024
+ ];
30025
+ return () => {
30026
+ disposers.forEach(fn => fn());
30027
+ };
30026
30028
  };
30027
30029
 
30028
- function isAmityImagePost(post) {
30029
- return !!(post.data &&
30030
- typeof post.data !== 'string' &&
30031
- 'fileId' in post.data &&
30032
- post.dataType === 'image');
30033
- }
30034
- function isAmityFilePost(post) {
30035
- return !!(post.data &&
30036
- typeof post.data !== 'string' &&
30037
- 'fileId' in post.data &&
30038
- post.dataType === 'file');
30039
- }
30040
- function isAmityVideoPost(post) {
30041
- return !!(post.data &&
30042
- typeof post.data !== 'string' &&
30043
- 'videoFileId' in post.data &&
30044
- 'thumbnailFileId' in post.data &&
30045
- post.dataType === 'video');
30046
- }
30047
- function isAmityLivestreamPost(post) {
30048
- return !!(post.data &&
30049
- typeof post.data !== 'string' &&
30050
- 'streamId' in post.data &&
30051
- post.dataType === 'liveStream');
30052
- }
30053
- function isAmityPollPost(post) {
30054
- return !!(post.data &&
30055
- typeof post.data !== 'string' &&
30056
- 'pollId' in post.data &&
30057
- post.dataType === 'poll');
30058
- }
30059
- function isAmityClipPost(post) {
30060
- return !!(post.data &&
30061
- typeof post.data !== 'string' &&
30062
- 'fileId' in post.data &&
30063
- post.dataType === 'clip');
30064
- }
30065
- function isAmityAudioPost(post) {
30066
- return !!(post.data &&
30067
- typeof post.data !== 'string' &&
30068
- 'fileId' in post.data &&
30069
- post.dataType === 'audio');
30070
- }
30071
- function isAmityRoomPost(post) {
30072
- return !!(post.data &&
30073
- typeof post.data !== 'string' &&
30074
- 'roomId' in post.data &&
30075
- post.dataType === 'room');
30030
+ class JoinRequestsLiveCollectionController extends LiveCollectionController {
30031
+ constructor(query, callback) {
30032
+ const queryStreamId = hash(query);
30033
+ const cacheKey = ['joinRequest', 'collection', queryStreamId];
30034
+ const paginationController = new JoinRequestsPaginationController(query);
30035
+ super(paginationController, queryStreamId, cacheKey, callback);
30036
+ this.query = query;
30037
+ this.queryStreamController = new JoinRequestsQueryStreamController(this.query, this.cacheKey, this.notifyChange.bind(this), prepareCommunityJoinRequestPayload);
30038
+ this.callback = callback.bind(this);
30039
+ this.loadPage({ initial: true });
30040
+ }
30041
+ setup() {
30042
+ var _a;
30043
+ const collection = (_a = pullFromCache(this.cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
30044
+ if (!collection) {
30045
+ pushToCache(this.cacheKey, {
30046
+ data: [],
30047
+ params: this.query,
30048
+ });
30049
+ }
30050
+ }
30051
+ async persistModel(queryPayload) {
30052
+ await this.queryStreamController.saveToMainDB(queryPayload);
30053
+ }
30054
+ persistQueryStream({ response, direction, refresh, }) {
30055
+ const joinRequestResponse = response;
30056
+ this.queryStreamController.appendToQueryStream(joinRequestResponse, direction, refresh);
30057
+ }
30058
+ startSubscription() {
30059
+ return this.queryStreamController.subscribeRTE([
30060
+ { fn: onJoinRequestCreated, action: EnumJoinRequestAction$1.OnLocalJoinRequestCreated },
30061
+ { fn: onJoinRequestUpdated, action: EnumJoinRequestAction$1.OnLocalJoinRequestUpdated },
30062
+ { fn: onJoinRequestDeleted, action: EnumJoinRequestAction$1.OnLocalJoinRequestDeleted },
30063
+ ]);
30064
+ }
30065
+ notifyChange({ origin, loading, error }) {
30066
+ var _a;
30067
+ const collection = (_a = pullFromCache(this.cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
30068
+ if (!collection)
30069
+ return;
30070
+ const data = this.applyFilter(collection.data
30071
+ .map(id => pullFromCache(['joinRequest', 'get', id]))
30072
+ .filter(isNonNullable)
30073
+ .map(({ data }) => data)
30074
+ .map(joinRequestLinkedObject));
30075
+ if (!this.shouldNotify(data) && origin === 'event')
30076
+ return;
30077
+ this.callback({
30078
+ onNextPage: () => this.loadPage({ direction: "next" /* Amity.LiveCollectionPageDirection.NEXT */ }),
30079
+ data,
30080
+ hasNextPage: !!this.paginationController.getNextToken(),
30081
+ loading,
30082
+ error,
30083
+ });
30084
+ }
30085
+ applyFilter(data) {
30086
+ let joinRequest = data;
30087
+ if (this.query.status) {
30088
+ joinRequest = joinRequest.filter(joinRequest => joinRequest.status === this.query.status);
30089
+ }
30090
+ const sortFn = (() => {
30091
+ switch (this.query.sortBy) {
30092
+ case 'firstCreated':
30093
+ return sortByFirstCreated;
30094
+ case 'lastCreated':
30095
+ return sortByLastCreated;
30096
+ default:
30097
+ return sortByLastCreated;
30098
+ }
30099
+ })();
30100
+ joinRequest = joinRequest.sort(sortFn);
30101
+ return joinRequest;
30102
+ }
30076
30103
  }
30077
30104
 
30078
30105
  /**
30079
- * ```js
30080
- * import { RoomRepository } from '@amityco/ts-sdk-react-native'
30081
- * const stream = await getStream('foobar')
30082
- * ```
30106
+ * Get Join Requests
30083
30107
  *
30084
- * Fetches a {@link Amity.Channel} object linked with a current stream
30108
+ * @param params the query parameters
30109
+ * @param callback the callback to be called when the join request are updated
30110
+ * @returns joinRequests
30085
30111
  *
30086
- * @param stream {@link Amity.Stream} that has linked live channel
30087
- * @returns the associated {@link Amity.Channel<'live'>} object
30112
+ * @category joinRequest Live Collection
30088
30113
  *
30089
- * @category Stream API
30090
- * @async
30091
30114
  */
30092
- const getLiveChat = async (room) => {
30093
- var _a;
30094
- const client = getActiveClient();
30095
- client.log('room/getLiveChat', room.roomId);
30096
- if (room.liveChannelId) {
30097
- const channel = (_a = pullFromCache([
30098
- 'channel',
30099
- 'get',
30100
- room.liveChannelId,
30101
- ])) === null || _a === void 0 ? void 0 : _a.data;
30102
- if (channel)
30103
- return channelLinkedObject(constructChannelObject(channel));
30104
- const { data } = await getChannel$1(room.liveChannelId);
30105
- return channelLinkedObject(constructChannelObject(data));
30106
- }
30107
- // No Channel ID
30108
- // streamer: create a new live channel
30109
- if (room.createdBy === client.userId) {
30110
- const { data: channel } = await createChannel({
30111
- type: 'live',
30112
- postId: room.referenceId,
30113
- roomId: room.roomId,
30114
- });
30115
- // Update channelId to stream object in cache
30116
- mergeInCache(['room', 'get', room.roomId], {
30117
- liveChannelId: channel.channelId,
30118
- });
30119
- return channel;
30115
+ const getJoinRequests = (params, callback, config) => {
30116
+ const { log, cache } = getActiveClient();
30117
+ if (!cache) {
30118
+ console.log(ENABLE_CACHE_MESSAGE);
30120
30119
  }
30121
- // watcher: return undefined
30122
- return undefined;
30120
+ const timestamp = Date.now();
30121
+ log(`getJoinRequests: (tmpid: ${timestamp}) > listen`);
30122
+ const joinRequestLiveCollection = new JoinRequestsLiveCollectionController(params, callback);
30123
+ const disposers = joinRequestLiveCollection.startSubscription();
30124
+ const cacheKey = joinRequestLiveCollection.getCacheKey();
30125
+ disposers.push(() => {
30126
+ dropFromCache(cacheKey);
30127
+ });
30128
+ return () => {
30129
+ log(`getJoinRequests (tmpid: ${timestamp}) > dispose`);
30130
+ disposers.forEach(fn => fn());
30131
+ };
30123
30132
  };
30124
30133
 
30125
30134
  const convertRawInvitationToInternalInvitation = (rawInvitation) => {
@@ -30274,1391 +30283,1382 @@ const invitationLinkedObject = (invitation) => {
30274
30283
  } });
30275
30284
  };
30276
30285
 
30277
- /* begin_public_function
30278
- id: invitation.get
30279
- */
30286
+ /* begin_public_function
30287
+ id: invitation.get
30288
+ */
30289
+ /**
30290
+ * ```js
30291
+ * import { getInvitation } from '@amityco/ts-sdk-react-native'
30292
+ * const { invitation } = await getInvitation(targetType, targetId)
30293
+ * ```
30294
+ *
30295
+ * Get a {@link Amity.Invitation} object
30296
+ *
30297
+ * @param targetType The type of the target of the {@link Amity.Invitation}
30298
+ * @param targetId The ID of the target of the {@link Amity.Invitation}
30299
+ * @returns A {@link Amity.Invitation} object
30300
+ *
30301
+ * @category Invitation API
30302
+ * @async
30303
+ */
30304
+ const getInvitation = async (params) => {
30305
+ const client = getActiveClient();
30306
+ client.log('invitation/getInvitation', params.targetType, params.targetId, params.type);
30307
+ const { data: payload } = await client.http.get(`/api/v1/invitations/me`, { params });
30308
+ const data = prepareMyInvitationsPayload(payload);
30309
+ const cachedAt = client.cache && Date.now();
30310
+ if (client.cache)
30311
+ ingestInCache(data, { cachedAt });
30312
+ return {
30313
+ data: data.invitations[0] ? invitationLinkedObject(data.invitations[0]) : undefined,
30314
+ cachedAt,
30315
+ };
30316
+ };
30317
+ /* end_public_function */
30318
+
30319
+ var InvitationActionsEnum;
30320
+ (function (InvitationActionsEnum) {
30321
+ InvitationActionsEnum["OnLocalInvitationCreated"] = "onLocalInvitationCreated";
30322
+ InvitationActionsEnum["OnLocalInvitationUpdated"] = "onLocalInvitationUpdated";
30323
+ InvitationActionsEnum["OnLocalInvitationCanceled"] = "onLocalInvitationCanceled";
30324
+ })(InvitationActionsEnum || (InvitationActionsEnum = {}));
30325
+
30326
+ class InvitationsPaginationController extends PaginationController {
30327
+ async getRequest(queryParams, token) {
30328
+ const { limit = COLLECTION_DEFAULT_PAGINATION_LIMIT } = queryParams, params = __rest(queryParams, ["limit"]);
30329
+ const options = token ? { token } : { limit };
30330
+ const { data } = await this.http.get('/api/v1/invitations', { params: Object.assign(Object.assign({}, params), { options }) });
30331
+ return data;
30332
+ }
30333
+ }
30334
+
30335
+ class InvitationsQueryStreamController extends QueryStreamController {
30336
+ constructor(query, cacheKey, notifyChange, preparePayload) {
30337
+ super(query, cacheKey);
30338
+ this.notifyChange = notifyChange;
30339
+ this.preparePayload = preparePayload;
30340
+ }
30341
+ async saveToMainDB(response) {
30342
+ const processedPayload = await this.preparePayload(response);
30343
+ const client = getActiveClient();
30344
+ const cachedAt = client.cache && Date.now();
30345
+ if (client.cache) {
30346
+ ingestInCache(processedPayload, { cachedAt });
30347
+ }
30348
+ }
30349
+ appendToQueryStream(response, direction, refresh = false) {
30350
+ var _a, _b;
30351
+ if (refresh) {
30352
+ pushToCache(this.cacheKey, {
30353
+ data: response.invitations.map(getResolver('invitation')),
30354
+ });
30355
+ }
30356
+ else {
30357
+ const collection = (_a = pullFromCache(this.cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
30358
+ const invitations = (_b = collection === null || collection === void 0 ? void 0 : collection.data) !== null && _b !== void 0 ? _b : [];
30359
+ pushToCache(this.cacheKey, Object.assign(Object.assign({}, collection), { data: [
30360
+ ...new Set([...invitations, ...response.invitations.map(getResolver('invitation'))]),
30361
+ ] }));
30362
+ }
30363
+ }
30364
+ reactor(action) {
30365
+ return (invitations) => {
30366
+ var _a;
30367
+ const collection = (_a = pullFromCache(this.cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
30368
+ if (!collection)
30369
+ return;
30370
+ if (action === InvitationActionsEnum.OnLocalInvitationUpdated) {
30371
+ const isExist = collection.data.find(id => id === invitations[0].invitationId);
30372
+ if (!isExist)
30373
+ return;
30374
+ }
30375
+ if (action === InvitationActionsEnum.OnLocalInvitationCreated) {
30376
+ collection.data = [
30377
+ ...new Set([
30378
+ ...invitations.map(invitation => invitation.invitationId),
30379
+ ...collection.data,
30380
+ ]),
30381
+ ];
30382
+ }
30383
+ if (action === InvitationActionsEnum.OnLocalInvitationDeleted) {
30384
+ collection.data = collection.data.filter(id => id !== invitations[0].invitationId);
30385
+ }
30386
+ pushToCache(this.cacheKey, collection);
30387
+ this.notifyChange({ origin: "event" /* Amity.LiveDataOrigin.EVENT */, loading: false });
30388
+ };
30389
+ }
30390
+ subscribeRTE(createSubscriber) {
30391
+ return createSubscriber.map(subscriber => subscriber.fn(this.reactor(subscriber.action)));
30392
+ }
30393
+ }
30394
+
30395
+ /**
30396
+ * ```js
30397
+ * import { onLocalInvitationCreated } from '@amityco/ts-sdk-react-native'
30398
+ * const dispose = onLocalInvitationCreated(data => {
30399
+ * // ...
30400
+ * })
30401
+ * ```
30402
+ *
30403
+ * Fired when an {@link Amity.InvitationPayload} has been created
30404
+ *
30405
+ * @param callback The function to call when the event was fired
30406
+ * @returns an {@link Amity.Unsubscriber} function to stop listening
30407
+ *
30408
+ * @category Invitation Events
30409
+ */
30410
+ const onLocalInvitationCreated = (callback) => {
30411
+ const client = getActiveClient();
30412
+ const disposers = [
30413
+ createEventSubscriber(client, 'onLocalInvitationCreated', 'local.invitation.created', payload => callback(payload)),
30414
+ ];
30415
+ return () => {
30416
+ disposers.forEach(fn => fn());
30417
+ };
30418
+ };
30419
+
30420
+ /**
30421
+ * ```js
30422
+ * import { onLocalInvitationUpdated } from '@amityco/ts-sdk-react-native'
30423
+ * const dispose = onLocalInvitationUpdated(data => {
30424
+ * // ...
30425
+ * })
30426
+ * ```
30427
+ *
30428
+ * Fired when an {@link Amity.InvitationPayload} has been updated
30429
+ *
30430
+ * @param callback The function to call when the event was fired
30431
+ * @returns an {@link Amity.Unsubscriber} function to stop listening
30432
+ *
30433
+ * @category Invitation Events
30434
+ */
30435
+ const onLocalInvitationUpdated = (callback) => {
30436
+ const client = getActiveClient();
30437
+ const disposers = [
30438
+ createEventSubscriber(client, 'onLocalInvitationUpdated', 'local.invitation.updated', payload => callback(payload)),
30439
+ ];
30440
+ return () => {
30441
+ disposers.forEach(fn => fn());
30442
+ };
30443
+ };
30444
+
30280
30445
  /**
30281
30446
  * ```js
30282
- * import { getInvitation } from '@amityco/ts-sdk-react-native'
30283
- * const { invitation } = await getInvitation(targetType, targetId)
30447
+ * import { onLocalInvitationCanceled } from '@amityco/ts-sdk-react-native'
30448
+ * const dispose = onLocalInvitationCanceled(data => {
30449
+ * // ...
30450
+ * })
30284
30451
  * ```
30285
30452
  *
30286
- * Get a {@link Amity.Invitation} object
30453
+ * Fired when an {@link Amity.InvitationPayload} has been deleted
30287
30454
  *
30288
- * @param targetType The type of the target of the {@link Amity.Invitation}
30289
- * @param targetId The ID of the target of the {@link Amity.Invitation}
30290
- * @returns A {@link Amity.Invitation} object
30455
+ * @param callback The function to call when the event was fired
30456
+ * @returns an {@link Amity.Unsubscriber} function to stop listening
30291
30457
  *
30292
- * @category Invitation API
30293
- * @async
30458
+ * @category Invitation Events
30294
30459
  */
30295
- const getInvitation = async (params) => {
30460
+ const onLocalInvitationCanceled = (callback) => {
30296
30461
  const client = getActiveClient();
30297
- client.log('invitation/getInvitation', params.targetType, params.targetId, params.type);
30298
- const { data: payload } = await client.http.get(`/api/v1/invitations/me`, { params });
30299
- const data = prepareMyInvitationsPayload(payload);
30300
- const cachedAt = client.cache && Date.now();
30301
- if (client.cache)
30302
- ingestInCache(data, { cachedAt });
30303
- return {
30304
- data: data.invitations[0] ? invitationLinkedObject(data.invitations[0]) : undefined,
30305
- cachedAt,
30462
+ const disposers = [
30463
+ createEventSubscriber(client, 'onLocalInvitationCanceled', 'local.invitation.canceled', payload => callback(payload)),
30464
+ ];
30465
+ return () => {
30466
+ disposers.forEach(fn => fn());
30306
30467
  };
30307
30468
  };
30308
- /* end_public_function */
30309
30469
 
30310
- /**
30311
- * WatchSessionStorage manages watch session data in memory
30312
- * Similar to UsageCollector for stream watch minutes
30313
- */
30314
- class WatchSessionStorage {
30315
- constructor() {
30316
- this.sessions = new Map();
30317
- }
30318
- /**
30319
- * Add a new watch session
30320
- */
30321
- addSession(session) {
30322
- this.sessions.set(session.sessionId, session);
30323
- }
30324
- /**
30325
- * Get a watch session by sessionId
30326
- */
30327
- getSession(sessionId) {
30328
- return this.sessions.get(sessionId);
30470
+ class InvitationsLiveCollectionController extends LiveCollectionController {
30471
+ constructor(query, callback) {
30472
+ const queryStreamId = hash(query);
30473
+ const cacheKey = ['invitation', 'collection', queryStreamId];
30474
+ const paginationController = new InvitationsPaginationController(query);
30475
+ super(paginationController, queryStreamId, cacheKey, callback);
30476
+ this.query = query;
30477
+ this.queryStreamController = new InvitationsQueryStreamController(this.query, this.cacheKey, this.notifyChange.bind(this), prepareInvitationPayload);
30478
+ this.callback = callback.bind(this);
30479
+ this.loadPage({ initial: true });
30329
30480
  }
30330
- /**
30331
- * Update a watch session
30332
- */
30333
- updateSession(sessionId, updates) {
30334
- const session = this.sessions.get(sessionId);
30335
- if (session) {
30336
- this.sessions.set(sessionId, Object.assign(Object.assign({}, session), updates));
30481
+ setup() {
30482
+ var _a;
30483
+ const collection = (_a = pullFromCache(this.cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
30484
+ if (!collection) {
30485
+ pushToCache(this.cacheKey, {
30486
+ data: [],
30487
+ params: this.query,
30488
+ });
30337
30489
  }
30338
30490
  }
30339
- /**
30340
- * Get all sessions with a specific sync state
30341
- */
30342
- getSessionsByState(state) {
30343
- return Array.from(this.sessions.values()).filter(session => session.syncState === state);
30344
- }
30345
- /**
30346
- * Delete a session
30347
- */
30348
- deleteSession(sessionId) {
30349
- this.sessions.delete(sessionId);
30350
- }
30351
- /**
30352
- * Get all pending sessions
30353
- */
30354
- getPendingSessions() {
30355
- return this.getSessionsByState('PENDING');
30356
- }
30357
- /**
30358
- * Get all syncing sessions
30359
- */
30360
- getSyncingSessions() {
30361
- return this.getSessionsByState('SYNCING');
30362
- }
30363
- }
30364
- // Singleton instance
30365
- let storageInstance = null;
30366
- const getWatchSessionStorage = () => {
30367
- if (!storageInstance) {
30368
- storageInstance = new WatchSessionStorage();
30369
- }
30370
- return storageInstance;
30371
- };
30372
-
30373
- const privateKey = "-----BEGIN PRIVATE KEY-----\nMIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDAARz+hmBgi8pJ\nQb8LeY41gtHhk+ACMwRfhsn7GqpqRQNG2qU0755mzZuVDUqjQMGSo8THJB7O+OJs\nflbZRkFXlFoFOVNw1UpNOgwEQZ6wB9oRwzepTJAfF1sVhm/o/ixvXh1zDFNDy6yZ\npXyiiJHUVxqyjllZhxnwdvjoVtDs6hW6awG09bB9nh/TTejlUKXoAgzqVwu/1QMu\nUVViET495elEe19aUarEy+oL2iKeXCEvqda/pWNBdbieFyJvvZ08HN8dPuT88wq2\njZLEAth1vrwQ2IAa4ktaLcBQdLJgIkrbDvAiVZ8lQAjS/bq5vXQikTGvoPlC5bbn\nvuOM/3eLAgMBAAECggEAVZ+peHAghq2QVj71nX5lxsNCKaCyYwixSJBpfouTt7Rz\nE6PpzMOXFi1W1o+I22jDakuSM2SOQKqI/u0QefB0r0O/KVk5NrZHXk0mkrdYtxOp\nUgaGyf8UvmjB+8VqHrNKyZdk9qtmbnNj01kTTcAtmE4H39zPR7eR/8Rul94vaZbs\nwCnKJS3mLT3JxyGug6lxanveKkjG+CKC1nJQYWaxCJxaFSzbwXQPvDhB+TvrIbee\npd5v4EAyEJohpr+T9oDGGJkb/KARBZCtwLyB976PKJwwBA8MRVL1i5QwawuMiMq5\nUtnOnbGKtCeFzaLbNU0Qi8bqyims84EQxC6DOu1fkQKBgQDdvsoBsEhsOXV7hlIJ\naEd0eSJZVkdqimxH8uGoMM2FeNaOrcB6yBXqTSP0R3OIyf8eaY6yjRvP30ZNXcll\n/gD3O1Mu6YmWQdt1W2WA6pKOsUuPXasf0pdOF7IiFZKlSabz5YHXFqwVuqm8loaj\nsXel3YWqPVdHiankE7tz+3ssnQKBgQDdqi4TNdD1MdEpihx19jr0QjUiXW3939FK\nqp30HESPEGDGQzXdmJgif9HhZb+cJSuWaHEbjgBrYahvgCF+y6LbEpOD+D/dmT+s\nDEAQaR84sah6dokwPjV8fjBSrcVFjCS+doxv0d3p/9OUEeyUhFrY03nxtIEYkLIE\n/Zvn37b4RwKBgQCLENVFe9XfsaVhQ5r9dV2iyTlmh7qgMZG5CbTFs12hQGhm8McO\n+Z7s41YSJCFr/yq1WwP4LJDtrBw99vyQr1zRsG35tNLp3gGRNzGQSQyC2uQFVHw2\np+7mNewsfhUK/gbrXNsyFnDz6635rPlhfbII3sWuP2wWXFqkxE9CbMwR7QKBgQC6\nawDMzxmo2/iYArrkyevSuEuPVxvFwpF1RgAI6C0QVCnPE38dmdN4UB7mfHekje4W\nVEercMURidPp0cxZolCYBQtilUjAyL0vqC3In1/Ogjq6oy3FEMxSop1pKxMY5j+Q\nnoqFD+6deLUrddeNH7J3X4LSr4dSbX4JjG+tlgt+yQKBgQCuwTL4hA6KqeInQ0Ta\n9VQX5Qr8hFlqJz1gpymi/k63tW/Ob8yedbg3WWNWyShwRMFYyY9S81ITFWM95uL6\nvF3x9rmRjwElJw9PMwVu6dmf/CO0Z1wzXSp2VVD12gbrUD/0/d7MUoJ9LgC8X8f/\nn0txLHYGHbx+nf95+JUg6lV3hg==\n-----END PRIVATE KEY-----";
30374
- /*
30375
- * The crypto algorithm used for importing key and signing string
30376
- */
30377
- const ALGORITHM = {
30378
- name: 'RSASSA-PKCS1-v1_5',
30379
- hash: { name: 'SHA-256' },
30380
- };
30381
- /*
30382
- * IMPORTANT!
30383
- * If you are recieving key from other platforms use an online tool to convert
30384
- * the PKCS1 to PKCS8. For instance the key from Android SDK is of the format
30385
- * PKCS1.
30386
- *
30387
- * If recieving from the platform, verify if it's already in the expected
30388
- * format. Otherwise the crypto.subtle.importKey will throw a DOMException
30389
- */
30390
- const PRIVATE_KEY_SIGNATURE = 'pkcs8';
30391
- /*
30392
- * Ensure that the private key in the .env follows this format
30393
- */
30394
- const PEM_HEADER = '-----BEGIN PRIVATE KEY-----';
30395
- const PEM_FOOTER = '-----END PRIVATE KEY-----';
30396
- /*
30397
- * The crypto.subtle.sign function returns an ArrayBuffer whereas the server
30398
- * expects a base64 string. This util helps facilitate that process
30399
- */
30400
- function base64FromArrayBuffer(buffer) {
30401
- const uint8Array = new Uint8Array(buffer);
30402
- let binary = '';
30403
- uint8Array.forEach(byte => {
30404
- binary += String.fromCharCode(byte);
30405
- });
30406
- return btoa(binary);
30407
- }
30408
- /*
30409
- * Encode ASN.1 length field
30410
- */
30411
- function encodeLength(length) {
30412
- if (length < 128) {
30413
- return new Uint8Array([length]);
30491
+ async persistModel(queryPayload) {
30492
+ await this.queryStreamController.saveToMainDB(queryPayload);
30414
30493
  }
30415
- if (length < 256) {
30416
- return new Uint8Array([0x81, length]);
30494
+ persistQueryStream({ response, direction, refresh, }) {
30495
+ this.queryStreamController.appendToQueryStream(response, direction, refresh);
30417
30496
  }
30418
- // eslint-disable-next-line no-bitwise
30419
- return new Uint8Array([0x82, (length >> 8) & 0xff, length & 0xff]);
30420
- }
30421
- /*
30422
- * Convert PKCS1 private key to PKCS8 format
30423
- * PKCS1 is RSA-specific format, PKCS8 is generic format that crypto.subtle requires
30424
- * Android uses PKCS8EncodedKeySpec which expects PKCS8 format
30425
- */
30426
- function pkcs1ToPkcs8(pkcs1) {
30427
- // Algorithm identifier for RSA
30428
- const algorithmIdentifier = new Uint8Array([
30429
- 0x30,
30430
- 0x0d,
30431
- 0x06,
30432
- 0x09,
30433
- 0x2a,
30434
- 0x86,
30435
- 0x48,
30436
- 0x86,
30437
- 0xf7,
30438
- 0x0d,
30439
- 0x01,
30440
- 0x01,
30441
- 0x01,
30442
- 0x05,
30443
- 0x00, // NULL
30444
- ]);
30445
- // Version (INTEGER 0)
30446
- const version = new Uint8Array([0x02, 0x01, 0x00]);
30447
- // OCTET STRING tag + length + pkcs1 data
30448
- const octetStringTag = 0x04;
30449
- const octetStringLength = encodeLength(pkcs1.length);
30450
- // Calculate total content length (version + algorithm + octet string)
30451
- const contentLength = version.length + algorithmIdentifier.length + 1 + octetStringLength.length + pkcs1.length;
30452
- // SEQUENCE tag + length
30453
- const sequenceTag = 0x30;
30454
- const sequenceLength = encodeLength(contentLength);
30455
- // Build the PKCS8 structure
30456
- const pkcs8 = new Uint8Array(1 + sequenceLength.length + contentLength);
30457
- let offset = 0;
30458
- pkcs8[offset] = sequenceTag;
30459
- offset += 1;
30460
- pkcs8.set(sequenceLength, offset);
30461
- offset += sequenceLength.length;
30462
- pkcs8.set(version, offset);
30463
- offset += version.length;
30464
- pkcs8.set(algorithmIdentifier, offset);
30465
- offset += algorithmIdentifier.length;
30466
- pkcs8[offset] = octetStringTag;
30467
- offset += 1;
30468
- pkcs8.set(octetStringLength, offset);
30469
- offset += octetStringLength.length;
30470
- pkcs8.set(pkcs1, offset);
30471
- return pkcs8;
30472
- }
30473
- async function importPrivateKey(keyString) {
30474
- // Remove PEM headers if present and any whitespace
30475
- let base64Key = keyString;
30476
- if (keyString.includes(PEM_HEADER)) {
30477
- base64Key = keyString
30478
- .substring(PEM_HEADER.length, keyString.length - PEM_FOOTER.length)
30479
- .replace(/\s/g, '');
30497
+ startSubscription() {
30498
+ return this.queryStreamController.subscribeRTE([
30499
+ {
30500
+ fn: onLocalInvitationCreated,
30501
+ action: InvitationActionsEnum.OnLocalInvitationCreated,
30502
+ },
30503
+ {
30504
+ fn: onLocalInvitationUpdated,
30505
+ action: InvitationActionsEnum.OnLocalInvitationUpdated,
30506
+ },
30507
+ {
30508
+ fn: onLocalInvitationCanceled,
30509
+ action: InvitationActionsEnum.OnLocalInvitationCanceled,
30510
+ },
30511
+ ]);
30480
30512
  }
30481
- else {
30482
- base64Key = keyString.replace(/\s/g, '');
30513
+ notifyChange({ origin, loading, error }) {
30514
+ var _a, _b;
30515
+ const collection = (_a = pullFromCache(this.cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
30516
+ if (!collection)
30517
+ return;
30518
+ const data = this.applyFilter((_b = collection.data
30519
+ .map(id => pullFromCache(['invitation', 'get', id]))
30520
+ .filter(isNonNullable)
30521
+ .map(({ data }) => invitationLinkedObject(data))) !== null && _b !== void 0 ? _b : []);
30522
+ if (!this.shouldNotify(data) && origin === 'event')
30523
+ return;
30524
+ this.callback({
30525
+ onNextPage: () => this.loadPage({ direction: "next" /* Amity.LiveCollectionPageDirection.NEXT */ }),
30526
+ data,
30527
+ hasNextPage: !!this.paginationController.getNextToken(),
30528
+ loading,
30529
+ error,
30530
+ });
30483
30531
  }
30484
- // Base64 decode to get binary data
30485
- const binaryDerString = atob(base64Key);
30486
- // Convert to Uint8Array for manipulation
30487
- const pkcs1 = new Uint8Array(binaryDerString.length);
30488
- for (let i = 0; i < binaryDerString.length; i += 1) {
30489
- pkcs1[i] = binaryDerString.charCodeAt(i);
30532
+ applyFilter(data) {
30533
+ let invitations = data;
30534
+ if (this.query.targetId) {
30535
+ invitations = invitations.filter(invitation => invitation.targetId === this.query.targetId);
30536
+ }
30537
+ if (this.query.statuses) {
30538
+ invitations = invitations.filter(invitation => { var _a; return (_a = this.query.statuses) === null || _a === void 0 ? void 0 : _a.includes(invitation.status); });
30539
+ }
30540
+ if (this.query.targetType) {
30541
+ invitations = invitations.filter(invitation => invitation.targetType === this.query.targetType);
30542
+ }
30543
+ if (this.query.type) {
30544
+ invitations = invitations.filter(invitation => invitation.type === this.query.type);
30545
+ }
30546
+ const sortFn = (() => {
30547
+ switch (this.query.sortBy) {
30548
+ case 'firstCreated':
30549
+ return sortByFirstCreated;
30550
+ case 'lastCreated':
30551
+ return sortByLastCreated;
30552
+ default:
30553
+ return sortByLastCreated;
30554
+ }
30555
+ })();
30556
+ invitations = invitations.sort(sortFn);
30557
+ return invitations;
30490
30558
  }
30491
- // Convert PKCS1 to PKCS8 (crypto.subtle requires PKCS8)
30492
- const pkcs8 = pkcs1ToPkcs8(pkcs1);
30493
- // Import the key
30494
- const key = await crypto.subtle.importKey(PRIVATE_KEY_SIGNATURE, pkcs8.buffer, ALGORITHM, false, ['sign']);
30495
- return key;
30496
- }
30497
- async function createSignature({ timestamp, rooms, }) {
30498
- const dataStr = rooms
30499
- .map(item => Object.keys(item)
30500
- .sort()
30501
- .map(key => `${key}=${item[key]}`)
30502
- .join('&'))
30503
- .join(';');
30504
- /*
30505
- * nonceStr needs to be unique for each request
30506
- */
30507
- const nonceStr = uuid$1.v4();
30508
- const signStr = `nonceStr=${nonceStr}&timestamp=${timestamp}&data=${dataStr}==`;
30509
- const encoder = new TextEncoder();
30510
- const data = encoder.encode(signStr);
30511
- const key = await importPrivateKey(privateKey);
30512
- const sign = await crypto.subtle.sign(ALGORITHM, key, data);
30513
- return { signature: base64FromArrayBuffer(sign), nonceStr };
30514
30559
  }
30515
30560
 
30516
30561
  /**
30517
- * Sync pending watch sessions to backend
30518
- * This function implements the full sync flow with network resilience
30562
+ * Get invitations
30563
+ *
30564
+ * @param params the query parameters
30565
+ * @param callback the callback to be called when the invitations are updated
30566
+ * @returns invitations
30567
+ *
30568
+ * @category Invitation Live Collection
30569
+ *
30519
30570
  */
30520
- async function syncWatchSessions() {
30521
- const storage = getWatchSessionStorage();
30522
- // Get all pending sessions
30523
- const pendingSessions = storage.getPendingSessions();
30524
- if (pendingSessions.length === 0) {
30525
- return true;
30571
+ const getInvitations$1 = (params, callback, config) => {
30572
+ const { log, cache } = getActiveClient();
30573
+ if (!cache) {
30574
+ console.log(ENABLE_CACHE_MESSAGE);
30526
30575
  }
30527
- try {
30528
- const timestamp = new Date().toISOString();
30529
- // Convert sessions to API format - always include all fields like syncUsage does
30530
- const rooms = pendingSessions.map(session => ({
30531
- sessionId: session.sessionId,
30532
- roomId: session.roomId,
30533
- watchSeconds: session.watchSeconds,
30534
- startTime: session.startTime.toISOString(),
30535
- endTime: session.endTime ? session.endTime.toISOString() : '',
30536
- }));
30537
- // Create signature (reuse from stream feature) - pass directly like syncUsage
30538
- const signatureData = await createSignature({
30539
- timestamp,
30540
- rooms,
30541
- });
30542
- if (!signatureData || !signatureData.signature) {
30543
- throw new Error('Signature is undefined');
30544
- }
30545
- // Update sync state to SYNCING
30546
- pendingSessions.forEach(session => {
30547
- storage.updateSession(session.sessionId, { syncState: 'SYNCING' });
30548
- });
30549
- const payload = {
30550
- signature: signatureData.signature,
30551
- nonceStr: signatureData.nonceStr,
30552
- timestamp,
30553
- rooms,
30554
- };
30555
- const client = getActiveClient();
30556
- // Send to backend
30557
- await client.http.post('/api/v3/user-event/room', payload);
30558
- // Success - update to SYNCED
30559
- pendingSessions.forEach(session => {
30560
- storage.updateSession(session.sessionId, {
30561
- syncState: 'SYNCED',
30562
- syncedAt: new Date(),
30576
+ const timestamp = Date.now();
30577
+ log(`getInvitations: (tmpid: ${timestamp}) > listen`);
30578
+ const invitationsLiveCollection = new InvitationsLiveCollectionController(params, callback);
30579
+ const disposers = invitationsLiveCollection.startSubscription();
30580
+ const cacheKey = invitationsLiveCollection.getCacheKey();
30581
+ disposers.push(() => {
30582
+ dropFromCache(cacheKey);
30583
+ });
30584
+ return () => {
30585
+ log(`getInvitations (tmpid: ${timestamp}) > dispose`);
30586
+ disposers.forEach(fn => fn());
30587
+ };
30588
+ };
30589
+
30590
+ const categoryLinkedObject = (category) => {
30591
+ return Object.assign(Object.assign({}, category), { get avatar() {
30592
+ var _a;
30593
+ if (!category.avatarFileId)
30594
+ return undefined;
30595
+ const avatar = (_a = pullFromCache([
30596
+ 'file',
30597
+ 'get',
30598
+ `${category.avatarFileId}`,
30599
+ ])) === null || _a === void 0 ? void 0 : _a.data;
30600
+ return avatar;
30601
+ } });
30602
+ };
30603
+
30604
+ const communityLinkedObject = (community) => {
30605
+ return Object.assign(Object.assign({}, community), { get categories() {
30606
+ var _a;
30607
+ return ((_a = community === null || community === void 0 ? void 0 : community.categoryIds) !== null && _a !== void 0 ? _a : [])
30608
+ .map(categoryId => {
30609
+ const cacheData = pullFromCache(['category', 'get', categoryId]);
30610
+ if (cacheData === null || cacheData === void 0 ? void 0 : cacheData.data)
30611
+ return categoryLinkedObject(cacheData.data);
30612
+ return undefined;
30613
+ })
30614
+ .filter(category => !!category);
30615
+ },
30616
+ get avatar() {
30617
+ var _a;
30618
+ if (!community.avatarFileId)
30619
+ return undefined;
30620
+ const avatar = (_a = pullFromCache([
30621
+ 'file',
30622
+ 'get',
30623
+ community.avatarFileId,
30624
+ ])) === null || _a === void 0 ? void 0 : _a.data;
30625
+ return avatar;
30626
+ }, createInvitations: async (userIds) => {
30627
+ await createInvitations({
30628
+ type: "communityMemberInvite" /* InvitationTypeEnum.CommunityMemberInvite */,
30629
+ targetType: 'community',
30630
+ targetId: community.communityId,
30631
+ userIds,
30563
30632
  });
30564
- });
30565
- return true;
30633
+ }, getMemberInvitations: (params, callback) => {
30634
+ return getInvitations$1(Object.assign(Object.assign({}, params), { targetId: community.communityId, targetType: 'community', type: "communityMemberInvite" /* InvitationTypeEnum.CommunityMemberInvite */ }), callback);
30635
+ }, getInvitation: async () => {
30636
+ const { data } = await getInvitation({
30637
+ targetType: 'community',
30638
+ targetId: community.communityId,
30639
+ });
30640
+ return data;
30641
+ }, join: async () => joinRequest(community.communityId), getJoinRequests: (params, callback) => {
30642
+ return getJoinRequests(Object.assign(Object.assign({}, params), { communityId: community.communityId }), callback);
30643
+ }, getMyJoinRequest: async () => {
30644
+ const { data } = await getMyJoinRequest(community.communityId);
30645
+ return data;
30646
+ } });
30647
+ };
30648
+
30649
+ class StoryComputedValue {
30650
+ constructor(targetId, lastStoryExpiresAt, lastStorySeenExpiresAt) {
30651
+ this._syncingStoriesCount = 0;
30652
+ this._errorStoriesCount = 0;
30653
+ this._targetId = targetId;
30654
+ this._lastStoryExpiresAt = lastStoryExpiresAt;
30655
+ this._lastStorySeenExpiresAt = lastStorySeenExpiresAt;
30656
+ this.cacheStoryExpireTime = pullFromCache([
30657
+ "story-expire" /* STORY_KEY_CACHE.EXPIRE */,
30658
+ this._targetId,
30659
+ ]);
30660
+ this.cacheStoreSeenTime = pullFromCache([
30661
+ "story-last-seen" /* STORY_KEY_CACHE.LAST_SEEN */,
30662
+ this._targetId,
30663
+ ]);
30664
+ this.getTotalStoryByStatus();
30566
30665
  }
30567
- catch (err) {
30568
- console.error('[SDK syncWatchSessions] ERROR caught:', (err === null || err === void 0 ? void 0 : err.message) || err);
30569
- // Failure - update back to PENDING and increment retry count
30570
- pendingSessions.forEach(session => {
30571
- const currentSession = storage.getSession(session.sessionId);
30572
- if (currentSession) {
30573
- const newRetryCount = currentSession.retryCount + 1;
30574
- if (newRetryCount >= 3) {
30575
- // Delete session if retry count exceeds 3
30576
- storage.deleteSession(session.sessionId);
30577
- }
30578
- else {
30579
- // Update to PENDING with incremented retry count
30580
- storage.updateSession(session.sessionId, {
30581
- syncState: 'PENDING',
30582
- retryCount: newRetryCount,
30583
- });
30584
- }
30585
- }
30586
- });
30587
- return false;
30666
+ get lastStoryExpiresAt() {
30667
+ return this._lastStoryExpiresAt ? new Date(this._lastStoryExpiresAt).getTime() : 0;
30668
+ }
30669
+ get lastStorySeenExpiresAt() {
30670
+ return this._lastStorySeenExpiresAt ? new Date(this._lastStorySeenExpiresAt).getTime() : 0;
30671
+ }
30672
+ get localLastStoryExpires() {
30673
+ var _a, _b;
30674
+ return ((_a = this.cacheStoryExpireTime) === null || _a === void 0 ? void 0 : _a.data)
30675
+ ? new Date((_b = this.cacheStoryExpireTime) === null || _b === void 0 ? void 0 : _b.data).getTime()
30676
+ : 0;
30677
+ }
30678
+ get localLastStorySeenExpiresAt() {
30679
+ var _a, _b;
30680
+ return ((_a = this.cacheStoreSeenTime) === null || _a === void 0 ? void 0 : _a.data) ? new Date((_b = this.cacheStoreSeenTime) === null || _b === void 0 ? void 0 : _b.data).getTime() : 0;
30681
+ }
30682
+ get isContainUnSyncedStory() {
30683
+ const currentSyncingState = pullFromCache([
30684
+ "story-sync-state" /* STORY_KEY_CACHE.SYNC_STATE */,
30685
+ this._targetId,
30686
+ ]);
30687
+ if (!(currentSyncingState === null || currentSyncingState === void 0 ? void 0 : currentSyncingState.data))
30688
+ return false;
30689
+ return ["syncing" /* Amity.SyncState.Syncing */, "error" /* Amity.SyncState.Error */].includes(currentSyncingState.data);
30588
30690
  }
30589
- }
30590
-
30591
- /**
30592
- * Room statuses that are considered watchable
30593
- */
30594
- const WATCHABLE_ROOM_STATUSES = ['live', 'recorded'];
30595
- /**
30596
- * Generate a random jitter delay between 5 and 30 seconds
30597
- */
30598
- const getJitterDelay = () => {
30599
- const minDelay = 5000; // 5 seconds
30600
- const maxDelay = 30000; // 30 seconds
30601
- return Math.floor(Math.random() * (maxDelay - minDelay + 1)) + minDelay;
30602
- };
30603
- /**
30604
- * Wait for network connection with timeout
30605
- * @param maxWaitTime Maximum time to wait in milliseconds (default: 60000 = 60 seconds)
30606
- * @returns Promise that resolves when network is available or timeout is reached
30607
- */
30608
- const waitForNetwork = (maxWaitTime = 60000) => {
30609
- return new Promise(resolve => {
30610
- // Simple check - if navigator.onLine is available, use it
30611
- // Otherwise, assume network is available
30612
- if (typeof navigator === 'undefined' || typeof navigator.onLine === 'undefined') {
30613
- resolve();
30614
- return;
30691
+ getLocalLastSortingDate() {
30692
+ if (this.isContainUnSyncedStory) {
30693
+ return this.localLastStoryExpires;
30615
30694
  }
30616
- const startTime = Date.now();
30617
- const checkInterval = 1000; // 1 second
30618
- const checkConnection = () => {
30619
- if (navigator.onLine || Date.now() - startTime >= maxWaitTime) {
30620
- resolve();
30621
- }
30622
- else {
30623
- setTimeout(checkConnection, checkInterval);
30624
- }
30625
- };
30626
- checkConnection();
30627
- });
30628
- };
30629
- /**
30630
- * AmityRoomAnalytics provides analytics capabilities for room watch sessions
30631
- */
30632
- class AmityRoomAnalytics {
30633
- constructor(room) {
30634
- this.storage = getWatchSessionStorage();
30635
- this.client = getActiveClient();
30636
- this.room = room;
30695
+ return this.lastStoryExpiresAt;
30637
30696
  }
30638
- /**
30639
- * Create a new watch session for the current room
30640
- * @param startedAt The timestamp when watching started
30641
- * @returns Promise<string> sessionId unique identifier for this watch session
30642
- * @throws ASCApiError if room is not in watchable state (not LIVE or RECORDED)
30643
- */
30644
- async createWatchSession(startedAt) {
30645
- // Validate room status
30646
- if (!WATCHABLE_ROOM_STATUSES.includes(this.room.status)) {
30647
- throw new ASCApiError('room is not in watchable state', 500000 /* Amity.ServerError.BUSINESS_ERROR */, "error" /* Amity.ErrorLevel.ERROR */);
30697
+ getHasUnseenFlag() {
30698
+ const now = new Date().getTime();
30699
+ const highestSeen = Math.max(this.lastStorySeenExpiresAt, this.localLastStorySeenExpiresAt);
30700
+ pullFromCache([
30701
+ "story-sync-state" /* STORY_KEY_CACHE.SYNC_STATE */,
30702
+ this._targetId,
30703
+ ]);
30704
+ if (this.isContainUnSyncedStory) {
30705
+ return this.localLastStoryExpires > now && this.localLastStoryExpires > highestSeen;
30648
30706
  }
30649
- // Generate session ID with prefix
30650
- const prefix = this.room.status === 'live' ? 'room_' : 'room_playback_';
30651
- const sessionId = prefix + uuid$1.v4();
30652
- // Create watch session entity
30653
- const session = {
30654
- sessionId,
30655
- roomId: this.room.roomId,
30656
- watchSeconds: 0,
30657
- startTime: startedAt,
30658
- endTime: null,
30659
- syncState: 'PENDING',
30660
- syncedAt: null,
30661
- retryCount: 0,
30662
- };
30663
- // Persist to storage
30664
- this.storage.addSession(session);
30665
- return sessionId;
30707
+ return this.lastStoryExpiresAt > now && this.lastStoryExpiresAt > highestSeen;
30666
30708
  }
30667
- /**
30668
- * Update an existing watch session with duration
30669
- * @param sessionId The unique identifier of the watch session
30670
- * @param duration The total watch duration in seconds
30671
- * @param endedAt The timestamp when this update occurred
30672
- * @returns Promise<void> Completion status
30673
- */
30674
- async updateWatchSession(sessionId, duration, endedAt) {
30675
- const session = this.storage.getSession(sessionId);
30676
- if (!session) {
30677
- throw new Error(`Watch session ${sessionId} not found`);
30709
+ getTotalStoryByStatus() {
30710
+ const stories = queryCache(["story" /* STORY_KEY_CACHE.STORY */, 'get']);
30711
+ if (!stories) {
30712
+ this._errorStoriesCount = 0;
30713
+ this._syncingStoriesCount = 0;
30714
+ return;
30678
30715
  }
30679
- // Update session
30680
- this.storage.updateSession(sessionId, {
30681
- watchSeconds: duration,
30682
- endTime: endedAt,
30716
+ const groupByType = stories.reduce((acc, story) => {
30717
+ const { data: { targetId, syncState, isDeleted }, } = story;
30718
+ if (targetId === this._targetId && !isDeleted) {
30719
+ acc[syncState] += 1;
30720
+ }
30721
+ return acc;
30722
+ }, {
30723
+ syncing: 0,
30724
+ error: 0,
30725
+ synced: 0,
30683
30726
  });
30727
+ this._errorStoriesCount = groupByType.error;
30728
+ this._syncingStoriesCount = groupByType.syncing;
30684
30729
  }
30685
- /**
30686
- * Sync all pending watch sessions to backend
30687
- * This function uses jitter delay and handles network resilience
30688
- */
30689
- syncPendingWatchSessions() {
30690
- // Execute with jitter delay (5-30 seconds)
30691
- const jitterDelay = getJitterDelay();
30692
- this.client.log('room/RoomAnalytics: syncPendingWatchSessions called, jitter delay:', `${jitterDelay}ms`);
30693
- setTimeout(async () => {
30694
- this.client.log('room/RoomAnalytics: Jitter delay completed, starting sync process');
30695
- try {
30696
- // Reset any SYNCING sessions back to PENDING
30697
- const syncingSessions = this.storage.getSyncingSessions();
30698
- this.client.log('room/RoomAnalytics: SYNCING sessions to reset:', syncingSessions.length);
30699
- syncingSessions.forEach(session => {
30700
- this.storage.updateSession(session.sessionId, { syncState: 'PENDING' });
30701
- });
30702
- // Wait for network connection (max 60 seconds)
30703
- await waitForNetwork(60000);
30704
- this.client.log('room/RoomAnalytics: Network available');
30705
- // Sync pending sessions
30706
- this.client.log('room/RoomAnalytics: Calling syncWatchSessions()');
30707
- await syncWatchSessions();
30708
- this.client.log('room/RoomAnalytics: syncWatchSessions completed');
30709
- }
30710
- catch (error) {
30711
- // Error is already handled in syncWatchSessions
30712
- console.error('Failed to sync watch sessions:', error);
30713
- }
30714
- }, jitterDelay);
30730
+ get syncingStoriesCount() {
30731
+ return this._syncingStoriesCount;
30732
+ }
30733
+ get failedStoriesCount() {
30734
+ return this._errorStoriesCount;
30715
30735
  }
30716
30736
  }
30717
30737
 
30718
- const roomLinkedObject = (room) => {
30719
- return Object.assign(Object.assign({}, room), { get post() {
30720
- var _a;
30721
- if (room.referenceType !== 'post')
30722
- return;
30723
- return (_a = pullFromCache(['post', 'get', room.referenceId])) === null || _a === void 0 ? void 0 : _a.data;
30738
+ const storyTargetLinkedObject = (storyTarget) => {
30739
+ const { targetType, targetId, lastStoryExpiresAt, lastStorySeenExpiresAt, targetUpdatedAt, localFilter, } = storyTarget;
30740
+ const computedValue = new StoryComputedValue(targetId, lastStoryExpiresAt, lastStorySeenExpiresAt);
30741
+ return {
30742
+ targetType,
30743
+ targetId,
30744
+ lastStoryExpiresAt,
30745
+ updatedAt: targetUpdatedAt,
30746
+ // Additional data
30747
+ hasUnseen: computedValue.getHasUnseenFlag(),
30748
+ syncingStoriesCount: computedValue.syncingStoriesCount,
30749
+ failedStoriesCount: computedValue.failedStoriesCount,
30750
+ localFilter,
30751
+ localLastExpires: computedValue.localLastStoryExpires,
30752
+ localLastSeen: computedValue.localLastStorySeenExpiresAt,
30753
+ localSortingDate: computedValue.getLocalLastSortingDate(),
30754
+ };
30755
+ };
30756
+
30757
+ const storyLinkedObject = (story) => {
30758
+ const analyticsEngineInstance = AnalyticsEngine$1.getInstance();
30759
+ const storyTargetCache = pullFromCache([
30760
+ "storyTarget" /* STORY_KEY_CACHE.STORY_TARGET */,
30761
+ 'get',
30762
+ story.targetId,
30763
+ ]);
30764
+ const communityCacheData = pullFromCache(['community', 'get', story.targetId]);
30765
+ return Object.assign(Object.assign({}, story), { analytics: {
30766
+ markAsSeen: () => {
30767
+ if (!story.expiresAt)
30768
+ return;
30769
+ if (story.syncState !== "synced" /* Amity.SyncState.Synced */)
30770
+ return;
30771
+ analyticsEngineInstance.markStoryAsViewed(story);
30772
+ },
30773
+ markLinkAsClicked: () => {
30774
+ if (!story.expiresAt)
30775
+ return;
30776
+ if (story.syncState !== "synced" /* Amity.SyncState.Synced */)
30777
+ return;
30778
+ analyticsEngineInstance.markStoryAsClicked(story);
30779
+ },
30780
+ }, get videoData() {
30781
+ var _a, _b;
30782
+ const cache = pullFromCache([
30783
+ 'file',
30784
+ 'get',
30785
+ (_b = (_a = story.data) === null || _a === void 0 ? void 0 : _a.videoFileId) === null || _b === void 0 ? void 0 : _b.original,
30786
+ ]);
30787
+ if (!cache)
30788
+ return undefined;
30789
+ const { data } = cache;
30790
+ return data || undefined;
30791
+ },
30792
+ get imageData() {
30793
+ var _a, _b;
30794
+ if (!((_a = story.data) === null || _a === void 0 ? void 0 : _a.fileId))
30795
+ return undefined;
30796
+ const cache = pullFromCache(['file', 'get', (_b = story.data) === null || _b === void 0 ? void 0 : _b.fileId]);
30797
+ if (!cache)
30798
+ return undefined;
30799
+ const { data } = cache;
30800
+ if (!data)
30801
+ return undefined;
30802
+ return Object.assign(Object.assign({}, data), { fileUrl: `${data.fileUrl}?size=full` });
30724
30803
  },
30725
30804
  get community() {
30726
- var _a;
30727
- if (room.targetType !== 'community')
30805
+ if (story.targetType !== 'community')
30806
+ return undefined;
30807
+ if (!(communityCacheData === null || communityCacheData === void 0 ? void 0 : communityCacheData.data))
30808
+ return undefined;
30809
+ return communityLinkedObject(communityCacheData.data);
30810
+ },
30811
+ get communityCategories() {
30812
+ if (story.targetType !== 'community')
30813
+ return undefined;
30814
+ if (!communityCacheData)
30815
+ return undefined;
30816
+ const { data: { categoryIds }, } = communityCacheData;
30817
+ if (categoryIds.length === 0)
30818
+ return undefined;
30819
+ return categoryIds
30820
+ .map(categoryId => {
30821
+ const categoryCacheData = pullFromCache(['category', 'get', categoryId]);
30822
+ return (categoryCacheData === null || categoryCacheData === void 0 ? void 0 : categoryCacheData.data) || undefined;
30823
+ })
30824
+ .filter(category => category !== undefined);
30825
+ },
30826
+ get creator() {
30827
+ const cacheData = pullFromCache(['user', 'get', story.creatorPublicId]);
30828
+ if (!(cacheData === null || cacheData === void 0 ? void 0 : cacheData.data))
30728
30829
  return;
30729
- return (_a = pullFromCache(['community', 'get', room.targetId])) === null || _a === void 0 ? void 0 : _a.data;
30830
+ return userLinkedObject(cacheData.data);
30730
30831
  },
30731
- get user() {
30732
- var _a;
30733
- const user = (_a = pullFromCache(['user', 'get', room.createdBy])) === null || _a === void 0 ? void 0 : _a.data;
30734
- return user ? userLinkedObject(user) : user;
30832
+ get storyTarget() {
30833
+ if (!(storyTargetCache === null || storyTargetCache === void 0 ? void 0 : storyTargetCache.data))
30834
+ return;
30835
+ return storyTargetLinkedObject(storyTargetCache.data);
30735
30836
  },
30736
- get childRooms() {
30737
- if (!room.childRoomIds || room.childRoomIds.length === 0)
30738
- return [];
30739
- return room.childRoomIds
30740
- .map(id => {
30741
- var _a;
30742
- const roomCache = (_a = pullFromCache(['room', 'get', id])) === null || _a === void 0 ? void 0 : _a.data;
30743
- if (!roomCache)
30744
- return undefined;
30745
- return roomLinkedObject(roomCache);
30746
- })
30747
- .filter(isNonNullable);
30748
- }, participants: room.participants.map(participant => (Object.assign(Object.assign({}, participant), { get user() {
30749
- var _a;
30750
- const user = (_a = pullFromCache(['user', 'get', participant.userId])) === null || _a === void 0 ? void 0 : _a.data;
30751
- return user ? userLinkedObject(user) : user;
30752
- } }))), getLiveChat: () => getLiveChat(room), createInvitation: (userId) => createInvitations({
30753
- type: "livestreamCohostInvite" /* InvitationTypeEnum.LivestreamCohostInvite */,
30754
- targetType: 'room',
30755
- targetId: room.roomId,
30756
- userIds: [userId],
30757
- }), getInvitations: async () => {
30758
- const { data } = await getInvitation({
30759
- targetId: room.roomId,
30760
- targetType: 'room',
30761
- type: "livestreamCohostInvite" /* InvitationTypeEnum.LivestreamCohostInvite */,
30762
- });
30763
- return data;
30764
- }, analytics() {
30765
- // Use 'this' to avoid creating a new room object
30766
- return new AmityRoomAnalytics(this);
30837
+ get isSeen() {
30838
+ const cacheData = pullFromCache(["story-last-seen" /* STORY_KEY_CACHE.LAST_SEEN */, story.targetId]);
30839
+ if (!(storyTargetCache === null || storyTargetCache === void 0 ? void 0 : storyTargetCache.data))
30840
+ return false;
30841
+ const localLastSeen = (cacheData === null || cacheData === void 0 ? void 0 : cacheData.data) ? new Date(cacheData.data).getTime() : 0;
30842
+ const serverLastSeen = new Date(storyTargetCache === null || storyTargetCache === void 0 ? void 0 : storyTargetCache.data.lastStorySeenExpiresAt).getTime() || 0;
30843
+ const expiresAt = new Date(story.expiresAt).getTime();
30844
+ return Math.max(localLastSeen, serverLastSeen) >= expiresAt;
30767
30845
  } });
30768
30846
  };
30769
30847
 
30770
- const pollLinkedObject = (poll) => {
30771
- return Object.assign(Object.assign({}, poll), { answers: poll.answers.map(answer => (Object.assign(Object.assign({}, answer), { get image() {
30772
- var _a;
30773
- if (!answer.fileId)
30774
- return undefined;
30775
- return (_a = pullFromCache(['file', 'get', answer.fileId])) === null || _a === void 0 ? void 0 : _a.data;
30776
- } }))) });
30777
- };
30778
-
30779
- /*
30780
- * verifies membership status
30781
- */
30782
- function isMember(membership) {
30783
- return membership !== 'none';
30784
- }
30785
- /*
30786
- * checks if currently logged in user is part of the community
30787
- */
30788
- function isCurrentUserPartOfCommunity(c, m) {
30789
- const { userId } = getActiveUser();
30790
- return c.communityId === m.communityId && m.userId === userId;
30791
- }
30792
- /*
30793
- * For mqtt events server will not send user specific data as it's broadcasted
30794
- * to multiple users and it also does not include communityUser
30795
- *
30796
- * Client SDK needs to check for the existing isJoined field in cache data before calculating.
30797
- * Althought this can be calculated, it's not scalable.
30798
- */
30799
- function updateMembershipStatus(communities, communityUsers) {
30800
- return communities.map(c => {
30801
- const cachedCommunity = pullFromCache([
30802
- 'community',
30803
- 'get',
30804
- c.communityId,
30805
- ]);
30806
- if ((cachedCommunity === null || cachedCommunity === void 0 ? void 0 : cachedCommunity.data) && (cachedCommunity === null || cachedCommunity === void 0 ? void 0 : cachedCommunity.data.hasOwnProperty('isJoined'))) {
30807
- return Object.assign(Object.assign({}, cachedCommunity.data), c);
30808
- }
30809
- const isJoined = c.isJoined !== undefined
30810
- ? c.isJoined
30811
- : communityUsers.some(m => isCurrentUserPartOfCommunity(c, m) && isMember(m.communityMembership));
30812
- return Object.assign(Object.assign({}, c), { isJoined });
30813
- });
30814
- }
30815
-
30816
- const getMatchPostSetting = (value) => {
30817
- var _a;
30818
- return (_a = Object.keys(CommunityPostSettingMaps).find(key => value.needApprovalOnPostCreation ===
30819
- CommunityPostSettingMaps[key].needApprovalOnPostCreation &&
30820
- value.onlyAdminCanPost === CommunityPostSettingMaps[key].onlyAdminCanPost)) !== null && _a !== void 0 ? _a : DefaultCommunityPostSetting;
30821
- };
30822
- function addPostSetting({ communities }) {
30823
- return communities.map((_a) => {
30824
- var { needApprovalOnPostCreation, onlyAdminCanPost } = _a, restCommunityPayload = __rest(_a, ["needApprovalOnPostCreation", "onlyAdminCanPost"]);
30825
- return (Object.assign({ postSetting: getMatchPostSetting({
30826
- needApprovalOnPostCreation,
30827
- onlyAdminCanPost,
30828
- }) }, restCommunityPayload));
30829
- });
30830
- }
30831
- const prepareCommunityPayload = (rawPayload) => {
30832
- const communitiesWithPostSetting = addPostSetting({ communities: rawPayload.communities });
30833
- // Convert users to internal format
30834
- const internalUsers = rawPayload.users.map(convertRawUserToInternalUser);
30835
- // map users with community
30836
- const mappedCommunityUsers = rawPayload.communityUsers.map(communityUser => {
30837
- const user = internalUsers.find(user => user.userId === communityUser.userId);
30838
- return Object.assign(Object.assign({}, communityUser), { user });
30839
- });
30840
- const communityWithMembershipStatus = updateMembershipStatus(communitiesWithPostSetting, mappedCommunityUsers);
30841
- return Object.assign(Object.assign({}, rawPayload), { users: rawPayload.users.map(convertRawUserToInternalUser), communities: communityWithMembershipStatus, communityUsers: mappedCommunityUsers });
30842
- };
30843
- const prepareCommunityJoinRequestPayload = (rawPayload) => {
30844
- const mappedJoinRequests = rawPayload.joinRequests.map(joinRequest => {
30845
- return Object.assign(Object.assign({}, joinRequest), { joinRequestId: joinRequest._id });
30846
- });
30847
- const users = rawPayload.users.map(convertRawUserToInternalUser);
30848
- return Object.assign(Object.assign({}, rawPayload), { joinRequests: mappedJoinRequests, users });
30849
- };
30850
- const prepareCommunityMembershipPayload = (rawPayload) => {
30851
- const communitiesWithPostSetting = addPostSetting({ communities: rawPayload.communities });
30852
- // map users with community
30853
- const mappedCommunityUsers = rawPayload.communityUsers.map(communityUser => {
30854
- const user = rawPayload.users.find(user => user.userId === communityUser.userId);
30855
- return Object.assign(Object.assign({}, communityUser), { user });
30856
- });
30857
- const communityWithMembershipStatus = updateMembershipStatus(communitiesWithPostSetting, mappedCommunityUsers);
30858
- return Object.assign(Object.assign({}, rawPayload), { communities: communityWithMembershipStatus, communityUsers: mappedCommunityUsers });
30859
- };
30860
- const prepareCommunityRequest = (params) => {
30861
- const { postSetting = undefined, storySetting } = params, restParam = __rest(params, ["postSetting", "storySetting"]);
30862
- return Object.assign(Object.assign(Object.assign({}, restParam), (postSetting ? CommunityPostSettingMaps[postSetting] : undefined)), {
30863
- // Convert story setting to the actual value. (Allow by default)
30864
- allowCommentInStory: typeof (storySetting === null || storySetting === void 0 ? void 0 : storySetting.enableComment) === 'boolean' ? storySetting.enableComment : true });
30865
- };
30866
- const prepareSemanticSearchCommunityPayload = (_a) => {
30867
- var communityPayload = __rest(_a, ["searchResult"]);
30868
- const processedCommunityPayload = prepareCommunityPayload(communityPayload);
30869
- return Object.assign({}, processedCommunityPayload);
30870
- };
30871
-
30872
30848
  /* begin_public_function
30873
- id: joinRequest.approve
30849
+ id: channel.create
30874
30850
  */
30875
30851
  /**
30876
30852
  * ```js
30877
- * import { joinRequest } from '@amityco/ts-sdk-react-native'
30878
- * const isAccepted = await joinRequest.approve()
30853
+ * import { createChannel } from '@amityco/ts-sdk-react-native'
30854
+ * const created = await createChannel({ displayName: 'foobar' })
30879
30855
  * ```
30880
30856
  *
30881
- * Accepts a {@link Amity.JoinRequest} object
30857
+ * Creates an {@link Amity.Channel}
30882
30858
  *
30883
- * @param joinRequest the {@link Amity.JoinRequest} to accept
30884
- * @returns A success boolean if the {@link Amity.JoinRequest} was accepted
30859
+ * @param bundle The data necessary to create a new {@link Amity.Channel}
30860
+ * @returns The newly created {@link Amity.Channel}
30885
30861
  *
30886
- * @category Join Request API
30862
+ * @category Channel API
30887
30863
  * @async
30888
30864
  */
30889
- const approveJoinRequest = async (joinRequest) => {
30890
- var _a;
30865
+ const createChannel = async (bundle) => {
30891
30866
  const client = getActiveClient();
30892
- client.log('joinRequest/approveJoinRequest', joinRequest.joinRequestId);
30893
- const { data } = await client.http.post(`/api/v4/communities/${joinRequest.targetId}/join/approve`, {
30894
- userId: joinRequest.requestorInternalId,
30895
- });
30896
- const joinRequestCache = (_a = pullFromCache([
30897
- 'joinRequest',
30898
- 'get',
30899
- joinRequest.joinRequestId,
30900
- ])) === null || _a === void 0 ? void 0 : _a.data;
30901
- if (joinRequestCache) {
30902
- upsertInCache(['joinRequest', 'get', joinRequest.joinRequestId], {
30903
- status: "approved" /* JoinRequestStatusEnum.Approved */,
30904
- });
30905
- fireEvent('local.joinRequest.updated', [joinRequestCache]);
30867
+ client.log('user/createChannel', bundle);
30868
+ let payload;
30869
+ /* c8 ignore next */
30870
+ if ((bundle === null || bundle === void 0 ? void 0 : bundle.type) === 'conversation') {
30871
+ payload = await client.http.post('/api/v3/channels/conversation', Object.assign(Object.assign({}, bundle), { isDistinct: true }));
30906
30872
  }
30907
- return data.success;
30873
+ else {
30874
+ const { isPublic } = bundle, restParams = __rest(bundle, ["isPublic"]);
30875
+ payload = await client.http.post('/api/v3/channels', Object.assign(Object.assign({}, restParams), {
30876
+ /* c8 ignore next */
30877
+ isPublic: (bundle === null || bundle === void 0 ? void 0 : bundle.type) === 'community' ? isPublic : undefined }));
30878
+ }
30879
+ const data = await prepareChannelPayload(payload.data);
30880
+ const cachedAt = client.cache && Date.now();
30881
+ if (client.cache)
30882
+ ingestInCache(data, { cachedAt });
30883
+ const { channels } = data;
30884
+ return {
30885
+ data: constructChannelObject(channels[0]),
30886
+ cachedAt,
30887
+ };
30908
30888
  };
30909
30889
  /* end_public_function */
30910
30890
 
30911
- /* begin_public_function
30912
- id: joinRequest.cancel
30913
- */
30914
30891
  /**
30915
30892
  * ```js
30916
- * import { joinRequest } from '@amityco/ts-sdk-react-native'
30917
- * const isCanceled = await joinRequest.cancel()
30893
+ * import { getChannel } from '@amityco/ts-sdk-react-native'
30894
+ * const channel = await getChannel('foobar')
30918
30895
  * ```
30919
30896
  *
30920
- * Cancels a {@link Amity.JoinRequest} object
30897
+ * Fetches a {@link Amity.Channel} object
30921
30898
  *
30922
- * @param joinRequest the {@link Amity.JoinRequest} to cancel
30923
- * @returns A success boolean if the {@link Amity.JoinRequest} was canceled
30899
+ * @param channelId the ID of the {@link Amity.Channel} to fetch
30900
+ * @returns the associated {@link Amity.Channel} object
30924
30901
  *
30925
- * @category Join Request API
30902
+ * @category Channel API
30926
30903
  * @async
30927
30904
  */
30928
- const cancelJoinRequest = async (joinRequest) => {
30929
- var _a;
30905
+ const getChannel$1 = async (channelId) => {
30930
30906
  const client = getActiveClient();
30931
- client.log('joinRequest/cancelJoinRequest', joinRequest.joinRequestId);
30932
- const { data } = await client.http.delete(`/api/v4/communities/${joinRequest.targetId}/join`);
30933
- const joinRequestCache = (_a = pullFromCache([
30934
- 'joinRequest',
30935
- 'get',
30936
- joinRequest.joinRequestId,
30937
- ])) === null || _a === void 0 ? void 0 : _a.data;
30938
- if (joinRequestCache) {
30939
- upsertInCache(['joinRequest', 'get', joinRequest.joinRequestId], {
30940
- status: "cancelled" /* JoinRequestStatusEnum.Cancelled */,
30941
- });
30942
- fireEvent('local.joinRequest.deleted', [joinRequestCache]);
30907
+ client.log('channel/getChannel', channelId);
30908
+ isInTombstone('channel', channelId);
30909
+ let data;
30910
+ try {
30911
+ const { data: payload } = await client.http.get(`/api/v3/channels/${encodeURIComponent(channelId)}`);
30912
+ data = await prepareChannelPayload(payload);
30913
+ if (client.isUnreadCountEnabled && client.getMarkerSyncConsistentMode()) {
30914
+ prepareUnreadCountInfo(payload);
30915
+ }
30943
30916
  }
30944
- return data.success;
30917
+ catch (error) {
30918
+ if (checkIfShouldGoesToTombstone(error === null || error === void 0 ? void 0 : error.code)) {
30919
+ // NOTE: use channelPublicId as tombstone cache key since we cannot get the channelPrivateId that come along with channel data from server
30920
+ pushToTombstone('channel', channelId);
30921
+ }
30922
+ throw error;
30923
+ }
30924
+ const cachedAt = client.cache && Date.now();
30925
+ if (client.cache)
30926
+ ingestInCache(data, { cachedAt });
30927
+ const { channels } = data;
30928
+ return {
30929
+ data: channels.find(channel => channel.channelId === channelId),
30930
+ cachedAt,
30931
+ };
30945
30932
  };
30946
- /* end_public_function */
30947
-
30948
- /* begin_public_function
30949
- id: joinRequest.reject
30950
- */
30951
30933
  /**
30952
30934
  * ```js
30953
- * import { joinRequest } from '@amityco/ts-sdk-react-native'
30954
- * const isRejected = await joinRequest.reject()
30935
+ * import { getChannel } from '@amityco/ts-sdk-react-native'
30936
+ * const channel = getChannel.locally('foobar')
30955
30937
  * ```
30956
30938
  *
30957
- * Rejects a {@link Amity.JoinRequest} object
30939
+ * Fetches a {@link Amity.Channel} object from cache
30958
30940
  *
30959
- * @param joinRequest the {@link Amity.JoinRequest} to reject
30960
- * @returns A success boolean if the {@link Amity.JoinRequest} was rejected
30941
+ * @param channelId the ID of the {@link Amity.Channel} to fetch
30942
+ * @returns the associated {@link Amity.Channel} object
30961
30943
  *
30962
- * @category Join Request API
30963
- * @async
30944
+ * @category Channel API
30964
30945
  */
30965
- const rejectJoinRequest = async (joinRequest) => {
30946
+ getChannel$1.locally = (channelId) => {
30966
30947
  var _a;
30967
30948
  const client = getActiveClient();
30968
- client.log('joinRequest/rejectJoinRequest', joinRequest.joinRequestId);
30969
- const { data } = await client.http.post(`/api/v4/communities/${joinRequest.targetId}/join/reject`, {
30970
- userId: joinRequest.requestorInternalId,
30949
+ client.log('channel/getChannel.locally', channelId);
30950
+ if (!client.cache)
30951
+ return;
30952
+ // use queryCache to get all channel caches and filter by channelPublicId since we use channelPrivateId as cache key
30953
+ const cached = (_a = queryCache(['channel', 'get'])) === null || _a === void 0 ? void 0 : _a.filter(({ data }) => {
30954
+ return data.channelPublicId === channelId;
30971
30955
  });
30972
- const joinRequestCache = (_a = pullFromCache([
30973
- 'joinRequest',
30974
- 'get',
30975
- joinRequest.joinRequestId,
30976
- ])) === null || _a === void 0 ? void 0 : _a.data;
30977
- if (joinRequestCache) {
30978
- upsertInCache(['joinRequest', 'get', joinRequest.joinRequestId], {
30979
- status: "rejected" /* JoinRequestStatusEnum.Rejected */,
30980
- });
30981
- fireEvent('local.joinRequest.updated', [joinRequestCache]);
30982
- }
30983
- return data.success;
30984
- };
30985
- /* end_public_function */
30986
-
30987
- const joinRequestLinkedObject = (joinRequest) => {
30988
- return Object.assign(Object.assign({}, joinRequest), { get user() {
30989
- var _a;
30990
- const user = (_a = pullFromCache([
30991
- 'user',
30992
- 'get',
30993
- joinRequest.requestorPublicId,
30994
- ])) === null || _a === void 0 ? void 0 : _a.data;
30995
- if (!user)
30996
- return undefined;
30997
- return userLinkedObject(user);
30998
- }, cancel: async () => {
30999
- await cancelJoinRequest(joinRequest);
31000
- }, approve: async () => {
31001
- await approveJoinRequest(joinRequest);
31002
- }, reject: async () => {
31003
- await rejectJoinRequest(joinRequest);
31004
- } });
30956
+ if (!cached || (cached === null || cached === void 0 ? void 0 : cached.length) === 0)
30957
+ return;
30958
+ return {
30959
+ data: cached[0].data,
30960
+ cachedAt: cached[0].cachedAt,
30961
+ };
31005
30962
  };
31006
30963
 
31007
- /* begin_public_function
31008
- id: community.getMyJoinRequest
31009
- */
31010
30964
  /**
31011
30965
  * ```js
31012
- * import { community } from '@amityco/ts-sdk-react-native'
31013
- * const isJoined = await community.getMyJoinRequest('foobar')
30966
+ * import { getStream } from '@amityco/ts-sdk-react-native'
30967
+ * const stream = await getStream('foobar')
31014
30968
  * ```
31015
30969
  *
31016
- * Joins a {@link Amity.Community} object
30970
+ * Fetches a {@link Amity.Channel} object linked with a current stream
31017
30971
  *
31018
- * @param communityId the {@link Amity.Community} to join
31019
- * @returns A success boolean if the {@link Amity.Community} was joined
30972
+ * @param stream {@link Amity.Stream} that has linked live channel
30973
+ * @returns the associated {@link Amity.Channel<'live'>} object
31020
30974
  *
31021
- * @category Community API
30975
+ * @category Stream API
31022
30976
  * @async
31023
30977
  */
31024
- const getMyJoinRequest = async (communityId) => {
30978
+ const getLiveChat$1 = async (stream) => {
30979
+ var _a;
31025
30980
  const client = getActiveClient();
31026
- client.log('community/myJoinRequest', communityId);
31027
- const { data: payload } = await client.http.get(`/api/v4/communities/${communityId}/join/me`);
31028
- const data = prepareCommunityJoinRequestPayload(payload);
31029
- const cachedAt = client.cache && Date.now();
31030
- if (client.cache)
31031
- ingestInCache(data, { cachedAt });
31032
- return {
31033
- data: data.joinRequests[0] ? joinRequestLinkedObject(data.joinRequests[0]) : undefined,
31034
- cachedAt,
31035
- };
30981
+ client.log('stream/getLiveChat', stream.streamId);
30982
+ if (stream.channelId) {
30983
+ const channel = (_a = pullFromCache([
30984
+ 'channel',
30985
+ 'get',
30986
+ stream.channelId,
30987
+ ])) === null || _a === void 0 ? void 0 : _a.data;
30988
+ if (channel)
30989
+ return channelLinkedObject(constructChannelObject(channel));
30990
+ const { data } = await getChannel$1(stream.channelId);
30991
+ return channelLinkedObject(constructChannelObject(data));
30992
+ }
30993
+ // No Channel ID
30994
+ // streamer: create a new live channel
30995
+ if (stream.userId === client.userId) {
30996
+ const { data: channel } = await createChannel({
30997
+ type: 'live',
30998
+ postId: stream.postId,
30999
+ videoStreamId: stream.streamId,
31000
+ });
31001
+ // Update channelId to stream object in cache
31002
+ mergeInCache(['stream', 'get', stream.streamId], {
31003
+ channelId: channel.channelId,
31004
+ });
31005
+ return channel;
31006
+ }
31007
+ // watcher: return undefined
31008
+ return undefined;
31036
31009
  };
31037
- /* end_public_function */
31038
31010
 
31039
- /* begin_public_function
31040
- id: community.join
31041
- */
31011
+ const GET_WATCHER_URLS = Symbol('getWatcherUrls');
31012
+ const streamLinkedObject = (stream) => {
31013
+ return Object.assign(Object.assign({}, stream), { get moderation() {
31014
+ var _a;
31015
+ return (_a = pullFromCache(['streamModeration', 'get', stream.streamId])) === null || _a === void 0 ? void 0 : _a.data;
31016
+ },
31017
+ get post() {
31018
+ var _a;
31019
+ if (stream.referenceType !== 'post')
31020
+ return;
31021
+ return (_a = pullFromCache(['post', 'get', stream.referenceId])) === null || _a === void 0 ? void 0 : _a.data;
31022
+ },
31023
+ get community() {
31024
+ var _a;
31025
+ if (stream.targetType !== 'community')
31026
+ return;
31027
+ return (_a = pullFromCache(['community', 'get', stream.targetId])) === null || _a === void 0 ? void 0 : _a.data;
31028
+ },
31029
+ get user() {
31030
+ var _a;
31031
+ return (_a = pullFromCache(['user', 'get', stream.userId])) === null || _a === void 0 ? void 0 : _a.data;
31032
+ },
31033
+ get childStreams() {
31034
+ if (!stream.childStreamIds || stream.childStreamIds.length === 0)
31035
+ return [];
31036
+ return stream.childStreamIds
31037
+ .map(id => {
31038
+ var _a;
31039
+ const streamCache = (_a = pullFromCache(['stream', 'get', id])) === null || _a === void 0 ? void 0 : _a.data;
31040
+ if (!streamCache)
31041
+ return undefined;
31042
+ return streamLinkedObject(streamCache);
31043
+ })
31044
+ .filter(isNonNullable);
31045
+ }, getLiveChat: () => getLiveChat$1(stream), isBanned: !stream.watcherUrl, watcherUrl: null, get [GET_WATCHER_URLS]() {
31046
+ return stream.watcherUrl;
31047
+ } });
31048
+ };
31049
+
31050
+ const commentLinkedObject = (comment) => {
31051
+ return Object.assign(Object.assign({}, comment), { get target() {
31052
+ const commentTypes = {
31053
+ type: comment.targetType,
31054
+ };
31055
+ if (comment.targetType === 'user') {
31056
+ return Object.assign(Object.assign({}, commentTypes), { userId: comment.targetId });
31057
+ }
31058
+ if (commentTypes.type === 'content') {
31059
+ return Object.assign(Object.assign({}, commentTypes), { contentId: comment.targetId });
31060
+ }
31061
+ if (commentTypes.type === 'community') {
31062
+ const cacheData = pullFromCache([
31063
+ 'communityUsers',
31064
+ 'get',
31065
+ `${comment.targetId}#${comment.userId}`,
31066
+ ]);
31067
+ return Object.assign(Object.assign({}, commentTypes), { communityId: comment.targetId, creatorMember: cacheData === null || cacheData === void 0 ? void 0 : cacheData.data });
31068
+ }
31069
+ return {
31070
+ type: 'unknown',
31071
+ };
31072
+ },
31073
+ get creator() {
31074
+ const cacheData = pullFromCache(['user', 'get', comment.userId]);
31075
+ if (cacheData === null || cacheData === void 0 ? void 0 : cacheData.data)
31076
+ return userLinkedObject(cacheData.data);
31077
+ return undefined;
31078
+ },
31079
+ get childrenComment() {
31080
+ return comment.children
31081
+ .map(childCommentId => {
31082
+ const commentCache = pullFromCache([
31083
+ 'comment',
31084
+ 'get',
31085
+ childCommentId,
31086
+ ]);
31087
+ if (!(commentCache === null || commentCache === void 0 ? void 0 : commentCache.data))
31088
+ return;
31089
+ return commentCache === null || commentCache === void 0 ? void 0 : commentCache.data;
31090
+ })
31091
+ .filter(isNonNullable)
31092
+ .map(item => commentLinkedObject(item));
31093
+ } });
31094
+ };
31095
+
31096
+ function isAmityImagePost(post) {
31097
+ return !!(post.data &&
31098
+ typeof post.data !== 'string' &&
31099
+ 'fileId' in post.data &&
31100
+ post.dataType === 'image');
31101
+ }
31102
+ function isAmityFilePost(post) {
31103
+ return !!(post.data &&
31104
+ typeof post.data !== 'string' &&
31105
+ 'fileId' in post.data &&
31106
+ post.dataType === 'file');
31107
+ }
31108
+ function isAmityVideoPost(post) {
31109
+ return !!(post.data &&
31110
+ typeof post.data !== 'string' &&
31111
+ 'videoFileId' in post.data &&
31112
+ 'thumbnailFileId' in post.data &&
31113
+ post.dataType === 'video');
31114
+ }
31115
+ function isAmityLivestreamPost(post) {
31116
+ return !!(post.data &&
31117
+ typeof post.data !== 'string' &&
31118
+ 'streamId' in post.data &&
31119
+ post.dataType === 'liveStream');
31120
+ }
31121
+ function isAmityPollPost(post) {
31122
+ return !!(post.data &&
31123
+ typeof post.data !== 'string' &&
31124
+ 'pollId' in post.data &&
31125
+ post.dataType === 'poll');
31126
+ }
31127
+ function isAmityClipPost(post) {
31128
+ return !!(post.data &&
31129
+ typeof post.data !== 'string' &&
31130
+ 'fileId' in post.data &&
31131
+ post.dataType === 'clip');
31132
+ }
31133
+ function isAmityAudioPost(post) {
31134
+ return !!(post.data &&
31135
+ typeof post.data !== 'string' &&
31136
+ 'fileId' in post.data &&
31137
+ post.dataType === 'audio');
31138
+ }
31139
+ function isAmityRoomPost(post) {
31140
+ return !!(post.data &&
31141
+ typeof post.data !== 'string' &&
31142
+ 'roomId' in post.data &&
31143
+ post.dataType === 'room');
31144
+ }
31145
+
31042
31146
  /**
31043
31147
  * ```js
31044
- * import { community } from '@amityco/ts-sdk-react-native'
31045
- * const isJoined = await community.join('foobar')
31148
+ * import { RoomRepository } from '@amityco/ts-sdk-react-native'
31149
+ * const stream = await getStream('foobar')
31046
31150
  * ```
31047
31151
  *
31048
- * Joins a {@link Amity.Community} object
31152
+ * Fetches a {@link Amity.Channel} object linked with a current stream
31049
31153
  *
31050
- * @param communityId the {@link Amity.Community} to join
31051
- * @returns A status join result
31154
+ * @param stream {@link Amity.Stream} that has linked live channel
31155
+ * @returns the associated {@link Amity.Channel<'live'>} object
31052
31156
  *
31053
- * @category Community API
31157
+ * @category Stream API
31054
31158
  * @async
31055
31159
  */
31056
- const joinRequest = async (communityId) => {
31160
+ const getLiveChat = async (room) => {
31057
31161
  var _a;
31058
31162
  const client = getActiveClient();
31059
- client.log('community/joinRequest', communityId);
31060
- const { data: payload } = await client.http.post(`/api/v4/communities/${communityId}/join`);
31061
- const data = prepareCommunityJoinRequestPayload(payload);
31062
- const cachedAt = client.cache && Date.now();
31063
- if (client.cache)
31064
- ingestInCache(data, { cachedAt });
31065
- const status = data.joinRequests[0].status === "approved" /* JoinRequestStatusEnum.Approved */
31066
- ? "success" /* JoinResultStatusEnum.Success */
31067
- : "pending" /* JoinResultStatusEnum.Pending */;
31068
- if (status === "success" /* JoinResultStatusEnum.Success */ && client.cache) {
31069
- const community = (_a = pullFromCache(['community', 'get', communityId])) === null || _a === void 0 ? void 0 : _a.data;
31070
- if (community) {
31071
- const updatedCommunity = Object.assign(Object.assign({}, community), { isJoined: true });
31072
- upsertInCache(['community', 'get', communityId], updatedCommunity);
31073
- }
31163
+ client.log('room/getLiveChat', room.roomId);
31164
+ if (room.liveChannelId) {
31165
+ const channel = (_a = pullFromCache([
31166
+ 'channel',
31167
+ 'get',
31168
+ room.liveChannelId,
31169
+ ])) === null || _a === void 0 ? void 0 : _a.data;
31170
+ if (channel)
31171
+ return channelLinkedObject(constructChannelObject(channel));
31172
+ const { data } = await getChannel$1(room.liveChannelId);
31173
+ return channelLinkedObject(constructChannelObject(data));
31074
31174
  }
31075
- fireEvent('v4.local.community.joined', data.joinRequests);
31076
- return status === "success" /* JoinResultStatusEnum.Success */
31077
- ? { status }
31078
- : { status, request: joinRequestLinkedObject(data.joinRequests[0]) };
31079
- };
31080
- /* end_public_function */
31081
-
31082
- /**
31083
- * TODO: handle cache receive cache option, and cache policy
31084
- * TODO: check if querybyIds is supported
31085
- */
31086
- class JoinRequestsPaginationController extends PaginationController {
31087
- async getRequest(queryParams, token) {
31088
- const { limit = 20, communityId } = queryParams, params = __rest(queryParams, ["limit", "communityId"]);
31089
- const options = token ? { token } : { limit };
31090
- const { data: queryResponse } = await this.http.get(`/api/v4/communities/${communityId}/join`, {
31091
- params: Object.assign(Object.assign({}, params), { options }),
31175
+ // No Channel ID
31176
+ // streamer: create a new live channel
31177
+ if (room.createdBy === client.userId) {
31178
+ const { data: channel } = await createChannel({
31179
+ type: 'live',
31180
+ postId: room.referenceId,
31181
+ roomId: room.roomId,
31092
31182
  });
31093
- return queryResponse;
31094
- }
31095
- }
31096
-
31097
- var EnumJoinRequestAction$1;
31098
- (function (EnumJoinRequestAction) {
31099
- EnumJoinRequestAction["OnLocalJoinRequestCreated"] = "OnLocalJoinRequestCreated";
31100
- EnumJoinRequestAction["OnLocalJoinRequestUpdated"] = "OnLocalJoinRequestUpdated";
31101
- EnumJoinRequestAction["OnLocalJoinRequestDeleted"] = "OnLocalJoinRequestDeleted";
31102
- })(EnumJoinRequestAction$1 || (EnumJoinRequestAction$1 = {}));
31103
-
31104
- class JoinRequestsQueryStreamController extends QueryStreamController {
31105
- constructor(query, cacheKey, notifyChange, preparePayload) {
31106
- super(query, cacheKey);
31107
- this.notifyChange = notifyChange;
31108
- this.preparePayload = preparePayload;
31109
- }
31110
- async saveToMainDB(response) {
31111
- const processedPayload = await this.preparePayload(response);
31112
- const client = getActiveClient();
31113
- const cachedAt = client.cache && Date.now();
31114
- if (client.cache) {
31115
- ingestInCache(processedPayload, { cachedAt });
31116
- }
31117
- }
31118
- appendToQueryStream(response, direction, refresh = false) {
31119
- var _a, _b;
31120
- if (refresh) {
31121
- pushToCache(this.cacheKey, {
31122
- data: response.joinRequests.map(joinRequest => getResolver('joinRequest')({ joinRequestId: joinRequest._id })),
31123
- });
31124
- }
31125
- else {
31126
- const collection = (_a = pullFromCache(this.cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
31127
- const joinRequests = (_b = collection === null || collection === void 0 ? void 0 : collection.data) !== null && _b !== void 0 ? _b : [];
31128
- pushToCache(this.cacheKey, Object.assign(Object.assign({}, collection), { data: [
31129
- ...new Set([
31130
- ...joinRequests,
31131
- ...response.joinRequests.map(joinRequest => getResolver('joinRequest')({ joinRequestId: joinRequest._id })),
31132
- ]),
31133
- ] }));
31134
- }
31135
- }
31136
- reactor(action) {
31137
- return (joinRequest) => {
31138
- var _a;
31139
- const collection = (_a = pullFromCache(this.cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
31140
- if (!collection)
31141
- return;
31142
- if (action === EnumJoinRequestAction$1.OnLocalJoinRequestUpdated) {
31143
- const isExist = collection.data.find(id => id === joinRequest[0].joinRequestId);
31144
- if (!isExist)
31145
- return;
31146
- }
31147
- if (action === EnumJoinRequestAction$1.OnLocalJoinRequestCreated) {
31148
- collection.data = [
31149
- ...new Set([
31150
- ...joinRequest.map(joinRequest => joinRequest.joinRequestId),
31151
- ...collection.data,
31152
- ]),
31153
- ];
31154
- }
31155
- if (action === EnumJoinRequestAction$1.OnLocalJoinRequestDeleted) {
31156
- collection.data = collection.data.filter(id => id !== joinRequest[0].joinRequestId);
31157
- }
31158
- pushToCache(this.cacheKey, collection);
31159
- this.notifyChange({ origin: "event" /* Amity.LiveDataOrigin.EVENT */, loading: false });
31160
- };
31161
- }
31162
- subscribeRTE(createSubscriber) {
31163
- return createSubscriber.map(subscriber => subscriber.fn(this.reactor(subscriber.action)));
31183
+ // Update channelId to stream object in cache
31184
+ mergeInCache(['room', 'get', room.roomId], {
31185
+ liveChannelId: channel.channelId,
31186
+ });
31187
+ return channel;
31164
31188
  }
31165
- }
31166
-
31167
- /**
31168
- * ```js
31169
- * import { onJoinRequestCreated } from '@amityco/ts-sdk-react-native'
31170
- * const dispose = onJoinRequestCreated(data => {
31171
- * // ...
31172
- * })
31173
- * ```
31174
- *
31175
- * Fired when an {@link Amity.CommunityJoinRequestPayload} has been created
31176
- *
31177
- * @param callback The function to call when the event was fired
31178
- * @returns an {@link Amity.Unsubscriber} function to stop listening
31179
- *
31180
- * @category JoinRequest Events
31181
- */
31182
- const onJoinRequestCreated = (callback) => {
31183
- const client = getActiveClient();
31184
- const disposers = [
31185
- createEventSubscriber(client, 'onJoinRequestCreated', 'local.joinRequest.created', payload => callback(payload)),
31186
- ];
31187
- return () => {
31188
- disposers.forEach(fn => fn());
31189
- };
31190
- };
31191
-
31192
- /**
31193
- * ```js
31194
- * import { onJoinRequestUpdated } from '@amityco/ts-sdk-react-native'
31195
- * const dispose = onJoinRequestUpdated(data => {
31196
- * // ...
31197
- * })
31198
- * ```
31199
- *
31200
- * Fired when an {@link Amity.CommunityJoinRequestPayload} has been created
31201
- *
31202
- * @param callback The function to call when the event was fired
31203
- * @returns an {@link Amity.Unsubscriber} function to stop listening
31204
- *
31205
- * @category JoinRequest Events
31206
- */
31207
- const onJoinRequestUpdated = (callback) => {
31208
- const client = getActiveClient();
31209
- const disposers = [
31210
- createEventSubscriber(client, 'onJoinRequestUpdated', 'local.joinRequest.updated', payload => callback(payload)),
31211
- ];
31212
- return () => {
31213
- disposers.forEach(fn => fn());
31214
- };
31189
+ // watcher: return undefined
31190
+ return undefined;
31215
31191
  };
31216
31192
 
31217
31193
  /**
31218
- * ```js
31219
- * import { onJoinRequestDeleted } from '@amityco/ts-sdk-react-native'
31220
- * const dispose = onJoinRequestDeleted(data => {
31221
- * // ...
31222
- * })
31223
- * ```
31224
- *
31225
- * Fired when an {@link Amity.CommunityJoinRequestPayload} has been created
31226
- *
31227
- * @param callback The function to call when the event was fired
31228
- * @returns an {@link Amity.Unsubscriber} function to stop listening
31229
- *
31230
- * @category JoinRequest Events
31194
+ * WatchSessionStorage manages watch session data in memory
31195
+ * Similar to UsageCollector for stream watch minutes
31231
31196
  */
31232
- const onJoinRequestDeleted = (callback) => {
31233
- const client = getActiveClient();
31234
- const disposers = [
31235
- createEventSubscriber(client, 'onJoinRequestDeleted', 'local.joinRequest.deleted', payload => callback(payload)),
31236
- ];
31237
- return () => {
31238
- disposers.forEach(fn => fn());
31239
- };
31240
- };
31241
-
31242
- class JoinRequestsLiveCollectionController extends LiveCollectionController {
31243
- constructor(query, callback) {
31244
- const queryStreamId = hash(query);
31245
- const cacheKey = ['joinRequest', 'collection', queryStreamId];
31246
- const paginationController = new JoinRequestsPaginationController(query);
31247
- super(paginationController, queryStreamId, cacheKey, callback);
31248
- this.query = query;
31249
- this.queryStreamController = new JoinRequestsQueryStreamController(this.query, this.cacheKey, this.notifyChange.bind(this), prepareCommunityJoinRequestPayload);
31250
- this.callback = callback.bind(this);
31251
- this.loadPage({ initial: true });
31197
+ class WatchSessionStorage {
31198
+ constructor() {
31199
+ this.sessions = new Map();
31252
31200
  }
31253
- setup() {
31254
- var _a;
31255
- const collection = (_a = pullFromCache(this.cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
31256
- if (!collection) {
31257
- pushToCache(this.cacheKey, {
31258
- data: [],
31259
- params: this.query,
31260
- });
31261
- }
31201
+ /**
31202
+ * Add a new watch session
31203
+ */
31204
+ addSession(session) {
31205
+ this.sessions.set(session.sessionId, session);
31206
+ }
31207
+ /**
31208
+ * Get a watch session by sessionId
31209
+ */
31210
+ getSession(sessionId) {
31211
+ return this.sessions.get(sessionId);
31262
31212
  }
31263
- async persistModel(queryPayload) {
31264
- await this.queryStreamController.saveToMainDB(queryPayload);
31213
+ /**
31214
+ * Update a watch session
31215
+ */
31216
+ updateSession(sessionId, updates) {
31217
+ const session = this.sessions.get(sessionId);
31218
+ if (session) {
31219
+ this.sessions.set(sessionId, Object.assign(Object.assign({}, session), updates));
31220
+ }
31265
31221
  }
31266
- persistQueryStream({ response, direction, refresh, }) {
31267
- const joinRequestResponse = response;
31268
- this.queryStreamController.appendToQueryStream(joinRequestResponse, direction, refresh);
31222
+ /**
31223
+ * Get all sessions with a specific sync state
31224
+ */
31225
+ getSessionsByState(state) {
31226
+ return Array.from(this.sessions.values()).filter(session => session.syncState === state);
31269
31227
  }
31270
- startSubscription() {
31271
- return this.queryStreamController.subscribeRTE([
31272
- { fn: onJoinRequestCreated, action: EnumJoinRequestAction$1.OnLocalJoinRequestCreated },
31273
- { fn: onJoinRequestUpdated, action: EnumJoinRequestAction$1.OnLocalJoinRequestUpdated },
31274
- { fn: onJoinRequestDeleted, action: EnumJoinRequestAction$1.OnLocalJoinRequestDeleted },
31275
- ]);
31228
+ /**
31229
+ * Delete a session
31230
+ */
31231
+ deleteSession(sessionId) {
31232
+ this.sessions.delete(sessionId);
31276
31233
  }
31277
- notifyChange({ origin, loading, error }) {
31278
- var _a;
31279
- const collection = (_a = pullFromCache(this.cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
31280
- if (!collection)
31281
- return;
31282
- const data = this.applyFilter(collection.data
31283
- .map(id => pullFromCache(['joinRequest', 'get', id]))
31284
- .filter(isNonNullable)
31285
- .map(({ data }) => data)
31286
- .map(joinRequestLinkedObject));
31287
- if (!this.shouldNotify(data) && origin === 'event')
31288
- return;
31289
- this.callback({
31290
- onNextPage: () => this.loadPage({ direction: "next" /* Amity.LiveCollectionPageDirection.NEXT */ }),
31291
- data,
31292
- hasNextPage: !!this.paginationController.getNextToken(),
31293
- loading,
31294
- error,
31295
- });
31234
+ /**
31235
+ * Get all pending sessions
31236
+ */
31237
+ getPendingSessions() {
31238
+ return this.getSessionsByState('PENDING');
31296
31239
  }
31297
- applyFilter(data) {
31298
- let joinRequest = data;
31299
- if (this.query.status) {
31300
- joinRequest = joinRequest.filter(joinRequest => joinRequest.status === this.query.status);
31301
- }
31302
- const sortFn = (() => {
31303
- switch (this.query.sortBy) {
31304
- case 'firstCreated':
31305
- return sortByFirstCreated;
31306
- case 'lastCreated':
31307
- return sortByLastCreated;
31308
- default:
31309
- return sortByLastCreated;
31310
- }
31311
- })();
31312
- joinRequest = joinRequest.sort(sortFn);
31313
- return joinRequest;
31240
+ /**
31241
+ * Get all syncing sessions
31242
+ */
31243
+ getSyncingSessions() {
31244
+ return this.getSessionsByState('SYNCING');
31314
31245
  }
31315
31246
  }
31247
+ // Singleton instance
31248
+ let storageInstance = null;
31249
+ const getWatchSessionStorage = () => {
31250
+ if (!storageInstance) {
31251
+ storageInstance = new WatchSessionStorage();
31252
+ }
31253
+ return storageInstance;
31254
+ };
31316
31255
 
31317
- /**
31318
- * Get Join Requests
31319
- *
31320
- * @param params the query parameters
31321
- * @param callback the callback to be called when the join request are updated
31322
- * @returns joinRequests
31323
- *
31324
- * @category joinRequest Live Collection
31256
+ const privateKey = "-----BEGIN PRIVATE KEY-----\nMIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDAARz+hmBgi8pJ\nQb8LeY41gtHhk+ACMwRfhsn7GqpqRQNG2qU0755mzZuVDUqjQMGSo8THJB7O+OJs\nflbZRkFXlFoFOVNw1UpNOgwEQZ6wB9oRwzepTJAfF1sVhm/o/ixvXh1zDFNDy6yZ\npXyiiJHUVxqyjllZhxnwdvjoVtDs6hW6awG09bB9nh/TTejlUKXoAgzqVwu/1QMu\nUVViET495elEe19aUarEy+oL2iKeXCEvqda/pWNBdbieFyJvvZ08HN8dPuT88wq2\njZLEAth1vrwQ2IAa4ktaLcBQdLJgIkrbDvAiVZ8lQAjS/bq5vXQikTGvoPlC5bbn\nvuOM/3eLAgMBAAECggEAVZ+peHAghq2QVj71nX5lxsNCKaCyYwixSJBpfouTt7Rz\nE6PpzMOXFi1W1o+I22jDakuSM2SOQKqI/u0QefB0r0O/KVk5NrZHXk0mkrdYtxOp\nUgaGyf8UvmjB+8VqHrNKyZdk9qtmbnNj01kTTcAtmE4H39zPR7eR/8Rul94vaZbs\nwCnKJS3mLT3JxyGug6lxanveKkjG+CKC1nJQYWaxCJxaFSzbwXQPvDhB+TvrIbee\npd5v4EAyEJohpr+T9oDGGJkb/KARBZCtwLyB976PKJwwBA8MRVL1i5QwawuMiMq5\nUtnOnbGKtCeFzaLbNU0Qi8bqyims84EQxC6DOu1fkQKBgQDdvsoBsEhsOXV7hlIJ\naEd0eSJZVkdqimxH8uGoMM2FeNaOrcB6yBXqTSP0R3OIyf8eaY6yjRvP30ZNXcll\n/gD3O1Mu6YmWQdt1W2WA6pKOsUuPXasf0pdOF7IiFZKlSabz5YHXFqwVuqm8loaj\nsXel3YWqPVdHiankE7tz+3ssnQKBgQDdqi4TNdD1MdEpihx19jr0QjUiXW3939FK\nqp30HESPEGDGQzXdmJgif9HhZb+cJSuWaHEbjgBrYahvgCF+y6LbEpOD+D/dmT+s\nDEAQaR84sah6dokwPjV8fjBSrcVFjCS+doxv0d3p/9OUEeyUhFrY03nxtIEYkLIE\n/Zvn37b4RwKBgQCLENVFe9XfsaVhQ5r9dV2iyTlmh7qgMZG5CbTFs12hQGhm8McO\n+Z7s41YSJCFr/yq1WwP4LJDtrBw99vyQr1zRsG35tNLp3gGRNzGQSQyC2uQFVHw2\np+7mNewsfhUK/gbrXNsyFnDz6635rPlhfbII3sWuP2wWXFqkxE9CbMwR7QKBgQC6\nawDMzxmo2/iYArrkyevSuEuPVxvFwpF1RgAI6C0QVCnPE38dmdN4UB7mfHekje4W\nVEercMURidPp0cxZolCYBQtilUjAyL0vqC3In1/Ogjq6oy3FEMxSop1pKxMY5j+Q\nnoqFD+6deLUrddeNH7J3X4LSr4dSbX4JjG+tlgt+yQKBgQCuwTL4hA6KqeInQ0Ta\n9VQX5Qr8hFlqJz1gpymi/k63tW/Ob8yedbg3WWNWyShwRMFYyY9S81ITFWM95uL6\nvF3x9rmRjwElJw9PMwVu6dmf/CO0Z1wzXSp2VVD12gbrUD/0/d7MUoJ9LgC8X8f/\nn0txLHYGHbx+nf95+JUg6lV3hg==\n-----END PRIVATE KEY-----";
31257
+ /*
31258
+ * The crypto algorithm used for importing key and signing string
31259
+ */
31260
+ const ALGORITHM = {
31261
+ name: 'RSASSA-PKCS1-v1_5',
31262
+ hash: { name: 'SHA-256' },
31263
+ };
31264
+ /*
31265
+ * IMPORTANT!
31266
+ * If you are recieving key from other platforms use an online tool to convert
31267
+ * the PKCS1 to PKCS8. For instance the key from Android SDK is of the format
31268
+ * PKCS1.
31325
31269
  *
31270
+ * If recieving from the platform, verify if it's already in the expected
31271
+ * format. Otherwise the crypto.subtle.importKey will throw a DOMException
31326
31272
  */
31327
- const getJoinRequests = (params, callback, config) => {
31328
- const { log, cache } = getActiveClient();
31329
- if (!cache) {
31330
- console.log(ENABLE_CACHE_MESSAGE);
31331
- }
31332
- const timestamp = Date.now();
31333
- log(`getJoinRequests: (tmpid: ${timestamp}) > listen`);
31334
- const joinRequestLiveCollection = new JoinRequestsLiveCollectionController(params, callback);
31335
- const disposers = joinRequestLiveCollection.startSubscription();
31336
- const cacheKey = joinRequestLiveCollection.getCacheKey();
31337
- disposers.push(() => {
31338
- dropFromCache(cacheKey);
31273
+ const PRIVATE_KEY_SIGNATURE = 'pkcs8';
31274
+ /*
31275
+ * Ensure that the private key in the .env follows this format
31276
+ */
31277
+ const PEM_HEADER = '-----BEGIN PRIVATE KEY-----';
31278
+ const PEM_FOOTER = '-----END PRIVATE KEY-----';
31279
+ /*
31280
+ * The crypto.subtle.sign function returns an ArrayBuffer whereas the server
31281
+ * expects a base64 string. This util helps facilitate that process
31282
+ */
31283
+ function base64FromArrayBuffer(buffer) {
31284
+ const uint8Array = new Uint8Array(buffer);
31285
+ let binary = '';
31286
+ uint8Array.forEach(byte => {
31287
+ binary += String.fromCharCode(byte);
31339
31288
  });
31340
- return () => {
31341
- log(`getJoinRequests (tmpid: ${timestamp}) > dispose`);
31342
- disposers.forEach(fn => fn());
31343
- };
31344
- };
31345
-
31346
- var InvitationActionsEnum;
31347
- (function (InvitationActionsEnum) {
31348
- InvitationActionsEnum["OnLocalInvitationCreated"] = "onLocalInvitationCreated";
31349
- InvitationActionsEnum["OnLocalInvitationUpdated"] = "onLocalInvitationUpdated";
31350
- InvitationActionsEnum["OnLocalInvitationCanceled"] = "onLocalInvitationCanceled";
31351
- })(InvitationActionsEnum || (InvitationActionsEnum = {}));
31352
-
31353
- class InvitationsPaginationController extends PaginationController {
31354
- async getRequest(queryParams, token) {
31355
- const { limit = COLLECTION_DEFAULT_PAGINATION_LIMIT } = queryParams, params = __rest(queryParams, ["limit"]);
31356
- const options = token ? { token } : { limit };
31357
- const { data } = await this.http.get('/api/v1/invitations', { params: Object.assign(Object.assign({}, params), { options }) });
31358
- return data;
31359
- }
31289
+ return btoa(binary);
31360
31290
  }
31361
-
31362
- class InvitationsQueryStreamController extends QueryStreamController {
31363
- constructor(query, cacheKey, notifyChange, preparePayload) {
31364
- super(query, cacheKey);
31365
- this.notifyChange = notifyChange;
31366
- this.preparePayload = preparePayload;
31367
- }
31368
- async saveToMainDB(response) {
31369
- const processedPayload = await this.preparePayload(response);
31370
- const client = getActiveClient();
31371
- const cachedAt = client.cache && Date.now();
31372
- if (client.cache) {
31373
- ingestInCache(processedPayload, { cachedAt });
31374
- }
31291
+ /*
31292
+ * Encode ASN.1 length field
31293
+ */
31294
+ function encodeLength(length) {
31295
+ if (length < 128) {
31296
+ return new Uint8Array([length]);
31375
31297
  }
31376
- appendToQueryStream(response, direction, refresh = false) {
31377
- var _a, _b;
31378
- if (refresh) {
31379
- pushToCache(this.cacheKey, {
31380
- data: response.invitations.map(getResolver('invitation')),
31381
- });
31382
- }
31383
- else {
31384
- const collection = (_a = pullFromCache(this.cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
31385
- const invitations = (_b = collection === null || collection === void 0 ? void 0 : collection.data) !== null && _b !== void 0 ? _b : [];
31386
- pushToCache(this.cacheKey, Object.assign(Object.assign({}, collection), { data: [
31387
- ...new Set([...invitations, ...response.invitations.map(getResolver('invitation'))]),
31388
- ] }));
31389
- }
31298
+ if (length < 256) {
31299
+ return new Uint8Array([0x81, length]);
31390
31300
  }
31391
- reactor(action) {
31392
- return (invitations) => {
31393
- var _a;
31394
- const collection = (_a = pullFromCache(this.cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
31395
- if (!collection)
31396
- return;
31397
- if (action === InvitationActionsEnum.OnLocalInvitationUpdated) {
31398
- const isExist = collection.data.find(id => id === invitations[0].invitationId);
31399
- if (!isExist)
31400
- return;
31401
- }
31402
- if (action === InvitationActionsEnum.OnLocalInvitationCreated) {
31403
- collection.data = [
31404
- ...new Set([
31405
- ...invitations.map(invitation => invitation.invitationId),
31406
- ...collection.data,
31407
- ]),
31408
- ];
31409
- }
31410
- if (action === InvitationActionsEnum.OnLocalInvitationDeleted) {
31411
- collection.data = collection.data.filter(id => id !== invitations[0].invitationId);
31412
- }
31413
- pushToCache(this.cacheKey, collection);
31414
- this.notifyChange({ origin: "event" /* Amity.LiveDataOrigin.EVENT */, loading: false });
31415
- };
31301
+ // eslint-disable-next-line no-bitwise
31302
+ return new Uint8Array([0x82, (length >> 8) & 0xff, length & 0xff]);
31303
+ }
31304
+ /*
31305
+ * Convert PKCS1 private key to PKCS8 format
31306
+ * PKCS1 is RSA-specific format, PKCS8 is generic format that crypto.subtle requires
31307
+ * Android uses PKCS8EncodedKeySpec which expects PKCS8 format
31308
+ */
31309
+ function pkcs1ToPkcs8(pkcs1) {
31310
+ // Algorithm identifier for RSA
31311
+ const algorithmIdentifier = new Uint8Array([
31312
+ 0x30,
31313
+ 0x0d,
31314
+ 0x06,
31315
+ 0x09,
31316
+ 0x2a,
31317
+ 0x86,
31318
+ 0x48,
31319
+ 0x86,
31320
+ 0xf7,
31321
+ 0x0d,
31322
+ 0x01,
31323
+ 0x01,
31324
+ 0x01,
31325
+ 0x05,
31326
+ 0x00, // NULL
31327
+ ]);
31328
+ // Version (INTEGER 0)
31329
+ const version = new Uint8Array([0x02, 0x01, 0x00]);
31330
+ // OCTET STRING tag + length + pkcs1 data
31331
+ const octetStringTag = 0x04;
31332
+ const octetStringLength = encodeLength(pkcs1.length);
31333
+ // Calculate total content length (version + algorithm + octet string)
31334
+ const contentLength = version.length + algorithmIdentifier.length + 1 + octetStringLength.length + pkcs1.length;
31335
+ // SEQUENCE tag + length
31336
+ const sequenceTag = 0x30;
31337
+ const sequenceLength = encodeLength(contentLength);
31338
+ // Build the PKCS8 structure
31339
+ const pkcs8 = new Uint8Array(1 + sequenceLength.length + contentLength);
31340
+ let offset = 0;
31341
+ pkcs8[offset] = sequenceTag;
31342
+ offset += 1;
31343
+ pkcs8.set(sequenceLength, offset);
31344
+ offset += sequenceLength.length;
31345
+ pkcs8.set(version, offset);
31346
+ offset += version.length;
31347
+ pkcs8.set(algorithmIdentifier, offset);
31348
+ offset += algorithmIdentifier.length;
31349
+ pkcs8[offset] = octetStringTag;
31350
+ offset += 1;
31351
+ pkcs8.set(octetStringLength, offset);
31352
+ offset += octetStringLength.length;
31353
+ pkcs8.set(pkcs1, offset);
31354
+ return pkcs8;
31355
+ }
31356
+ async function importPrivateKey(keyString) {
31357
+ // Remove PEM headers if present and any whitespace
31358
+ let base64Key = keyString;
31359
+ if (keyString.includes(PEM_HEADER)) {
31360
+ base64Key = keyString
31361
+ .substring(PEM_HEADER.length, keyString.length - PEM_FOOTER.length)
31362
+ .replace(/\s/g, '');
31416
31363
  }
31417
- subscribeRTE(createSubscriber) {
31418
- return createSubscriber.map(subscriber => subscriber.fn(this.reactor(subscriber.action)));
31364
+ else {
31365
+ base64Key = keyString.replace(/\s/g, '');
31366
+ }
31367
+ // Base64 decode to get binary data
31368
+ const binaryDerString = atob(base64Key);
31369
+ // Convert to Uint8Array for manipulation
31370
+ const pkcs1 = new Uint8Array(binaryDerString.length);
31371
+ for (let i = 0; i < binaryDerString.length; i += 1) {
31372
+ pkcs1[i] = binaryDerString.charCodeAt(i);
31419
31373
  }
31374
+ // Convert PKCS1 to PKCS8 (crypto.subtle requires PKCS8)
31375
+ const pkcs8 = pkcs1ToPkcs8(pkcs1);
31376
+ // Import the key
31377
+ const key = await crypto.subtle.importKey(PRIVATE_KEY_SIGNATURE, pkcs8.buffer, ALGORITHM, false, ['sign']);
31378
+ return key;
31379
+ }
31380
+ async function createSignature({ timestamp, rooms, }) {
31381
+ const dataStr = rooms
31382
+ .map(item => Object.keys(item)
31383
+ .sort()
31384
+ .map(key => `${key}=${item[key]}`)
31385
+ .join('&'))
31386
+ .join(';');
31387
+ /*
31388
+ * nonceStr needs to be unique for each request
31389
+ */
31390
+ const nonceStr = uuid$1.v4();
31391
+ const signStr = `nonceStr=${nonceStr}&timestamp=${timestamp}&data=${dataStr}==`;
31392
+ const encoder = new TextEncoder();
31393
+ const data = encoder.encode(signStr);
31394
+ const key = await importPrivateKey(privateKey);
31395
+ const sign = await crypto.subtle.sign(ALGORITHM, key, data);
31396
+ return { signature: base64FromArrayBuffer(sign), nonceStr };
31420
31397
  }
31421
31398
 
31422
31399
  /**
31423
- * ```js
31424
- * import { onLocalInvitationCreated } from '@amityco/ts-sdk-react-native'
31425
- * const dispose = onLocalInvitationCreated(data => {
31426
- * // ...
31427
- * })
31428
- * ```
31429
- *
31430
- * Fired when an {@link Amity.InvitationPayload} has been created
31431
- *
31432
- * @param callback The function to call when the event was fired
31433
- * @returns an {@link Amity.Unsubscriber} function to stop listening
31434
- *
31435
- * @category Invitation Events
31436
- */
31437
- const onLocalInvitationCreated = (callback) => {
31438
- const client = getActiveClient();
31439
- const disposers = [
31440
- createEventSubscriber(client, 'onLocalInvitationCreated', 'local.invitation.created', payload => callback(payload)),
31441
- ];
31442
- return () => {
31443
- disposers.forEach(fn => fn());
31444
- };
31445
- };
31446
-
31447
- /**
31448
- * ```js
31449
- * import { onLocalInvitationUpdated } from '@amityco/ts-sdk-react-native'
31450
- * const dispose = onLocalInvitationUpdated(data => {
31451
- * // ...
31452
- * })
31453
- * ```
31454
- *
31455
- * Fired when an {@link Amity.InvitationPayload} has been updated
31456
- *
31457
- * @param callback The function to call when the event was fired
31458
- * @returns an {@link Amity.Unsubscriber} function to stop listening
31459
- *
31460
- * @category Invitation Events
31461
- */
31462
- const onLocalInvitationUpdated = (callback) => {
31463
- const client = getActiveClient();
31464
- const disposers = [
31465
- createEventSubscriber(client, 'onLocalInvitationUpdated', 'local.invitation.updated', payload => callback(payload)),
31466
- ];
31467
- return () => {
31468
- disposers.forEach(fn => fn());
31469
- };
31470
- };
31471
-
31472
- /**
31473
- * ```js
31474
- * import { onLocalInvitationCanceled } from '@amityco/ts-sdk-react-native'
31475
- * const dispose = onLocalInvitationCanceled(data => {
31476
- * // ...
31477
- * })
31478
- * ```
31479
- *
31480
- * Fired when an {@link Amity.InvitationPayload} has been deleted
31481
- *
31482
- * @param callback The function to call when the event was fired
31483
- * @returns an {@link Amity.Unsubscriber} function to stop listening
31484
- *
31485
- * @category Invitation Events
31400
+ * Sync pending watch sessions to backend
31401
+ * This function implements the full sync flow with network resilience
31486
31402
  */
31487
- const onLocalInvitationCanceled = (callback) => {
31488
- const client = getActiveClient();
31489
- const disposers = [
31490
- createEventSubscriber(client, 'onLocalInvitationCanceled', 'local.invitation.canceled', payload => callback(payload)),
31491
- ];
31492
- return () => {
31493
- disposers.forEach(fn => fn());
31494
- };
31495
- };
31496
-
31497
- class InvitationsLiveCollectionController extends LiveCollectionController {
31498
- constructor(query, callback) {
31499
- const queryStreamId = hash(query);
31500
- const cacheKey = ['invitation', 'collection', queryStreamId];
31501
- const paginationController = new InvitationsPaginationController(query);
31502
- super(paginationController, queryStreamId, cacheKey, callback);
31503
- this.query = query;
31504
- this.queryStreamController = new InvitationsQueryStreamController(this.query, this.cacheKey, this.notifyChange.bind(this), prepareInvitationPayload);
31505
- this.callback = callback.bind(this);
31506
- this.loadPage({ initial: true });
31403
+ async function syncWatchSessions() {
31404
+ const storage = getWatchSessionStorage();
31405
+ // Get all pending sessions
31406
+ const pendingSessions = storage.getPendingSessions();
31407
+ if (pendingSessions.length === 0) {
31408
+ return true;
31507
31409
  }
31508
- setup() {
31509
- var _a;
31510
- const collection = (_a = pullFromCache(this.cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
31511
- if (!collection) {
31512
- pushToCache(this.cacheKey, {
31513
- data: [],
31514
- params: this.query,
31515
- });
31410
+ try {
31411
+ const timestamp = new Date().toISOString();
31412
+ // Convert sessions to API format - always include all fields like syncUsage does
31413
+ const rooms = pendingSessions.map(session => ({
31414
+ sessionId: session.sessionId,
31415
+ roomId: session.roomId,
31416
+ watchSeconds: session.watchSeconds,
31417
+ startTime: session.startTime.toISOString(),
31418
+ endTime: session.endTime ? session.endTime.toISOString() : '',
31419
+ }));
31420
+ // Create signature (reuse from stream feature) - pass directly like syncUsage
31421
+ const signatureData = await createSignature({
31422
+ timestamp,
31423
+ rooms,
31424
+ });
31425
+ if (!signatureData || !signatureData.signature) {
31426
+ throw new Error('Signature is undefined');
31516
31427
  }
31517
- }
31518
- async persistModel(queryPayload) {
31519
- await this.queryStreamController.saveToMainDB(queryPayload);
31520
- }
31521
- persistQueryStream({ response, direction, refresh, }) {
31522
- this.queryStreamController.appendToQueryStream(response, direction, refresh);
31523
- }
31524
- startSubscription() {
31525
- return this.queryStreamController.subscribeRTE([
31526
- {
31527
- fn: onLocalInvitationCreated,
31528
- action: InvitationActionsEnum.OnLocalInvitationCreated,
31529
- },
31530
- {
31531
- fn: onLocalInvitationUpdated,
31532
- action: InvitationActionsEnum.OnLocalInvitationUpdated,
31533
- },
31534
- {
31535
- fn: onLocalInvitationCanceled,
31536
- action: InvitationActionsEnum.OnLocalInvitationCanceled,
31537
- },
31538
- ]);
31539
- }
31540
- notifyChange({ origin, loading, error }) {
31541
- var _a, _b;
31542
- const collection = (_a = pullFromCache(this.cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
31543
- if (!collection)
31544
- return;
31545
- const data = this.applyFilter((_b = collection.data
31546
- .map(id => pullFromCache(['invitation', 'get', id]))
31547
- .filter(isNonNullable)
31548
- .map(({ data }) => invitationLinkedObject(data))) !== null && _b !== void 0 ? _b : []);
31549
- if (!this.shouldNotify(data) && origin === 'event')
31550
- return;
31551
- this.callback({
31552
- onNextPage: () => this.loadPage({ direction: "next" /* Amity.LiveCollectionPageDirection.NEXT */ }),
31553
- data,
31554
- hasNextPage: !!this.paginationController.getNextToken(),
31555
- loading,
31556
- error,
31428
+ // Update sync state to SYNCING
31429
+ pendingSessions.forEach(session => {
31430
+ storage.updateSession(session.sessionId, { syncState: 'SYNCING' });
31431
+ });
31432
+ const payload = {
31433
+ signature: signatureData.signature,
31434
+ nonceStr: signatureData.nonceStr,
31435
+ timestamp,
31436
+ rooms,
31437
+ };
31438
+ const client = getActiveClient();
31439
+ // Send to backend
31440
+ await client.http.post('/api/v3/user-event/room', payload);
31441
+ // Success - update to SYNCED
31442
+ pendingSessions.forEach(session => {
31443
+ storage.updateSession(session.sessionId, {
31444
+ syncState: 'SYNCED',
31445
+ syncedAt: new Date(),
31446
+ });
31557
31447
  });
31448
+ return true;
31558
31449
  }
31559
- applyFilter(data) {
31560
- let invitations = data;
31561
- if (this.query.targetId) {
31562
- invitations = invitations.filter(invitation => invitation.targetId === this.query.targetId);
31563
- }
31564
- if (this.query.statuses) {
31565
- invitations = invitations.filter(invitation => { var _a; return (_a = this.query.statuses) === null || _a === void 0 ? void 0 : _a.includes(invitation.status); });
31566
- }
31567
- if (this.query.targetType) {
31568
- invitations = invitations.filter(invitation => invitation.targetType === this.query.targetType);
31569
- }
31570
- if (this.query.type) {
31571
- invitations = invitations.filter(invitation => invitation.type === this.query.type);
31572
- }
31573
- const sortFn = (() => {
31574
- switch (this.query.sortBy) {
31575
- case 'firstCreated':
31576
- return sortByFirstCreated;
31577
- case 'lastCreated':
31578
- return sortByLastCreated;
31579
- default:
31580
- return sortByLastCreated;
31450
+ catch (err) {
31451
+ console.error('[SDK syncWatchSessions] ERROR caught:', (err === null || err === void 0 ? void 0 : err.message) || err);
31452
+ // Failure - update back to PENDING and increment retry count
31453
+ pendingSessions.forEach(session => {
31454
+ const currentSession = storage.getSession(session.sessionId);
31455
+ if (currentSession) {
31456
+ const newRetryCount = currentSession.retryCount + 1;
31457
+ if (newRetryCount >= 3) {
31458
+ // Delete session if retry count exceeds 3
31459
+ storage.deleteSession(session.sessionId);
31460
+ }
31461
+ else {
31462
+ // Update to PENDING with incremented retry count
31463
+ storage.updateSession(session.sessionId, {
31464
+ syncState: 'PENDING',
31465
+ retryCount: newRetryCount,
31466
+ });
31467
+ }
31581
31468
  }
31582
- })();
31583
- invitations = invitations.sort(sortFn);
31584
- return invitations;
31469
+ });
31470
+ return false;
31585
31471
  }
31586
31472
  }
31587
31473
 
31588
31474
  /**
31589
- * Get invitations
31590
- *
31591
- * @param params the query parameters
31592
- * @param callback the callback to be called when the invitations are updated
31593
- * @returns invitations
31594
- *
31595
- * @category Invitation Live Collection
31596
- *
31475
+ * Room statuses that are considered watchable
31597
31476
  */
31598
- const getInvitations$1 = (params, callback, config) => {
31599
- const { log, cache } = getActiveClient();
31600
- if (!cache) {
31601
- console.log(ENABLE_CACHE_MESSAGE);
31602
- }
31603
- const timestamp = Date.now();
31604
- log(`getInvitations: (tmpid: ${timestamp}) > listen`);
31605
- const invitationsLiveCollection = new InvitationsLiveCollectionController(params, callback);
31606
- const disposers = invitationsLiveCollection.startSubscription();
31607
- const cacheKey = invitationsLiveCollection.getCacheKey();
31608
- disposers.push(() => {
31609
- dropFromCache(cacheKey);
31477
+ const WATCHABLE_ROOM_STATUSES = ['live', 'recorded'];
31478
+ /**
31479
+ * Generate a random jitter delay between 5 and 30 seconds
31480
+ */
31481
+ const getJitterDelay = () => {
31482
+ const minDelay = 5000; // 5 seconds
31483
+ const maxDelay = 30000; // 30 seconds
31484
+ return Math.floor(Math.random() * (maxDelay - minDelay + 1)) + minDelay;
31485
+ };
31486
+ /**
31487
+ * Wait for network connection with timeout
31488
+ * @param maxWaitTime Maximum time to wait in milliseconds (default: 60000 = 60 seconds)
31489
+ * @returns Promise that resolves when network is available or timeout is reached
31490
+ */
31491
+ const waitForNetwork = (maxWaitTime = 60000) => {
31492
+ return new Promise(resolve => {
31493
+ // Simple check - if navigator.onLine is available, use it
31494
+ // Otherwise, assume network is available
31495
+ if (typeof navigator === 'undefined' || typeof navigator.onLine === 'undefined') {
31496
+ resolve();
31497
+ return;
31498
+ }
31499
+ const startTime = Date.now();
31500
+ const checkInterval = 1000; // 1 second
31501
+ const checkConnection = () => {
31502
+ if (navigator.onLine || Date.now() - startTime >= maxWaitTime) {
31503
+ resolve();
31504
+ }
31505
+ else {
31506
+ setTimeout(checkConnection, checkInterval);
31507
+ }
31508
+ };
31509
+ checkConnection();
31610
31510
  });
31611
- return () => {
31612
- log(`getInvitations (tmpid: ${timestamp}) > dispose`);
31613
- disposers.forEach(fn => fn());
31614
- };
31615
31511
  };
31512
+ /**
31513
+ * AmityRoomAnalytics provides analytics capabilities for room watch sessions
31514
+ */
31515
+ class AmityRoomAnalytics {
31516
+ constructor(room) {
31517
+ this.storage = getWatchSessionStorage();
31518
+ this.client = getActiveClient();
31519
+ this.room = room;
31520
+ }
31521
+ /**
31522
+ * Create a new watch session for the current room
31523
+ * @param startedAt The timestamp when watching started
31524
+ * @returns Promise<string> sessionId unique identifier for this watch session
31525
+ * @throws ASCApiError if room is not in watchable state (not LIVE or RECORDED)
31526
+ */
31527
+ async createWatchSession(startedAt) {
31528
+ // Validate room status
31529
+ if (!WATCHABLE_ROOM_STATUSES.includes(this.room.status)) {
31530
+ throw new ASCApiError('room is not in watchable state', 500000 /* Amity.ServerError.BUSINESS_ERROR */, "error" /* Amity.ErrorLevel.ERROR */);
31531
+ }
31532
+ // Generate session ID with prefix
31533
+ const prefix = this.room.status === 'live' ? 'room_' : 'room_playback_';
31534
+ const sessionId = prefix + uuid$1.v4();
31535
+ // Create watch session entity
31536
+ const session = {
31537
+ sessionId,
31538
+ roomId: this.room.roomId,
31539
+ watchSeconds: 0,
31540
+ startTime: startedAt,
31541
+ endTime: null,
31542
+ syncState: 'PENDING',
31543
+ syncedAt: null,
31544
+ retryCount: 0,
31545
+ };
31546
+ // Persist to storage
31547
+ this.storage.addSession(session);
31548
+ return sessionId;
31549
+ }
31550
+ /**
31551
+ * Update an existing watch session with duration
31552
+ * @param sessionId The unique identifier of the watch session
31553
+ * @param duration The total watch duration in seconds
31554
+ * @param endedAt The timestamp when this update occurred
31555
+ * @returns Promise<void> Completion status
31556
+ */
31557
+ async updateWatchSession(sessionId, duration, endedAt) {
31558
+ const session = this.storage.getSession(sessionId);
31559
+ if (!session) {
31560
+ throw new Error(`Watch session ${sessionId} not found`);
31561
+ }
31562
+ // Update session
31563
+ this.storage.updateSession(sessionId, {
31564
+ watchSeconds: duration,
31565
+ endTime: endedAt,
31566
+ });
31567
+ }
31568
+ /**
31569
+ * Sync all pending watch sessions to backend
31570
+ * This function uses jitter delay and handles network resilience
31571
+ */
31572
+ syncPendingWatchSessions() {
31573
+ // Execute with jitter delay (5-30 seconds)
31574
+ const jitterDelay = getJitterDelay();
31575
+ this.client.log('room/RoomAnalytics: syncPendingWatchSessions called, jitter delay:', `${jitterDelay}ms`);
31576
+ setTimeout(async () => {
31577
+ this.client.log('room/RoomAnalytics: Jitter delay completed, starting sync process');
31578
+ try {
31579
+ // Reset any SYNCING sessions back to PENDING
31580
+ const syncingSessions = this.storage.getSyncingSessions();
31581
+ this.client.log('room/RoomAnalytics: SYNCING sessions to reset:', syncingSessions.length);
31582
+ syncingSessions.forEach(session => {
31583
+ this.storage.updateSession(session.sessionId, { syncState: 'PENDING' });
31584
+ });
31585
+ // Wait for network connection (max 60 seconds)
31586
+ await waitForNetwork(60000);
31587
+ this.client.log('room/RoomAnalytics: Network available');
31588
+ // Sync pending sessions
31589
+ this.client.log('room/RoomAnalytics: Calling syncWatchSessions()');
31590
+ await syncWatchSessions();
31591
+ this.client.log('room/RoomAnalytics: syncWatchSessions completed');
31592
+ }
31593
+ catch (error) {
31594
+ // Error is already handled in syncWatchSessions
31595
+ console.error('Failed to sync watch sessions:', error);
31596
+ }
31597
+ }, jitterDelay);
31598
+ }
31599
+ }
31616
31600
 
31617
- const communityLinkedObject = (community) => {
31618
- return Object.assign(Object.assign({}, community), { get categories() {
31601
+ const roomLinkedObject = (room) => {
31602
+ return Object.assign(Object.assign({}, room), { get post() {
31619
31603
  var _a;
31620
- return ((_a = community === null || community === void 0 ? void 0 : community.categoryIds) !== null && _a !== void 0 ? _a : [])
31621
- .map(categoryId => {
31622
- const cacheData = pullFromCache(['category', 'get', categoryId]);
31623
- if (cacheData === null || cacheData === void 0 ? void 0 : cacheData.data)
31624
- return categoryLinkedObject(cacheData.data);
31625
- return undefined;
31626
- })
31627
- .filter(category => !!category);
31604
+ if (room.referenceType !== 'post')
31605
+ return;
31606
+ return (_a = pullFromCache(['post', 'get', room.referenceId])) === null || _a === void 0 ? void 0 : _a.data;
31628
31607
  },
31629
- get avatar() {
31608
+ get community() {
31630
31609
  var _a;
31631
- if (!community.avatarFileId)
31632
- return undefined;
31633
- const avatar = (_a = pullFromCache([
31634
- 'file',
31635
- 'get',
31636
- community.avatarFileId,
31637
- ])) === null || _a === void 0 ? void 0 : _a.data;
31638
- return avatar;
31639
- }, createInvitations: async (userIds) => {
31640
- await createInvitations({
31641
- type: "communityMemberInvite" /* InvitationTypeEnum.CommunityMemberInvite */,
31642
- targetType: 'community',
31643
- targetId: community.communityId,
31644
- userIds,
31645
- });
31646
- }, getMemberInvitations: (params, callback) => {
31647
- return getInvitations$1(Object.assign(Object.assign({}, params), { targetId: community.communityId, targetType: 'community', type: "communityMemberInvite" /* InvitationTypeEnum.CommunityMemberInvite */ }), callback);
31648
- }, getInvitation: async () => {
31610
+ if (room.targetType !== 'community')
31611
+ return;
31612
+ return (_a = pullFromCache(['community', 'get', room.targetId])) === null || _a === void 0 ? void 0 : _a.data;
31613
+ },
31614
+ get user() {
31615
+ var _a;
31616
+ const user = (_a = pullFromCache(['user', 'get', room.createdBy])) === null || _a === void 0 ? void 0 : _a.data;
31617
+ return user ? userLinkedObject(user) : user;
31618
+ },
31619
+ get childRooms() {
31620
+ if (!room.childRoomIds || room.childRoomIds.length === 0)
31621
+ return [];
31622
+ return room.childRoomIds
31623
+ .map(id => {
31624
+ var _a;
31625
+ const roomCache = (_a = pullFromCache(['room', 'get', id])) === null || _a === void 0 ? void 0 : _a.data;
31626
+ if (!roomCache)
31627
+ return undefined;
31628
+ return roomLinkedObject(roomCache);
31629
+ })
31630
+ .filter(isNonNullable);
31631
+ }, participants: room.participants.map(participant => (Object.assign(Object.assign({}, participant), { get user() {
31632
+ var _a;
31633
+ const user = (_a = pullFromCache(['user', 'get', participant.userId])) === null || _a === void 0 ? void 0 : _a.data;
31634
+ return user ? userLinkedObject(user) : user;
31635
+ } }))), getLiveChat: () => getLiveChat(room), createInvitation: (userId) => createInvitations({
31636
+ type: "livestreamCohostInvite" /* InvitationTypeEnum.LivestreamCohostInvite */,
31637
+ targetType: 'room',
31638
+ targetId: room.roomId,
31639
+ userIds: [userId],
31640
+ }), getInvitations: async () => {
31649
31641
  const { data } = await getInvitation({
31650
- targetType: 'community',
31651
- targetId: community.communityId,
31642
+ targetId: room.roomId,
31643
+ targetType: 'room',
31644
+ type: "livestreamCohostInvite" /* InvitationTypeEnum.LivestreamCohostInvite */,
31652
31645
  });
31653
31646
  return data;
31654
- }, join: async () => joinRequest(community.communityId), getJoinRequests: (params, callback) => {
31655
- return getJoinRequests(Object.assign(Object.assign({}, params), { communityId: community.communityId }), callback);
31656
- }, getMyJoinRequest: async () => {
31657
- const { data } = await getMyJoinRequest(community.communityId);
31658
- return data;
31647
+ }, analytics() {
31648
+ // Use 'this' to avoid creating a new room object
31649
+ return new AmityRoomAnalytics(this);
31659
31650
  } });
31660
31651
  };
31661
31652
 
31653
+ const pollLinkedObject = (poll) => {
31654
+ return Object.assign(Object.assign({}, poll), { answers: poll.answers.map(answer => (Object.assign(Object.assign({}, answer), { get image() {
31655
+ var _a;
31656
+ if (!answer.fileId)
31657
+ return undefined;
31658
+ return (_a = pullFromCache(['file', 'get', answer.fileId])) === null || _a === void 0 ? void 0 : _a.data;
31659
+ } }))) });
31660
+ };
31661
+
31662
31662
  const productLinkedObject = (product) => {
31663
31663
  const analyticsEngineInstance = AnalyticsEngine$1.getInstance();
31664
31664
  return Object.assign(Object.assign({}, product), { analytics: {