@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.cjs.js CHANGED
@@ -334,8 +334,8 @@ exports.NotificationRolesFilterTypeEnum = void 0;
334
334
 
335
335
  function getVersion() {
336
336
  try {
337
- // the string ''v7.23.0-cjs'' should be replaced by actual value by @rollup/plugin-replace
338
- return 'v7.23.0-cjs';
337
+ // the string ''v7.24.0-cjs'' should be replaced by actual value by @rollup/plugin-replace
338
+ return 'v7.24.0-cjs';
339
339
  }
340
340
  catch (error) {
341
341
  return '__dev__';
@@ -13491,562 +13491,571 @@ var index$r = /*#__PURE__*/Object.freeze({
13491
13491
  getMyFollowInfo: getMyFollowInfo
13492
13492
  });
13493
13493
 
13494
- class StoryComputedValue {
13495
- constructor(targetId, lastStoryExpiresAt, lastStorySeenExpiresAt) {
13496
- this._syncingStoriesCount = 0;
13497
- this._errorStoriesCount = 0;
13498
- this._targetId = targetId;
13499
- this._lastStoryExpiresAt = lastStoryExpiresAt;
13500
- this._lastStorySeenExpiresAt = lastStorySeenExpiresAt;
13501
- this.cacheStoryExpireTime = pullFromCache([
13502
- "story-expire" /* STORY_KEY_CACHE.EXPIRE */,
13503
- this._targetId,
13504
- ]);
13505
- this.cacheStoreSeenTime = pullFromCache([
13506
- "story-last-seen" /* STORY_KEY_CACHE.LAST_SEEN */,
13507
- this._targetId,
13508
- ]);
13509
- this.getTotalStoryByStatus();
13510
- }
13511
- get lastStoryExpiresAt() {
13512
- return this._lastStoryExpiresAt ? new Date(this._lastStoryExpiresAt).getTime() : 0;
13513
- }
13514
- get lastStorySeenExpiresAt() {
13515
- return this._lastStorySeenExpiresAt ? new Date(this._lastStorySeenExpiresAt).getTime() : 0;
13516
- }
13517
- get localLastStoryExpires() {
13518
- var _a, _b;
13519
- return ((_a = this.cacheStoryExpireTime) === null || _a === void 0 ? void 0 : _a.data)
13520
- ? new Date((_b = this.cacheStoryExpireTime) === null || _b === void 0 ? void 0 : _b.data).getTime()
13521
- : 0;
13522
- }
13523
- get localLastStorySeenExpiresAt() {
13524
- var _a, _b;
13525
- 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;
13526
- }
13527
- get isContainUnSyncedStory() {
13528
- const currentSyncingState = pullFromCache([
13529
- "story-sync-state" /* STORY_KEY_CACHE.SYNC_STATE */,
13530
- this._targetId,
13531
- ]);
13532
- if (!(currentSyncingState === null || currentSyncingState === void 0 ? void 0 : currentSyncingState.data))
13533
- return false;
13534
- return ["syncing" /* Amity.SyncState.Syncing */, "error" /* Amity.SyncState.Error */].includes(currentSyncingState.data);
13535
- }
13536
- getLocalLastSortingDate() {
13537
- if (this.isContainUnSyncedStory) {
13538
- return this.localLastStoryExpires;
13539
- }
13540
- return this.lastStoryExpiresAt;
13541
- }
13542
- getHasUnseenFlag() {
13543
- const now = new Date().getTime();
13544
- const highestSeen = Math.max(this.lastStorySeenExpiresAt, this.localLastStorySeenExpiresAt);
13545
- pullFromCache([
13546
- "story-sync-state" /* STORY_KEY_CACHE.SYNC_STATE */,
13547
- this._targetId,
13494
+ /*
13495
+ * verifies membership status
13496
+ */
13497
+ function isMember(membership) {
13498
+ return membership !== 'none';
13499
+ }
13500
+ /*
13501
+ * checks if currently logged in user is part of the community
13502
+ */
13503
+ function isCurrentUserPartOfCommunity(c, m) {
13504
+ const { userId } = getActiveUser();
13505
+ return c.communityId === m.communityId && m.userId === userId;
13506
+ }
13507
+ /*
13508
+ * For mqtt events server will not send user specific data as it's broadcasted
13509
+ * to multiple users and it also does not include communityUser
13510
+ *
13511
+ * Client SDK needs to check for the existing isJoined field in cache data before calculating.
13512
+ * Althought this can be calculated, it's not scalable.
13513
+ */
13514
+ function updateMembershipStatus(communities, communityUsers) {
13515
+ return communities.map(c => {
13516
+ const cachedCommunity = pullFromCache([
13517
+ 'community',
13518
+ 'get',
13519
+ c.communityId,
13548
13520
  ]);
13549
- if (this.isContainUnSyncedStory) {
13550
- return this.localLastStoryExpires > now && this.localLastStoryExpires > highestSeen;
13551
- }
13552
- return this.lastStoryExpiresAt > now && this.lastStoryExpiresAt > highestSeen;
13553
- }
13554
- getTotalStoryByStatus() {
13555
- const stories = queryCache(["story" /* STORY_KEY_CACHE.STORY */, 'get']);
13556
- if (!stories) {
13557
- this._errorStoriesCount = 0;
13558
- this._syncingStoriesCount = 0;
13559
- return;
13521
+ if ((cachedCommunity === null || cachedCommunity === void 0 ? void 0 : cachedCommunity.data) && (cachedCommunity === null || cachedCommunity === void 0 ? void 0 : cachedCommunity.data.hasOwnProperty('isJoined'))) {
13522
+ return Object.assign(Object.assign({}, cachedCommunity.data), c);
13560
13523
  }
13561
- const groupByType = stories.reduce((acc, story) => {
13562
- const { data: { targetId, syncState, isDeleted }, } = story;
13563
- if (targetId === this._targetId && !isDeleted) {
13564
- acc[syncState] += 1;
13565
- }
13566
- return acc;
13567
- }, {
13568
- syncing: 0,
13569
- error: 0,
13570
- synced: 0,
13524
+ const isJoined = c.isJoined !== undefined
13525
+ ? c.isJoined
13526
+ : communityUsers.some(m => isCurrentUserPartOfCommunity(c, m) && isMember(m.communityMembership));
13527
+ return Object.assign(Object.assign({}, c), { isJoined });
13528
+ });
13529
+ }
13530
+
13531
+ const getMatchPostSetting = (value) => {
13532
+ var _a;
13533
+ return (_a = Object.keys(CommunityPostSettingMaps).find(key => value.needApprovalOnPostCreation ===
13534
+ CommunityPostSettingMaps[key].needApprovalOnPostCreation &&
13535
+ value.onlyAdminCanPost === CommunityPostSettingMaps[key].onlyAdminCanPost)) !== null && _a !== void 0 ? _a : DefaultCommunityPostSetting;
13536
+ };
13537
+ function addPostSetting({ communities }) {
13538
+ return communities.map((_a) => {
13539
+ var { needApprovalOnPostCreation, onlyAdminCanPost } = _a, restCommunityPayload = __rest(_a, ["needApprovalOnPostCreation", "onlyAdminCanPost"]);
13540
+ return (Object.assign({ postSetting: getMatchPostSetting({
13541
+ needApprovalOnPostCreation,
13542
+ onlyAdminCanPost,
13543
+ }) }, restCommunityPayload));
13544
+ });
13545
+ }
13546
+ const prepareCommunityPayload = (rawPayload) => {
13547
+ const communitiesWithPostSetting = addPostSetting({ communities: rawPayload.communities });
13548
+ // Convert users to internal format
13549
+ const internalUsers = rawPayload.users.map(convertRawUserToInternalUser);
13550
+ // map users with community
13551
+ const mappedCommunityUsers = rawPayload.communityUsers.map(communityUser => {
13552
+ const user = internalUsers.find(user => user.userId === communityUser.userId);
13553
+ return Object.assign(Object.assign({}, communityUser), { user });
13554
+ });
13555
+ const communityWithMembershipStatus = updateMembershipStatus(communitiesWithPostSetting, mappedCommunityUsers);
13556
+ return Object.assign(Object.assign({}, rawPayload), { users: rawPayload.users.map(convertRawUserToInternalUser), communities: communityWithMembershipStatus, communityUsers: mappedCommunityUsers });
13557
+ };
13558
+ const prepareCommunityJoinRequestPayload = (rawPayload) => {
13559
+ const mappedJoinRequests = rawPayload.joinRequests.map(joinRequest => {
13560
+ return Object.assign(Object.assign({}, joinRequest), { joinRequestId: joinRequest._id });
13561
+ });
13562
+ const users = rawPayload.users.map(convertRawUserToInternalUser);
13563
+ return Object.assign(Object.assign({}, rawPayload), { joinRequests: mappedJoinRequests, users });
13564
+ };
13565
+ const prepareCommunityMembershipPayload = (rawPayload) => {
13566
+ const communitiesWithPostSetting = addPostSetting({ communities: rawPayload.communities });
13567
+ // map users with community
13568
+ const mappedCommunityUsers = rawPayload.communityUsers.map(communityUser => {
13569
+ const user = rawPayload.users.find(user => user.userId === communityUser.userId);
13570
+ return Object.assign(Object.assign({}, communityUser), { user });
13571
+ });
13572
+ const communityWithMembershipStatus = updateMembershipStatus(communitiesWithPostSetting, mappedCommunityUsers);
13573
+ return Object.assign(Object.assign({}, rawPayload), { communities: communityWithMembershipStatus, communityUsers: mappedCommunityUsers });
13574
+ };
13575
+ const prepareCommunityRequest = (params) => {
13576
+ const { postSetting = undefined, storySetting } = params, restParam = __rest(params, ["postSetting", "storySetting"]);
13577
+ return Object.assign(Object.assign(Object.assign({}, restParam), (postSetting ? CommunityPostSettingMaps[postSetting] : undefined)), {
13578
+ // Convert story setting to the actual value. (Allow by default)
13579
+ allowCommentInStory: typeof (storySetting === null || storySetting === void 0 ? void 0 : storySetting.enableComment) === 'boolean' ? storySetting.enableComment : true });
13580
+ };
13581
+ const prepareSemanticSearchCommunityPayload = (_a) => {
13582
+ var communityPayload = __rest(_a, ["searchResult"]);
13583
+ const processedCommunityPayload = prepareCommunityPayload(communityPayload);
13584
+ return Object.assign({}, processedCommunityPayload);
13585
+ };
13586
+
13587
+ /* begin_public_function
13588
+ id: joinRequest.approve
13589
+ */
13590
+ /**
13591
+ * ```js
13592
+ * import { joinRequest } from '@amityco/ts-sdk-react-native'
13593
+ * const isAccepted = await joinRequest.approve()
13594
+ * ```
13595
+ *
13596
+ * Accepts a {@link Amity.JoinRequest} object
13597
+ *
13598
+ * @param joinRequest the {@link Amity.JoinRequest} to accept
13599
+ * @returns A success boolean if the {@link Amity.JoinRequest} was accepted
13600
+ *
13601
+ * @category Join Request API
13602
+ * @async
13603
+ */
13604
+ const approveJoinRequest = async (joinRequest) => {
13605
+ var _a;
13606
+ const client = getActiveClient();
13607
+ client.log('joinRequest/approveJoinRequest', joinRequest.joinRequestId);
13608
+ const { data } = await client.http.post(`/api/v4/communities/${joinRequest.targetId}/join/approve`, {
13609
+ userId: joinRequest.requestorInternalId,
13610
+ });
13611
+ const joinRequestCache = (_a = pullFromCache([
13612
+ 'joinRequest',
13613
+ 'get',
13614
+ joinRequest.joinRequestId,
13615
+ ])) === null || _a === void 0 ? void 0 : _a.data;
13616
+ if (joinRequestCache) {
13617
+ upsertInCache(['joinRequest', 'get', joinRequest.joinRequestId], {
13618
+ status: "approved" /* JoinRequestStatusEnum.Approved */,
13571
13619
  });
13572
- this._errorStoriesCount = groupByType.error;
13573
- this._syncingStoriesCount = groupByType.syncing;
13574
- }
13575
- get syncingStoriesCount() {
13576
- return this._syncingStoriesCount;
13577
- }
13578
- get failedStoriesCount() {
13579
- return this._errorStoriesCount;
13620
+ fireEvent('local.joinRequest.updated', [joinRequestCache]);
13580
13621
  }
13581
- }
13622
+ return data.success;
13623
+ };
13624
+ /* end_public_function */
13582
13625
 
13583
- const storyTargetLinkedObject = (storyTarget) => {
13584
- const { targetType, targetId, lastStoryExpiresAt, lastStorySeenExpiresAt, targetUpdatedAt, localFilter, } = storyTarget;
13585
- const computedValue = new StoryComputedValue(targetId, lastStoryExpiresAt, lastStorySeenExpiresAt);
13586
- return {
13587
- targetType,
13588
- targetId,
13589
- lastStoryExpiresAt,
13590
- updatedAt: targetUpdatedAt,
13591
- // Additional data
13592
- hasUnseen: computedValue.getHasUnseenFlag(),
13593
- syncingStoriesCount: computedValue.syncingStoriesCount,
13594
- failedStoriesCount: computedValue.failedStoriesCount,
13595
- localFilter,
13596
- localLastExpires: computedValue.localLastStoryExpires,
13597
- localLastSeen: computedValue.localLastStorySeenExpiresAt,
13598
- localSortingDate: computedValue.getLocalLastSortingDate(),
13599
- };
13626
+ /* begin_public_function
13627
+ id: joinRequest.cancel
13628
+ */
13629
+ /**
13630
+ * ```js
13631
+ * import { joinRequest } from '@amityco/ts-sdk-react-native'
13632
+ * const isCanceled = await joinRequest.cancel()
13633
+ * ```
13634
+ *
13635
+ * Cancels a {@link Amity.JoinRequest} object
13636
+ *
13637
+ * @param joinRequest the {@link Amity.JoinRequest} to cancel
13638
+ * @returns A success boolean if the {@link Amity.JoinRequest} was canceled
13639
+ *
13640
+ * @category Join Request API
13641
+ * @async
13642
+ */
13643
+ const cancelJoinRequest = async (joinRequest) => {
13644
+ var _a;
13645
+ const client = getActiveClient();
13646
+ client.log('joinRequest/cancelJoinRequest', joinRequest.joinRequestId);
13647
+ const { data } = await client.http.delete(`/api/v4/communities/${joinRequest.targetId}/join`);
13648
+ const joinRequestCache = (_a = pullFromCache([
13649
+ 'joinRequest',
13650
+ 'get',
13651
+ joinRequest.joinRequestId,
13652
+ ])) === null || _a === void 0 ? void 0 : _a.data;
13653
+ if (joinRequestCache) {
13654
+ upsertInCache(['joinRequest', 'get', joinRequest.joinRequestId], {
13655
+ status: "cancelled" /* JoinRequestStatusEnum.Cancelled */,
13656
+ });
13657
+ fireEvent('local.joinRequest.deleted', [joinRequestCache]);
13658
+ }
13659
+ return data.success;
13600
13660
  };
13661
+ /* end_public_function */
13601
13662
 
13602
- const storyLinkedObject = (story) => {
13603
- const analyticsEngineInstance = AnalyticsEngine$1.getInstance();
13604
- const storyTargetCache = pullFromCache([
13605
- "storyTarget" /* STORY_KEY_CACHE.STORY_TARGET */,
13663
+ /* begin_public_function
13664
+ id: joinRequest.reject
13665
+ */
13666
+ /**
13667
+ * ```js
13668
+ * import { joinRequest } from '@amityco/ts-sdk-react-native'
13669
+ * const isRejected = await joinRequest.reject()
13670
+ * ```
13671
+ *
13672
+ * Rejects a {@link Amity.JoinRequest} object
13673
+ *
13674
+ * @param joinRequest the {@link Amity.JoinRequest} to reject
13675
+ * @returns A success boolean if the {@link Amity.JoinRequest} was rejected
13676
+ *
13677
+ * @category Join Request API
13678
+ * @async
13679
+ */
13680
+ const rejectJoinRequest = async (joinRequest) => {
13681
+ var _a;
13682
+ const client = getActiveClient();
13683
+ client.log('joinRequest/rejectJoinRequest', joinRequest.joinRequestId);
13684
+ const { data } = await client.http.post(`/api/v4/communities/${joinRequest.targetId}/join/reject`, {
13685
+ userId: joinRequest.requestorInternalId,
13686
+ });
13687
+ const joinRequestCache = (_a = pullFromCache([
13688
+ 'joinRequest',
13606
13689
  'get',
13607
- story.targetId,
13608
- ]);
13609
- const communityCacheData = pullFromCache(['community', 'get', story.targetId]);
13610
- return Object.assign(Object.assign({}, story), { analytics: {
13611
- markAsSeen: () => {
13612
- if (!story.expiresAt)
13613
- return;
13614
- if (story.syncState !== "synced" /* Amity.SyncState.Synced */)
13615
- return;
13616
- analyticsEngineInstance.markStoryAsViewed(story);
13617
- },
13618
- markLinkAsClicked: () => {
13619
- if (!story.expiresAt)
13620
- return;
13621
- if (story.syncState !== "synced" /* Amity.SyncState.Synced */)
13622
- return;
13623
- analyticsEngineInstance.markStoryAsClicked(story);
13624
- },
13625
- }, get videoData() {
13626
- var _a, _b;
13627
- const cache = pullFromCache([
13628
- 'file',
13629
- 'get',
13630
- (_b = (_a = story.data) === null || _a === void 0 ? void 0 : _a.videoFileId) === null || _b === void 0 ? void 0 : _b.original,
13631
- ]);
13632
- if (!cache)
13633
- return undefined;
13634
- const { data } = cache;
13635
- return data || undefined;
13636
- },
13637
- get imageData() {
13638
- var _a, _b;
13639
- if (!((_a = story.data) === null || _a === void 0 ? void 0 : _a.fileId))
13640
- return undefined;
13641
- const cache = pullFromCache(['file', 'get', (_b = story.data) === null || _b === void 0 ? void 0 : _b.fileId]);
13642
- if (!cache)
13643
- return undefined;
13644
- const { data } = cache;
13645
- if (!data)
13646
- return undefined;
13647
- return Object.assign(Object.assign({}, data), { fileUrl: `${data.fileUrl}?size=full` });
13648
- },
13649
- get community() {
13650
- if (story.targetType !== 'community')
13651
- return undefined;
13652
- if (!communityCacheData)
13653
- return undefined;
13654
- return (communityCacheData === null || communityCacheData === void 0 ? void 0 : communityCacheData.data) || undefined;
13655
- },
13656
- get communityCategories() {
13657
- if (story.targetType !== 'community')
13658
- return undefined;
13659
- if (!communityCacheData)
13660
- return undefined;
13661
- const { data: { categoryIds }, } = communityCacheData;
13662
- if (categoryIds.length === 0)
13690
+ joinRequest.joinRequestId,
13691
+ ])) === null || _a === void 0 ? void 0 : _a.data;
13692
+ if (joinRequestCache) {
13693
+ upsertInCache(['joinRequest', 'get', joinRequest.joinRequestId], {
13694
+ status: "rejected" /* JoinRequestStatusEnum.Rejected */,
13695
+ });
13696
+ fireEvent('local.joinRequest.updated', [joinRequestCache]);
13697
+ }
13698
+ return data.success;
13699
+ };
13700
+ /* end_public_function */
13701
+
13702
+ const joinRequestLinkedObject = (joinRequest) => {
13703
+ return Object.assign(Object.assign({}, joinRequest), { get user() {
13704
+ var _a;
13705
+ const user = (_a = pullFromCache([
13706
+ 'user',
13707
+ 'get',
13708
+ joinRequest.requestorPublicId,
13709
+ ])) === null || _a === void 0 ? void 0 : _a.data;
13710
+ if (!user)
13663
13711
  return undefined;
13664
- return categoryIds
13665
- .map(categoryId => {
13666
- const categoryCacheData = pullFromCache(['category', 'get', categoryId]);
13667
- return (categoryCacheData === null || categoryCacheData === void 0 ? void 0 : categoryCacheData.data) || undefined;
13668
- })
13669
- .filter(category => category !== undefined);
13670
- },
13671
- get creator() {
13672
- const cacheData = pullFromCache(['user', 'get', story.creatorPublicId]);
13673
- if (!(cacheData === null || cacheData === void 0 ? void 0 : cacheData.data))
13674
- return;
13675
- return userLinkedObject(cacheData.data);
13676
- },
13677
- get storyTarget() {
13678
- if (!(storyTargetCache === null || storyTargetCache === void 0 ? void 0 : storyTargetCache.data))
13679
- return;
13680
- return storyTargetLinkedObject(storyTargetCache.data);
13681
- },
13682
- get isSeen() {
13683
- const cacheData = pullFromCache(["story-last-seen" /* STORY_KEY_CACHE.LAST_SEEN */, story.targetId]);
13684
- if (!(storyTargetCache === null || storyTargetCache === void 0 ? void 0 : storyTargetCache.data))
13685
- return false;
13686
- const localLastSeen = (cacheData === null || cacheData === void 0 ? void 0 : cacheData.data) ? new Date(cacheData.data).getTime() : 0;
13687
- const serverLastSeen = new Date(storyTargetCache === null || storyTargetCache === void 0 ? void 0 : storyTargetCache.data.lastStorySeenExpiresAt).getTime() || 0;
13688
- const expiresAt = new Date(story.expiresAt).getTime();
13689
- return Math.max(localLastSeen, serverLastSeen) >= expiresAt;
13712
+ return userLinkedObject(user);
13713
+ }, cancel: async () => {
13714
+ await cancelJoinRequest(joinRequest);
13715
+ }, approve: async () => {
13716
+ await approveJoinRequest(joinRequest);
13717
+ }, reject: async () => {
13718
+ await rejectJoinRequest(joinRequest);
13690
13719
  } });
13691
13720
  };
13692
13721
 
13693
13722
  /* begin_public_function
13694
- id: channel.create
13723
+ id: community.getMyJoinRequest
13695
13724
  */
13696
13725
  /**
13697
13726
  * ```js
13698
- * import { createChannel } from '@amityco/ts-sdk-react-native'
13699
- * const created = await createChannel({ displayName: 'foobar' })
13727
+ * import { community } from '@amityco/ts-sdk-react-native'
13728
+ * const isJoined = await community.getMyJoinRequest('foobar')
13700
13729
  * ```
13701
13730
  *
13702
- * Creates an {@link Amity.Channel}
13731
+ * Joins a {@link Amity.Community} object
13703
13732
  *
13704
- * @param bundle The data necessary to create a new {@link Amity.Channel}
13705
- * @returns The newly created {@link Amity.Channel}
13733
+ * @param communityId the {@link Amity.Community} to join
13734
+ * @returns A success boolean if the {@link Amity.Community} was joined
13706
13735
  *
13707
- * @category Channel API
13736
+ * @category Community API
13708
13737
  * @async
13709
13738
  */
13710
- const createChannel = async (bundle) => {
13739
+ const getMyJoinRequest = async (communityId) => {
13711
13740
  const client = getActiveClient();
13712
- client.log('user/createChannel', bundle);
13713
- let payload;
13714
- /* c8 ignore next */
13715
- if ((bundle === null || bundle === void 0 ? void 0 : bundle.type) === 'conversation') {
13716
- payload = await client.http.post('/api/v3/channels/conversation', Object.assign(Object.assign({}, bundle), { isDistinct: true }));
13717
- }
13718
- else {
13719
- const { isPublic } = bundle, restParams = __rest(bundle, ["isPublic"]);
13720
- payload = await client.http.post('/api/v3/channels', Object.assign(Object.assign({}, restParams), {
13721
- /* c8 ignore next */
13722
- isPublic: (bundle === null || bundle === void 0 ? void 0 : bundle.type) === 'community' ? isPublic : undefined }));
13723
- }
13724
- const data = await prepareChannelPayload(payload.data);
13741
+ client.log('community/myJoinRequest', communityId);
13742
+ const { data: payload } = await client.http.get(`/api/v4/communities/${communityId}/join/me`);
13743
+ const data = prepareCommunityJoinRequestPayload(payload);
13725
13744
  const cachedAt = client.cache && Date.now();
13726
13745
  if (client.cache)
13727
13746
  ingestInCache(data, { cachedAt });
13728
- const { channels } = data;
13729
13747
  return {
13730
- data: constructChannelObject(channels[0]),
13748
+ data: data.joinRequests[0] ? joinRequestLinkedObject(data.joinRequests[0]) : undefined,
13731
13749
  cachedAt,
13732
13750
  };
13733
13751
  };
13734
13752
  /* end_public_function */
13735
13753
 
13754
+ /* begin_public_function
13755
+ id: community.join
13756
+ */
13736
13757
  /**
13737
13758
  * ```js
13738
- * import { getChannel } from '@amityco/ts-sdk-react-native'
13739
- * const channel = await getChannel('foobar')
13759
+ * import { community } from '@amityco/ts-sdk-react-native'
13760
+ * const isJoined = await community.join('foobar')
13740
13761
  * ```
13741
13762
  *
13742
- * Fetches a {@link Amity.Channel} object
13763
+ * Joins a {@link Amity.Community} object
13743
13764
  *
13744
- * @param channelId the ID of the {@link Amity.Channel} to fetch
13745
- * @returns the associated {@link Amity.Channel} object
13765
+ * @param communityId the {@link Amity.Community} to join
13766
+ * @returns A status join result
13746
13767
  *
13747
- * @category Channel API
13768
+ * @category Community API
13748
13769
  * @async
13749
13770
  */
13750
- const getChannel$1 = async (channelId) => {
13771
+ const joinRequest = async (communityId) => {
13772
+ var _a;
13751
13773
  const client = getActiveClient();
13752
- client.log('channel/getChannel', channelId);
13753
- isInTombstone('channel', channelId);
13754
- let data;
13755
- try {
13756
- const { data: payload } = await client.http.get(`/api/v3/channels/${encodeURIComponent(channelId)}`);
13757
- data = await prepareChannelPayload(payload);
13758
- if (client.isUnreadCountEnabled && client.getMarkerSyncConsistentMode()) {
13759
- prepareUnreadCountInfo(payload);
13774
+ client.log('community/joinRequest', communityId);
13775
+ const { data: payload } = await client.http.post(`/api/v4/communities/${communityId}/join`);
13776
+ const data = prepareCommunityJoinRequestPayload(payload);
13777
+ const cachedAt = client.cache && Date.now();
13778
+ if (client.cache)
13779
+ ingestInCache(data, { cachedAt });
13780
+ const status = data.joinRequests[0].status === "approved" /* JoinRequestStatusEnum.Approved */
13781
+ ? "success" /* JoinResultStatusEnum.Success */
13782
+ : "pending" /* JoinResultStatusEnum.Pending */;
13783
+ if (status === "success" /* JoinResultStatusEnum.Success */ && client.cache) {
13784
+ const community = (_a = pullFromCache(['community', 'get', communityId])) === null || _a === void 0 ? void 0 : _a.data;
13785
+ if (community) {
13786
+ const updatedCommunity = Object.assign(Object.assign({}, community), { isJoined: true });
13787
+ upsertInCache(['community', 'get', communityId], updatedCommunity);
13760
13788
  }
13761
13789
  }
13762
- catch (error) {
13763
- if (checkIfShouldGoesToTombstone(error === null || error === void 0 ? void 0 : error.code)) {
13764
- // NOTE: use channelPublicId as tombstone cache key since we cannot get the channelPrivateId that come along with channel data from server
13765
- pushToTombstone('channel', channelId);
13790
+ fireEvent('v4.local.community.joined', data.joinRequests);
13791
+ return status === "success" /* JoinResultStatusEnum.Success */
13792
+ ? { status }
13793
+ : { status, request: joinRequestLinkedObject(data.joinRequests[0]) };
13794
+ };
13795
+ /* end_public_function */
13796
+
13797
+ /**
13798
+ * TODO: handle cache receive cache option, and cache policy
13799
+ * TODO: check if querybyIds is supported
13800
+ */
13801
+ class JoinRequestsPaginationController extends PaginationController {
13802
+ async getRequest(queryParams, token) {
13803
+ const { limit = 20, communityId } = queryParams, params = __rest(queryParams, ["limit", "communityId"]);
13804
+ const options = token ? { token } : { limit };
13805
+ const { data: queryResponse } = await this.http.get(`/api/v4/communities/${communityId}/join`, {
13806
+ params: Object.assign(Object.assign({}, params), { options }),
13807
+ });
13808
+ return queryResponse;
13809
+ }
13810
+ }
13811
+
13812
+ var EnumJoinRequestAction$1;
13813
+ (function (EnumJoinRequestAction) {
13814
+ EnumJoinRequestAction["OnLocalJoinRequestCreated"] = "OnLocalJoinRequestCreated";
13815
+ EnumJoinRequestAction["OnLocalJoinRequestUpdated"] = "OnLocalJoinRequestUpdated";
13816
+ EnumJoinRequestAction["OnLocalJoinRequestDeleted"] = "OnLocalJoinRequestDeleted";
13817
+ })(EnumJoinRequestAction$1 || (EnumJoinRequestAction$1 = {}));
13818
+
13819
+ class JoinRequestsQueryStreamController extends QueryStreamController {
13820
+ constructor(query, cacheKey, notifyChange, preparePayload) {
13821
+ super(query, cacheKey);
13822
+ this.notifyChange = notifyChange;
13823
+ this.preparePayload = preparePayload;
13824
+ }
13825
+ async saveToMainDB(response) {
13826
+ const processedPayload = await this.preparePayload(response);
13827
+ const client = getActiveClient();
13828
+ const cachedAt = client.cache && Date.now();
13829
+ if (client.cache) {
13830
+ ingestInCache(processedPayload, { cachedAt });
13766
13831
  }
13767
- throw error;
13768
13832
  }
13769
- const cachedAt = client.cache && Date.now();
13770
- if (client.cache)
13771
- ingestInCache(data, { cachedAt });
13772
- const { channels } = data;
13773
- return {
13774
- data: channels.find(channel => channel.channelId === channelId),
13775
- cachedAt,
13833
+ appendToQueryStream(response, direction, refresh = false) {
13834
+ var _a, _b;
13835
+ if (refresh) {
13836
+ pushToCache(this.cacheKey, {
13837
+ data: response.joinRequests.map(joinRequest => getResolver('joinRequest')({ joinRequestId: joinRequest._id })),
13838
+ });
13839
+ }
13840
+ else {
13841
+ const collection = (_a = pullFromCache(this.cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
13842
+ const joinRequests = (_b = collection === null || collection === void 0 ? void 0 : collection.data) !== null && _b !== void 0 ? _b : [];
13843
+ pushToCache(this.cacheKey, Object.assign(Object.assign({}, collection), { data: [
13844
+ ...new Set([
13845
+ ...joinRequests,
13846
+ ...response.joinRequests.map(joinRequest => getResolver('joinRequest')({ joinRequestId: joinRequest._id })),
13847
+ ]),
13848
+ ] }));
13849
+ }
13850
+ }
13851
+ reactor(action) {
13852
+ return (joinRequest) => {
13853
+ var _a;
13854
+ const collection = (_a = pullFromCache(this.cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
13855
+ if (!collection)
13856
+ return;
13857
+ if (action === EnumJoinRequestAction$1.OnLocalJoinRequestUpdated) {
13858
+ const isExist = collection.data.find(id => id === joinRequest[0].joinRequestId);
13859
+ if (!isExist)
13860
+ return;
13861
+ }
13862
+ if (action === EnumJoinRequestAction$1.OnLocalJoinRequestCreated) {
13863
+ collection.data = [
13864
+ ...new Set([
13865
+ ...joinRequest.map(joinRequest => joinRequest.joinRequestId),
13866
+ ...collection.data,
13867
+ ]),
13868
+ ];
13869
+ }
13870
+ if (action === EnumJoinRequestAction$1.OnLocalJoinRequestDeleted) {
13871
+ collection.data = collection.data.filter(id => id !== joinRequest[0].joinRequestId);
13872
+ }
13873
+ pushToCache(this.cacheKey, collection);
13874
+ this.notifyChange({ origin: "event" /* Amity.LiveDataOrigin.EVENT */, loading: false });
13875
+ };
13876
+ }
13877
+ subscribeRTE(createSubscriber) {
13878
+ return createSubscriber.map(subscriber => subscriber.fn(this.reactor(subscriber.action)));
13879
+ }
13880
+ }
13881
+
13882
+ /**
13883
+ * ```js
13884
+ * import { onJoinRequestCreated } from '@amityco/ts-sdk-react-native'
13885
+ * const dispose = onJoinRequestCreated(data => {
13886
+ * // ...
13887
+ * })
13888
+ * ```
13889
+ *
13890
+ * Fired when an {@link Amity.CommunityJoinRequestPayload} has been created
13891
+ *
13892
+ * @param callback The function to call when the event was fired
13893
+ * @returns an {@link Amity.Unsubscriber} function to stop listening
13894
+ *
13895
+ * @category JoinRequest Events
13896
+ */
13897
+ const onJoinRequestCreated = (callback) => {
13898
+ const client = getActiveClient();
13899
+ const disposers = [
13900
+ createEventSubscriber(client, 'onJoinRequestCreated', 'local.joinRequest.created', payload => callback(payload)),
13901
+ ];
13902
+ return () => {
13903
+ disposers.forEach(fn => fn());
13776
13904
  };
13777
13905
  };
13906
+
13778
13907
  /**
13779
- * ```js
13780
- * import { getChannel } from '@amityco/ts-sdk-react-native'
13781
- * const channel = getChannel.locally('foobar')
13908
+ * ```js
13909
+ * import { onJoinRequestUpdated } from '@amityco/ts-sdk-react-native'
13910
+ * const dispose = onJoinRequestUpdated(data => {
13911
+ * // ...
13912
+ * })
13782
13913
  * ```
13783
13914
  *
13784
- * Fetches a {@link Amity.Channel} object from cache
13915
+ * Fired when an {@link Amity.CommunityJoinRequestPayload} has been created
13785
13916
  *
13786
- * @param channelId the ID of the {@link Amity.Channel} to fetch
13787
- * @returns the associated {@link Amity.Channel} object
13917
+ * @param callback The function to call when the event was fired
13918
+ * @returns an {@link Amity.Unsubscriber} function to stop listening
13788
13919
  *
13789
- * @category Channel API
13920
+ * @category JoinRequest Events
13790
13921
  */
13791
- getChannel$1.locally = (channelId) => {
13792
- var _a;
13922
+ const onJoinRequestUpdated = (callback) => {
13793
13923
  const client = getActiveClient();
13794
- client.log('channel/getChannel.locally', channelId);
13795
- if (!client.cache)
13796
- return;
13797
- // use queryCache to get all channel caches and filter by channelPublicId since we use channelPrivateId as cache key
13798
- const cached = (_a = queryCache(['channel', 'get'])) === null || _a === void 0 ? void 0 : _a.filter(({ data }) => {
13799
- return data.channelPublicId === channelId;
13800
- });
13801
- if (!cached || (cached === null || cached === void 0 ? void 0 : cached.length) === 0)
13802
- return;
13803
- return {
13804
- data: cached[0].data,
13805
- cachedAt: cached[0].cachedAt,
13924
+ const disposers = [
13925
+ createEventSubscriber(client, 'onJoinRequestUpdated', 'local.joinRequest.updated', payload => callback(payload)),
13926
+ ];
13927
+ return () => {
13928
+ disposers.forEach(fn => fn());
13806
13929
  };
13807
13930
  };
13808
13931
 
13809
13932
  /**
13810
13933
  * ```js
13811
- * import { getStream } from '@amityco/ts-sdk-react-native'
13812
- * const stream = await getStream('foobar')
13934
+ * import { onJoinRequestDeleted } from '@amityco/ts-sdk-react-native'
13935
+ * const dispose = onJoinRequestDeleted(data => {
13936
+ * // ...
13937
+ * })
13813
13938
  * ```
13814
13939
  *
13815
- * Fetches a {@link Amity.Channel} object linked with a current stream
13940
+ * Fired when an {@link Amity.CommunityJoinRequestPayload} has been created
13816
13941
  *
13817
- * @param stream {@link Amity.Stream} that has linked live channel
13818
- * @returns the associated {@link Amity.Channel<'live'>} object
13942
+ * @param callback The function to call when the event was fired
13943
+ * @returns an {@link Amity.Unsubscriber} function to stop listening
13819
13944
  *
13820
- * @category Stream API
13821
- * @async
13945
+ * @category JoinRequest Events
13822
13946
  */
13823
- const getLiveChat$1 = async (stream) => {
13824
- var _a;
13947
+ const onJoinRequestDeleted = (callback) => {
13825
13948
  const client = getActiveClient();
13826
- client.log('stream/getLiveChat', stream.streamId);
13827
- if (stream.channelId) {
13828
- const channel = (_a = pullFromCache([
13829
- 'channel',
13830
- 'get',
13831
- stream.channelId,
13832
- ])) === null || _a === void 0 ? void 0 : _a.data;
13833
- if (channel)
13834
- return channelLinkedObject(constructChannelObject(channel));
13835
- const { data } = await getChannel$1(stream.channelId);
13836
- return channelLinkedObject(constructChannelObject(data));
13837
- }
13838
- // No Channel ID
13839
- // streamer: create a new live channel
13840
- if (stream.userId === client.userId) {
13841
- const { data: channel } = await createChannel({
13842
- type: 'live',
13843
- postId: stream.postId,
13844
- videoStreamId: stream.streamId,
13845
- });
13846
- // Update channelId to stream object in cache
13847
- mergeInCache(['stream', 'get', stream.streamId], {
13848
- channelId: channel.channelId,
13849
- });
13850
- return channel;
13851
- }
13852
- // watcher: return undefined
13853
- return undefined;
13854
- };
13855
-
13856
- const GET_WATCHER_URLS = Symbol('getWatcherUrls');
13857
- const streamLinkedObject = (stream) => {
13858
- return Object.assign(Object.assign({}, stream), { get moderation() {
13859
- var _a;
13860
- return (_a = pullFromCache(['streamModeration', 'get', stream.streamId])) === null || _a === void 0 ? void 0 : _a.data;
13861
- },
13862
- get post() {
13863
- var _a;
13864
- if (stream.referenceType !== 'post')
13865
- return;
13866
- return (_a = pullFromCache(['post', 'get', stream.referenceId])) === null || _a === void 0 ? void 0 : _a.data;
13867
- },
13868
- get community() {
13869
- var _a;
13870
- if (stream.targetType !== 'community')
13871
- return;
13872
- return (_a = pullFromCache(['community', 'get', stream.targetId])) === null || _a === void 0 ? void 0 : _a.data;
13873
- },
13874
- get user() {
13875
- var _a;
13876
- return (_a = pullFromCache(['user', 'get', stream.userId])) === null || _a === void 0 ? void 0 : _a.data;
13877
- },
13878
- get childStreams() {
13879
- if (!stream.childStreamIds || stream.childStreamIds.length === 0)
13880
- return [];
13881
- return stream.childStreamIds
13882
- .map(id => {
13883
- var _a;
13884
- const streamCache = (_a = pullFromCache(['stream', 'get', id])) === null || _a === void 0 ? void 0 : _a.data;
13885
- if (!streamCache)
13886
- return undefined;
13887
- return streamLinkedObject(streamCache);
13888
- })
13889
- .filter(isNonNullable);
13890
- }, getLiveChat: () => getLiveChat$1(stream), isBanned: !stream.watcherUrl, watcherUrl: null, get [GET_WATCHER_URLS]() {
13891
- return stream.watcherUrl;
13892
- } });
13893
- };
13894
-
13895
- const categoryLinkedObject = (category) => {
13896
- return Object.assign(Object.assign({}, category), { get avatar() {
13897
- var _a;
13898
- if (!category.avatarFileId)
13899
- return undefined;
13900
- const avatar = (_a = pullFromCache([
13901
- 'file',
13902
- 'get',
13903
- `${category.avatarFileId}`,
13904
- ])) === null || _a === void 0 ? void 0 : _a.data;
13905
- return avatar;
13906
- } });
13907
- };
13908
-
13909
- const commentLinkedObject = (comment) => {
13910
- return Object.assign(Object.assign({}, comment), { get target() {
13911
- const commentTypes = {
13912
- type: comment.targetType,
13913
- };
13914
- if (comment.targetType === 'user') {
13915
- return Object.assign(Object.assign({}, commentTypes), { userId: comment.targetId });
13916
- }
13917
- if (commentTypes.type === 'content') {
13918
- return Object.assign(Object.assign({}, commentTypes), { contentId: comment.targetId });
13919
- }
13920
- if (commentTypes.type === 'community') {
13921
- const cacheData = pullFromCache([
13922
- 'communityUsers',
13923
- 'get',
13924
- `${comment.targetId}#${comment.userId}`,
13925
- ]);
13926
- return Object.assign(Object.assign({}, commentTypes), { communityId: comment.targetId, creatorMember: cacheData === null || cacheData === void 0 ? void 0 : cacheData.data });
13927
- }
13928
- return {
13929
- type: 'unknown',
13930
- };
13931
- },
13932
- get creator() {
13933
- const cacheData = pullFromCache(['user', 'get', comment.userId]);
13934
- if (cacheData === null || cacheData === void 0 ? void 0 : cacheData.data)
13935
- return userLinkedObject(cacheData.data);
13936
- return undefined;
13937
- },
13938
- get childrenComment() {
13939
- return comment.children
13940
- .map(childCommentId => {
13941
- const commentCache = pullFromCache([
13942
- 'comment',
13943
- 'get',
13944
- childCommentId,
13945
- ]);
13946
- if (!(commentCache === null || commentCache === void 0 ? void 0 : commentCache.data))
13947
- return;
13948
- return commentCache === null || commentCache === void 0 ? void 0 : commentCache.data;
13949
- })
13950
- .filter(isNonNullable)
13951
- .map(item => commentLinkedObject(item));
13952
- } });
13949
+ const disposers = [
13950
+ createEventSubscriber(client, 'onJoinRequestDeleted', 'local.joinRequest.deleted', payload => callback(payload)),
13951
+ ];
13952
+ return () => {
13953
+ disposers.forEach(fn => fn());
13954
+ };
13953
13955
  };
13954
13956
 
13955
- function isAmityImagePost(post) {
13956
- return !!(post.data &&
13957
- typeof post.data !== 'string' &&
13958
- 'fileId' in post.data &&
13959
- post.dataType === 'image');
13960
- }
13961
- function isAmityFilePost(post) {
13962
- return !!(post.data &&
13963
- typeof post.data !== 'string' &&
13964
- 'fileId' in post.data &&
13965
- post.dataType === 'file');
13966
- }
13967
- function isAmityVideoPost(post) {
13968
- return !!(post.data &&
13969
- typeof post.data !== 'string' &&
13970
- 'videoFileId' in post.data &&
13971
- 'thumbnailFileId' in post.data &&
13972
- post.dataType === 'video');
13973
- }
13974
- function isAmityLivestreamPost(post) {
13975
- return !!(post.data &&
13976
- typeof post.data !== 'string' &&
13977
- 'streamId' in post.data &&
13978
- post.dataType === 'liveStream');
13979
- }
13980
- function isAmityPollPost(post) {
13981
- return !!(post.data &&
13982
- typeof post.data !== 'string' &&
13983
- 'pollId' in post.data &&
13984
- post.dataType === 'poll');
13985
- }
13986
- function isAmityClipPost(post) {
13987
- return !!(post.data &&
13988
- typeof post.data !== 'string' &&
13989
- 'fileId' in post.data &&
13990
- post.dataType === 'clip');
13991
- }
13992
- function isAmityAudioPost(post) {
13993
- return !!(post.data &&
13994
- typeof post.data !== 'string' &&
13995
- 'fileId' in post.data &&
13996
- post.dataType === 'audio');
13997
- }
13998
- function isAmityRoomPost(post) {
13999
- return !!(post.data &&
14000
- typeof post.data !== 'string' &&
14001
- 'roomId' in post.data &&
14002
- post.dataType === 'room');
13957
+ class JoinRequestsLiveCollectionController extends LiveCollectionController {
13958
+ constructor(query, callback) {
13959
+ const queryStreamId = hash__default["default"](query);
13960
+ const cacheKey = ['joinRequest', 'collection', queryStreamId];
13961
+ const paginationController = new JoinRequestsPaginationController(query);
13962
+ super(paginationController, queryStreamId, cacheKey, callback);
13963
+ this.query = query;
13964
+ this.queryStreamController = new JoinRequestsQueryStreamController(this.query, this.cacheKey, this.notifyChange.bind(this), prepareCommunityJoinRequestPayload);
13965
+ this.callback = callback.bind(this);
13966
+ this.loadPage({ initial: true });
13967
+ }
13968
+ setup() {
13969
+ var _a;
13970
+ const collection = (_a = pullFromCache(this.cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
13971
+ if (!collection) {
13972
+ pushToCache(this.cacheKey, {
13973
+ data: [],
13974
+ params: this.query,
13975
+ });
13976
+ }
13977
+ }
13978
+ async persistModel(queryPayload) {
13979
+ await this.queryStreamController.saveToMainDB(queryPayload);
13980
+ }
13981
+ persistQueryStream({ response, direction, refresh, }) {
13982
+ const joinRequestResponse = response;
13983
+ this.queryStreamController.appendToQueryStream(joinRequestResponse, direction, refresh);
13984
+ }
13985
+ startSubscription() {
13986
+ return this.queryStreamController.subscribeRTE([
13987
+ { fn: onJoinRequestCreated, action: EnumJoinRequestAction$1.OnLocalJoinRequestCreated },
13988
+ { fn: onJoinRequestUpdated, action: EnumJoinRequestAction$1.OnLocalJoinRequestUpdated },
13989
+ { fn: onJoinRequestDeleted, action: EnumJoinRequestAction$1.OnLocalJoinRequestDeleted },
13990
+ ]);
13991
+ }
13992
+ notifyChange({ origin, loading, error }) {
13993
+ var _a;
13994
+ const collection = (_a = pullFromCache(this.cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
13995
+ if (!collection)
13996
+ return;
13997
+ const data = this.applyFilter(collection.data
13998
+ .map(id => pullFromCache(['joinRequest', 'get', id]))
13999
+ .filter(isNonNullable)
14000
+ .map(({ data }) => data)
14001
+ .map(joinRequestLinkedObject));
14002
+ if (!this.shouldNotify(data) && origin === 'event')
14003
+ return;
14004
+ this.callback({
14005
+ onNextPage: () => this.loadPage({ direction: "next" /* Amity.LiveCollectionPageDirection.NEXT */ }),
14006
+ data,
14007
+ hasNextPage: !!this.paginationController.getNextToken(),
14008
+ loading,
14009
+ error,
14010
+ });
14011
+ }
14012
+ applyFilter(data) {
14013
+ let joinRequest = data;
14014
+ if (this.query.status) {
14015
+ joinRequest = joinRequest.filter(joinRequest => joinRequest.status === this.query.status);
14016
+ }
14017
+ const sortFn = (() => {
14018
+ switch (this.query.sortBy) {
14019
+ case 'firstCreated':
14020
+ return sortByFirstCreated;
14021
+ case 'lastCreated':
14022
+ return sortByLastCreated;
14023
+ default:
14024
+ return sortByLastCreated;
14025
+ }
14026
+ })();
14027
+ joinRequest = joinRequest.sort(sortFn);
14028
+ return joinRequest;
14029
+ }
14003
14030
  }
14004
14031
 
14005
14032
  /**
14006
- * ```js
14007
- * import { RoomRepository } from '@amityco/ts-sdk-react-native'
14008
- * const stream = await getStream('foobar')
14009
- * ```
14033
+ * Get Join Requests
14010
14034
  *
14011
- * Fetches a {@link Amity.Channel} object linked with a current stream
14035
+ * @param params the query parameters
14036
+ * @param callback the callback to be called when the join request are updated
14037
+ * @returns joinRequests
14012
14038
  *
14013
- * @param stream {@link Amity.Stream} that has linked live channel
14014
- * @returns the associated {@link Amity.Channel<'live'>} object
14039
+ * @category joinRequest Live Collection
14015
14040
  *
14016
- * @category Stream API
14017
- * @async
14018
14041
  */
14019
- const getLiveChat = async (room) => {
14020
- var _a;
14021
- const client = getActiveClient();
14022
- client.log('room/getLiveChat', room.roomId);
14023
- if (room.liveChannelId) {
14024
- const channel = (_a = pullFromCache([
14025
- 'channel',
14026
- 'get',
14027
- room.liveChannelId,
14028
- ])) === null || _a === void 0 ? void 0 : _a.data;
14029
- if (channel)
14030
- return channelLinkedObject(constructChannelObject(channel));
14031
- const { data } = await getChannel$1(room.liveChannelId);
14032
- return channelLinkedObject(constructChannelObject(data));
14033
- }
14034
- // No Channel ID
14035
- // streamer: create a new live channel
14036
- if (room.createdBy === client.userId) {
14037
- const { data: channel } = await createChannel({
14038
- type: 'live',
14039
- postId: room.referenceId,
14040
- roomId: room.roomId,
14041
- });
14042
- // Update channelId to stream object in cache
14043
- mergeInCache(['room', 'get', room.roomId], {
14044
- liveChannelId: channel.channelId,
14045
- });
14046
- return channel;
14042
+ const getJoinRequests = (params, callback, config) => {
14043
+ const { log, cache } = getActiveClient();
14044
+ if (!cache) {
14045
+ console.log(ENABLE_CACHE_MESSAGE);
14047
14046
  }
14048
- // watcher: return undefined
14049
- return undefined;
14047
+ const timestamp = Date.now();
14048
+ log(`getJoinRequests: (tmpid: ${timestamp}) > listen`);
14049
+ const joinRequestLiveCollection = new JoinRequestsLiveCollectionController(params, callback);
14050
+ const disposers = joinRequestLiveCollection.startSubscription();
14051
+ const cacheKey = joinRequestLiveCollection.getCacheKey();
14052
+ disposers.push(() => {
14053
+ dropFromCache(cacheKey);
14054
+ });
14055
+ return () => {
14056
+ log(`getJoinRequests (tmpid: ${timestamp}) > dispose`);
14057
+ disposers.forEach(fn => fn());
14058
+ };
14050
14059
  };
14051
14060
 
14052
14061
  const convertRawInvitationToInternalInvitation = (rawInvitation) => {
@@ -14201,1391 +14210,1382 @@ const invitationLinkedObject = (invitation) => {
14201
14210
  } });
14202
14211
  };
14203
14212
 
14204
- /* begin_public_function
14205
- id: invitation.get
14206
- */
14213
+ /* begin_public_function
14214
+ id: invitation.get
14215
+ */
14216
+ /**
14217
+ * ```js
14218
+ * import { getInvitation } from '@amityco/ts-sdk-react-native'
14219
+ * const { invitation } = await getInvitation(targetType, targetId)
14220
+ * ```
14221
+ *
14222
+ * Get a {@link Amity.Invitation} object
14223
+ *
14224
+ * @param targetType The type of the target of the {@link Amity.Invitation}
14225
+ * @param targetId The ID of the target of the {@link Amity.Invitation}
14226
+ * @returns A {@link Amity.Invitation} object
14227
+ *
14228
+ * @category Invitation API
14229
+ * @async
14230
+ */
14231
+ const getInvitation = async (params) => {
14232
+ const client = getActiveClient();
14233
+ client.log('invitation/getInvitation', params.targetType, params.targetId, params.type);
14234
+ const { data: payload } = await client.http.get(`/api/v1/invitations/me`, { params });
14235
+ const data = prepareMyInvitationsPayload(payload);
14236
+ const cachedAt = client.cache && Date.now();
14237
+ if (client.cache)
14238
+ ingestInCache(data, { cachedAt });
14239
+ return {
14240
+ data: data.invitations[0] ? invitationLinkedObject(data.invitations[0]) : undefined,
14241
+ cachedAt,
14242
+ };
14243
+ };
14244
+ /* end_public_function */
14245
+
14246
+ var InvitationActionsEnum;
14247
+ (function (InvitationActionsEnum) {
14248
+ InvitationActionsEnum["OnLocalInvitationCreated"] = "onLocalInvitationCreated";
14249
+ InvitationActionsEnum["OnLocalInvitationUpdated"] = "onLocalInvitationUpdated";
14250
+ InvitationActionsEnum["OnLocalInvitationCanceled"] = "onLocalInvitationCanceled";
14251
+ })(InvitationActionsEnum || (InvitationActionsEnum = {}));
14252
+
14253
+ class InvitationsPaginationController extends PaginationController {
14254
+ async getRequest(queryParams, token) {
14255
+ const { limit = COLLECTION_DEFAULT_PAGINATION_LIMIT } = queryParams, params = __rest(queryParams, ["limit"]);
14256
+ const options = token ? { token } : { limit };
14257
+ const { data } = await this.http.get('/api/v1/invitations', { params: Object.assign(Object.assign({}, params), { options }) });
14258
+ return data;
14259
+ }
14260
+ }
14261
+
14262
+ class InvitationsQueryStreamController extends QueryStreamController {
14263
+ constructor(query, cacheKey, notifyChange, preparePayload) {
14264
+ super(query, cacheKey);
14265
+ this.notifyChange = notifyChange;
14266
+ this.preparePayload = preparePayload;
14267
+ }
14268
+ async saveToMainDB(response) {
14269
+ const processedPayload = await this.preparePayload(response);
14270
+ const client = getActiveClient();
14271
+ const cachedAt = client.cache && Date.now();
14272
+ if (client.cache) {
14273
+ ingestInCache(processedPayload, { cachedAt });
14274
+ }
14275
+ }
14276
+ appendToQueryStream(response, direction, refresh = false) {
14277
+ var _a, _b;
14278
+ if (refresh) {
14279
+ pushToCache(this.cacheKey, {
14280
+ data: response.invitations.map(getResolver('invitation')),
14281
+ });
14282
+ }
14283
+ else {
14284
+ const collection = (_a = pullFromCache(this.cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
14285
+ const invitations = (_b = collection === null || collection === void 0 ? void 0 : collection.data) !== null && _b !== void 0 ? _b : [];
14286
+ pushToCache(this.cacheKey, Object.assign(Object.assign({}, collection), { data: [
14287
+ ...new Set([...invitations, ...response.invitations.map(getResolver('invitation'))]),
14288
+ ] }));
14289
+ }
14290
+ }
14291
+ reactor(action) {
14292
+ return (invitations) => {
14293
+ var _a;
14294
+ const collection = (_a = pullFromCache(this.cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
14295
+ if (!collection)
14296
+ return;
14297
+ if (action === InvitationActionsEnum.OnLocalInvitationUpdated) {
14298
+ const isExist = collection.data.find(id => id === invitations[0].invitationId);
14299
+ if (!isExist)
14300
+ return;
14301
+ }
14302
+ if (action === InvitationActionsEnum.OnLocalInvitationCreated) {
14303
+ collection.data = [
14304
+ ...new Set([
14305
+ ...invitations.map(invitation => invitation.invitationId),
14306
+ ...collection.data,
14307
+ ]),
14308
+ ];
14309
+ }
14310
+ if (action === InvitationActionsEnum.OnLocalInvitationDeleted) {
14311
+ collection.data = collection.data.filter(id => id !== invitations[0].invitationId);
14312
+ }
14313
+ pushToCache(this.cacheKey, collection);
14314
+ this.notifyChange({ origin: "event" /* Amity.LiveDataOrigin.EVENT */, loading: false });
14315
+ };
14316
+ }
14317
+ subscribeRTE(createSubscriber) {
14318
+ return createSubscriber.map(subscriber => subscriber.fn(this.reactor(subscriber.action)));
14319
+ }
14320
+ }
14321
+
14322
+ /**
14323
+ * ```js
14324
+ * import { onLocalInvitationCreated } from '@amityco/ts-sdk-react-native'
14325
+ * const dispose = onLocalInvitationCreated(data => {
14326
+ * // ...
14327
+ * })
14328
+ * ```
14329
+ *
14330
+ * Fired when an {@link Amity.InvitationPayload} has been created
14331
+ *
14332
+ * @param callback The function to call when the event was fired
14333
+ * @returns an {@link Amity.Unsubscriber} function to stop listening
14334
+ *
14335
+ * @category Invitation Events
14336
+ */
14337
+ const onLocalInvitationCreated = (callback) => {
14338
+ const client = getActiveClient();
14339
+ const disposers = [
14340
+ createEventSubscriber(client, 'onLocalInvitationCreated', 'local.invitation.created', payload => callback(payload)),
14341
+ ];
14342
+ return () => {
14343
+ disposers.forEach(fn => fn());
14344
+ };
14345
+ };
14346
+
14347
+ /**
14348
+ * ```js
14349
+ * import { onLocalInvitationUpdated } from '@amityco/ts-sdk-react-native'
14350
+ * const dispose = onLocalInvitationUpdated(data => {
14351
+ * // ...
14352
+ * })
14353
+ * ```
14354
+ *
14355
+ * Fired when an {@link Amity.InvitationPayload} has been updated
14356
+ *
14357
+ * @param callback The function to call when the event was fired
14358
+ * @returns an {@link Amity.Unsubscriber} function to stop listening
14359
+ *
14360
+ * @category Invitation Events
14361
+ */
14362
+ const onLocalInvitationUpdated = (callback) => {
14363
+ const client = getActiveClient();
14364
+ const disposers = [
14365
+ createEventSubscriber(client, 'onLocalInvitationUpdated', 'local.invitation.updated', payload => callback(payload)),
14366
+ ];
14367
+ return () => {
14368
+ disposers.forEach(fn => fn());
14369
+ };
14370
+ };
14371
+
14207
14372
  /**
14208
14373
  * ```js
14209
- * import { getInvitation } from '@amityco/ts-sdk-react-native'
14210
- * const { invitation } = await getInvitation(targetType, targetId)
14374
+ * import { onLocalInvitationCanceled } from '@amityco/ts-sdk-react-native'
14375
+ * const dispose = onLocalInvitationCanceled(data => {
14376
+ * // ...
14377
+ * })
14211
14378
  * ```
14212
14379
  *
14213
- * Get a {@link Amity.Invitation} object
14380
+ * Fired when an {@link Amity.InvitationPayload} has been deleted
14214
14381
  *
14215
- * @param targetType The type of the target of the {@link Amity.Invitation}
14216
- * @param targetId The ID of the target of the {@link Amity.Invitation}
14217
- * @returns A {@link Amity.Invitation} object
14382
+ * @param callback The function to call when the event was fired
14383
+ * @returns an {@link Amity.Unsubscriber} function to stop listening
14218
14384
  *
14219
- * @category Invitation API
14220
- * @async
14385
+ * @category Invitation Events
14221
14386
  */
14222
- const getInvitation = async (params) => {
14387
+ const onLocalInvitationCanceled = (callback) => {
14223
14388
  const client = getActiveClient();
14224
- client.log('invitation/getInvitation', params.targetType, params.targetId, params.type);
14225
- const { data: payload } = await client.http.get(`/api/v1/invitations/me`, { params });
14226
- const data = prepareMyInvitationsPayload(payload);
14227
- const cachedAt = client.cache && Date.now();
14228
- if (client.cache)
14229
- ingestInCache(data, { cachedAt });
14230
- return {
14231
- data: data.invitations[0] ? invitationLinkedObject(data.invitations[0]) : undefined,
14232
- cachedAt,
14389
+ const disposers = [
14390
+ createEventSubscriber(client, 'onLocalInvitationCanceled', 'local.invitation.canceled', payload => callback(payload)),
14391
+ ];
14392
+ return () => {
14393
+ disposers.forEach(fn => fn());
14233
14394
  };
14234
14395
  };
14235
- /* end_public_function */
14236
14396
 
14237
- /**
14238
- * WatchSessionStorage manages watch session data in memory
14239
- * Similar to UsageCollector for stream watch minutes
14240
- */
14241
- class WatchSessionStorage {
14242
- constructor() {
14243
- this.sessions = new Map();
14244
- }
14245
- /**
14246
- * Add a new watch session
14247
- */
14248
- addSession(session) {
14249
- this.sessions.set(session.sessionId, session);
14250
- }
14251
- /**
14252
- * Get a watch session by sessionId
14253
- */
14254
- getSession(sessionId) {
14255
- return this.sessions.get(sessionId);
14397
+ class InvitationsLiveCollectionController extends LiveCollectionController {
14398
+ constructor(query, callback) {
14399
+ const queryStreamId = hash__default["default"](query);
14400
+ const cacheKey = ['invitation', 'collection', queryStreamId];
14401
+ const paginationController = new InvitationsPaginationController(query);
14402
+ super(paginationController, queryStreamId, cacheKey, callback);
14403
+ this.query = query;
14404
+ this.queryStreamController = new InvitationsQueryStreamController(this.query, this.cacheKey, this.notifyChange.bind(this), prepareInvitationPayload);
14405
+ this.callback = callback.bind(this);
14406
+ this.loadPage({ initial: true });
14256
14407
  }
14257
- /**
14258
- * Update a watch session
14259
- */
14260
- updateSession(sessionId, updates) {
14261
- const session = this.sessions.get(sessionId);
14262
- if (session) {
14263
- this.sessions.set(sessionId, Object.assign(Object.assign({}, session), updates));
14408
+ setup() {
14409
+ var _a;
14410
+ const collection = (_a = pullFromCache(this.cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
14411
+ if (!collection) {
14412
+ pushToCache(this.cacheKey, {
14413
+ data: [],
14414
+ params: this.query,
14415
+ });
14264
14416
  }
14265
14417
  }
14266
- /**
14267
- * Get all sessions with a specific sync state
14268
- */
14269
- getSessionsByState(state) {
14270
- return Array.from(this.sessions.values()).filter(session => session.syncState === state);
14271
- }
14272
- /**
14273
- * Delete a session
14274
- */
14275
- deleteSession(sessionId) {
14276
- this.sessions.delete(sessionId);
14277
- }
14278
- /**
14279
- * Get all pending sessions
14280
- */
14281
- getPendingSessions() {
14282
- return this.getSessionsByState('PENDING');
14283
- }
14284
- /**
14285
- * Get all syncing sessions
14286
- */
14287
- getSyncingSessions() {
14288
- return this.getSessionsByState('SYNCING');
14289
- }
14290
- }
14291
- // Singleton instance
14292
- let storageInstance = null;
14293
- const getWatchSessionStorage = () => {
14294
- if (!storageInstance) {
14295
- storageInstance = new WatchSessionStorage();
14296
- }
14297
- return storageInstance;
14298
- };
14299
-
14300
- 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-----";
14301
- /*
14302
- * The crypto algorithm used for importing key and signing string
14303
- */
14304
- const ALGORITHM = {
14305
- name: 'RSASSA-PKCS1-v1_5',
14306
- hash: { name: 'SHA-256' },
14307
- };
14308
- /*
14309
- * IMPORTANT!
14310
- * If you are recieving key from other platforms use an online tool to convert
14311
- * the PKCS1 to PKCS8. For instance the key from Android SDK is of the format
14312
- * PKCS1.
14313
- *
14314
- * If recieving from the platform, verify if it's already in the expected
14315
- * format. Otherwise the crypto.subtle.importKey will throw a DOMException
14316
- */
14317
- const PRIVATE_KEY_SIGNATURE = 'pkcs8';
14318
- /*
14319
- * Ensure that the private key in the .env follows this format
14320
- */
14321
- const PEM_HEADER = '-----BEGIN PRIVATE KEY-----';
14322
- const PEM_FOOTER = '-----END PRIVATE KEY-----';
14323
- /*
14324
- * The crypto.subtle.sign function returns an ArrayBuffer whereas the server
14325
- * expects a base64 string. This util helps facilitate that process
14326
- */
14327
- function base64FromArrayBuffer(buffer) {
14328
- const uint8Array = new Uint8Array(buffer);
14329
- let binary = '';
14330
- uint8Array.forEach(byte => {
14331
- binary += String.fromCharCode(byte);
14332
- });
14333
- return jsBase64.btoa(binary);
14334
- }
14335
- /*
14336
- * Encode ASN.1 length field
14337
- */
14338
- function encodeLength(length) {
14339
- if (length < 128) {
14340
- return new Uint8Array([length]);
14418
+ async persistModel(queryPayload) {
14419
+ await this.queryStreamController.saveToMainDB(queryPayload);
14341
14420
  }
14342
- if (length < 256) {
14343
- return new Uint8Array([0x81, length]);
14421
+ persistQueryStream({ response, direction, refresh, }) {
14422
+ this.queryStreamController.appendToQueryStream(response, direction, refresh);
14344
14423
  }
14345
- // eslint-disable-next-line no-bitwise
14346
- return new Uint8Array([0x82, (length >> 8) & 0xff, length & 0xff]);
14347
- }
14348
- /*
14349
- * Convert PKCS1 private key to PKCS8 format
14350
- * PKCS1 is RSA-specific format, PKCS8 is generic format that crypto.subtle requires
14351
- * Android uses PKCS8EncodedKeySpec which expects PKCS8 format
14352
- */
14353
- function pkcs1ToPkcs8(pkcs1) {
14354
- // Algorithm identifier for RSA
14355
- const algorithmIdentifier = new Uint8Array([
14356
- 0x30,
14357
- 0x0d,
14358
- 0x06,
14359
- 0x09,
14360
- 0x2a,
14361
- 0x86,
14362
- 0x48,
14363
- 0x86,
14364
- 0xf7,
14365
- 0x0d,
14366
- 0x01,
14367
- 0x01,
14368
- 0x01,
14369
- 0x05,
14370
- 0x00, // NULL
14371
- ]);
14372
- // Version (INTEGER 0)
14373
- const version = new Uint8Array([0x02, 0x01, 0x00]);
14374
- // OCTET STRING tag + length + pkcs1 data
14375
- const octetStringTag = 0x04;
14376
- const octetStringLength = encodeLength(pkcs1.length);
14377
- // Calculate total content length (version + algorithm + octet string)
14378
- const contentLength = version.length + algorithmIdentifier.length + 1 + octetStringLength.length + pkcs1.length;
14379
- // SEQUENCE tag + length
14380
- const sequenceTag = 0x30;
14381
- const sequenceLength = encodeLength(contentLength);
14382
- // Build the PKCS8 structure
14383
- const pkcs8 = new Uint8Array(1 + sequenceLength.length + contentLength);
14384
- let offset = 0;
14385
- pkcs8[offset] = sequenceTag;
14386
- offset += 1;
14387
- pkcs8.set(sequenceLength, offset);
14388
- offset += sequenceLength.length;
14389
- pkcs8.set(version, offset);
14390
- offset += version.length;
14391
- pkcs8.set(algorithmIdentifier, offset);
14392
- offset += algorithmIdentifier.length;
14393
- pkcs8[offset] = octetStringTag;
14394
- offset += 1;
14395
- pkcs8.set(octetStringLength, offset);
14396
- offset += octetStringLength.length;
14397
- pkcs8.set(pkcs1, offset);
14398
- return pkcs8;
14399
- }
14400
- async function importPrivateKey(keyString) {
14401
- // Remove PEM headers if present and any whitespace
14402
- let base64Key = keyString;
14403
- if (keyString.includes(PEM_HEADER)) {
14404
- base64Key = keyString
14405
- .substring(PEM_HEADER.length, keyString.length - PEM_FOOTER.length)
14406
- .replace(/\s/g, '');
14424
+ startSubscription() {
14425
+ return this.queryStreamController.subscribeRTE([
14426
+ {
14427
+ fn: onLocalInvitationCreated,
14428
+ action: InvitationActionsEnum.OnLocalInvitationCreated,
14429
+ },
14430
+ {
14431
+ fn: onLocalInvitationUpdated,
14432
+ action: InvitationActionsEnum.OnLocalInvitationUpdated,
14433
+ },
14434
+ {
14435
+ fn: onLocalInvitationCanceled,
14436
+ action: InvitationActionsEnum.OnLocalInvitationCanceled,
14437
+ },
14438
+ ]);
14407
14439
  }
14408
- else {
14409
- base64Key = keyString.replace(/\s/g, '');
14440
+ notifyChange({ origin, loading, error }) {
14441
+ var _a, _b;
14442
+ const collection = (_a = pullFromCache(this.cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
14443
+ if (!collection)
14444
+ return;
14445
+ const data = this.applyFilter((_b = collection.data
14446
+ .map(id => pullFromCache(['invitation', 'get', id]))
14447
+ .filter(isNonNullable)
14448
+ .map(({ data }) => invitationLinkedObject(data))) !== null && _b !== void 0 ? _b : []);
14449
+ if (!this.shouldNotify(data) && origin === 'event')
14450
+ return;
14451
+ this.callback({
14452
+ onNextPage: () => this.loadPage({ direction: "next" /* Amity.LiveCollectionPageDirection.NEXT */ }),
14453
+ data,
14454
+ hasNextPage: !!this.paginationController.getNextToken(),
14455
+ loading,
14456
+ error,
14457
+ });
14410
14458
  }
14411
- // Base64 decode to get binary data
14412
- const binaryDerString = jsBase64.atob(base64Key);
14413
- // Convert to Uint8Array for manipulation
14414
- const pkcs1 = new Uint8Array(binaryDerString.length);
14415
- for (let i = 0; i < binaryDerString.length; i += 1) {
14416
- pkcs1[i] = binaryDerString.charCodeAt(i);
14459
+ applyFilter(data) {
14460
+ let invitations = data;
14461
+ if (this.query.targetId) {
14462
+ invitations = invitations.filter(invitation => invitation.targetId === this.query.targetId);
14463
+ }
14464
+ if (this.query.statuses) {
14465
+ invitations = invitations.filter(invitation => { var _a; return (_a = this.query.statuses) === null || _a === void 0 ? void 0 : _a.includes(invitation.status); });
14466
+ }
14467
+ if (this.query.targetType) {
14468
+ invitations = invitations.filter(invitation => invitation.targetType === this.query.targetType);
14469
+ }
14470
+ if (this.query.type) {
14471
+ invitations = invitations.filter(invitation => invitation.type === this.query.type);
14472
+ }
14473
+ const sortFn = (() => {
14474
+ switch (this.query.sortBy) {
14475
+ case 'firstCreated':
14476
+ return sortByFirstCreated;
14477
+ case 'lastCreated':
14478
+ return sortByLastCreated;
14479
+ default:
14480
+ return sortByLastCreated;
14481
+ }
14482
+ })();
14483
+ invitations = invitations.sort(sortFn);
14484
+ return invitations;
14417
14485
  }
14418
- // Convert PKCS1 to PKCS8 (crypto.subtle requires PKCS8)
14419
- const pkcs8 = pkcs1ToPkcs8(pkcs1);
14420
- // Import the key
14421
- const key = await crypto.subtle.importKey(PRIVATE_KEY_SIGNATURE, pkcs8.buffer, ALGORITHM, false, ['sign']);
14422
- return key;
14423
- }
14424
- async function createSignature({ timestamp, rooms, }) {
14425
- const dataStr = rooms
14426
- .map(item => Object.keys(item)
14427
- .sort()
14428
- .map(key => `${key}=${item[key]}`)
14429
- .join('&'))
14430
- .join(';');
14431
- /*
14432
- * nonceStr needs to be unique for each request
14433
- */
14434
- const nonceStr = uuid__default["default"].v4();
14435
- const signStr = `nonceStr=${nonceStr}&timestamp=${timestamp}&data=${dataStr}==`;
14436
- const encoder = new TextEncoder();
14437
- const data = encoder.encode(signStr);
14438
- const key = await importPrivateKey(privateKey);
14439
- const sign = await crypto.subtle.sign(ALGORITHM, key, data);
14440
- return { signature: base64FromArrayBuffer(sign), nonceStr };
14441
14486
  }
14442
14487
 
14443
14488
  /**
14444
- * Sync pending watch sessions to backend
14445
- * This function implements the full sync flow with network resilience
14489
+ * Get invitations
14490
+ *
14491
+ * @param params the query parameters
14492
+ * @param callback the callback to be called when the invitations are updated
14493
+ * @returns invitations
14494
+ *
14495
+ * @category Invitation Live Collection
14496
+ *
14446
14497
  */
14447
- async function syncWatchSessions() {
14448
- const storage = getWatchSessionStorage();
14449
- // Get all pending sessions
14450
- const pendingSessions = storage.getPendingSessions();
14451
- if (pendingSessions.length === 0) {
14452
- return true;
14498
+ const getInvitations$1 = (params, callback, config) => {
14499
+ const { log, cache } = getActiveClient();
14500
+ if (!cache) {
14501
+ console.log(ENABLE_CACHE_MESSAGE);
14453
14502
  }
14454
- try {
14455
- const timestamp = new Date().toISOString();
14456
- // Convert sessions to API format - always include all fields like syncUsage does
14457
- const rooms = pendingSessions.map(session => ({
14458
- sessionId: session.sessionId,
14459
- roomId: session.roomId,
14460
- watchSeconds: session.watchSeconds,
14461
- startTime: session.startTime.toISOString(),
14462
- endTime: session.endTime ? session.endTime.toISOString() : '',
14463
- }));
14464
- // Create signature (reuse from stream feature) - pass directly like syncUsage
14465
- const signatureData = await createSignature({
14466
- timestamp,
14467
- rooms,
14468
- });
14469
- if (!signatureData || !signatureData.signature) {
14470
- throw new Error('Signature is undefined');
14471
- }
14472
- // Update sync state to SYNCING
14473
- pendingSessions.forEach(session => {
14474
- storage.updateSession(session.sessionId, { syncState: 'SYNCING' });
14475
- });
14476
- const payload = {
14477
- signature: signatureData.signature,
14478
- nonceStr: signatureData.nonceStr,
14479
- timestamp,
14480
- rooms,
14481
- };
14482
- const client = getActiveClient();
14483
- // Send to backend
14484
- await client.http.post('/api/v3/user-event/room', payload);
14485
- // Success - update to SYNCED
14486
- pendingSessions.forEach(session => {
14487
- storage.updateSession(session.sessionId, {
14488
- syncState: 'SYNCED',
14489
- syncedAt: new Date(),
14503
+ const timestamp = Date.now();
14504
+ log(`getInvitations: (tmpid: ${timestamp}) > listen`);
14505
+ const invitationsLiveCollection = new InvitationsLiveCollectionController(params, callback);
14506
+ const disposers = invitationsLiveCollection.startSubscription();
14507
+ const cacheKey = invitationsLiveCollection.getCacheKey();
14508
+ disposers.push(() => {
14509
+ dropFromCache(cacheKey);
14510
+ });
14511
+ return () => {
14512
+ log(`getInvitations (tmpid: ${timestamp}) > dispose`);
14513
+ disposers.forEach(fn => fn());
14514
+ };
14515
+ };
14516
+
14517
+ const categoryLinkedObject = (category) => {
14518
+ return Object.assign(Object.assign({}, category), { get avatar() {
14519
+ var _a;
14520
+ if (!category.avatarFileId)
14521
+ return undefined;
14522
+ const avatar = (_a = pullFromCache([
14523
+ 'file',
14524
+ 'get',
14525
+ `${category.avatarFileId}`,
14526
+ ])) === null || _a === void 0 ? void 0 : _a.data;
14527
+ return avatar;
14528
+ } });
14529
+ };
14530
+
14531
+ const communityLinkedObject = (community) => {
14532
+ return Object.assign(Object.assign({}, community), { get categories() {
14533
+ var _a;
14534
+ return ((_a = community === null || community === void 0 ? void 0 : community.categoryIds) !== null && _a !== void 0 ? _a : [])
14535
+ .map(categoryId => {
14536
+ const cacheData = pullFromCache(['category', 'get', categoryId]);
14537
+ if (cacheData === null || cacheData === void 0 ? void 0 : cacheData.data)
14538
+ return categoryLinkedObject(cacheData.data);
14539
+ return undefined;
14540
+ })
14541
+ .filter(category => !!category);
14542
+ },
14543
+ get avatar() {
14544
+ var _a;
14545
+ if (!community.avatarFileId)
14546
+ return undefined;
14547
+ const avatar = (_a = pullFromCache([
14548
+ 'file',
14549
+ 'get',
14550
+ community.avatarFileId,
14551
+ ])) === null || _a === void 0 ? void 0 : _a.data;
14552
+ return avatar;
14553
+ }, createInvitations: async (userIds) => {
14554
+ await createInvitations({
14555
+ type: "communityMemberInvite" /* InvitationTypeEnum.CommunityMemberInvite */,
14556
+ targetType: 'community',
14557
+ targetId: community.communityId,
14558
+ userIds,
14490
14559
  });
14491
- });
14492
- return true;
14560
+ }, getMemberInvitations: (params, callback) => {
14561
+ return getInvitations$1(Object.assign(Object.assign({}, params), { targetId: community.communityId, targetType: 'community', type: "communityMemberInvite" /* InvitationTypeEnum.CommunityMemberInvite */ }), callback);
14562
+ }, getInvitation: async () => {
14563
+ const { data } = await getInvitation({
14564
+ targetType: 'community',
14565
+ targetId: community.communityId,
14566
+ });
14567
+ return data;
14568
+ }, join: async () => joinRequest(community.communityId), getJoinRequests: (params, callback) => {
14569
+ return getJoinRequests(Object.assign(Object.assign({}, params), { communityId: community.communityId }), callback);
14570
+ }, getMyJoinRequest: async () => {
14571
+ const { data } = await getMyJoinRequest(community.communityId);
14572
+ return data;
14573
+ } });
14574
+ };
14575
+
14576
+ class StoryComputedValue {
14577
+ constructor(targetId, lastStoryExpiresAt, lastStorySeenExpiresAt) {
14578
+ this._syncingStoriesCount = 0;
14579
+ this._errorStoriesCount = 0;
14580
+ this._targetId = targetId;
14581
+ this._lastStoryExpiresAt = lastStoryExpiresAt;
14582
+ this._lastStorySeenExpiresAt = lastStorySeenExpiresAt;
14583
+ this.cacheStoryExpireTime = pullFromCache([
14584
+ "story-expire" /* STORY_KEY_CACHE.EXPIRE */,
14585
+ this._targetId,
14586
+ ]);
14587
+ this.cacheStoreSeenTime = pullFromCache([
14588
+ "story-last-seen" /* STORY_KEY_CACHE.LAST_SEEN */,
14589
+ this._targetId,
14590
+ ]);
14591
+ this.getTotalStoryByStatus();
14493
14592
  }
14494
- catch (err) {
14495
- console.error('[SDK syncWatchSessions] ERROR caught:', (err === null || err === void 0 ? void 0 : err.message) || err);
14496
- // Failure - update back to PENDING and increment retry count
14497
- pendingSessions.forEach(session => {
14498
- const currentSession = storage.getSession(session.sessionId);
14499
- if (currentSession) {
14500
- const newRetryCount = currentSession.retryCount + 1;
14501
- if (newRetryCount >= 3) {
14502
- // Delete session if retry count exceeds 3
14503
- storage.deleteSession(session.sessionId);
14504
- }
14505
- else {
14506
- // Update to PENDING with incremented retry count
14507
- storage.updateSession(session.sessionId, {
14508
- syncState: 'PENDING',
14509
- retryCount: newRetryCount,
14510
- });
14511
- }
14512
- }
14513
- });
14514
- return false;
14593
+ get lastStoryExpiresAt() {
14594
+ return this._lastStoryExpiresAt ? new Date(this._lastStoryExpiresAt).getTime() : 0;
14595
+ }
14596
+ get lastStorySeenExpiresAt() {
14597
+ return this._lastStorySeenExpiresAt ? new Date(this._lastStorySeenExpiresAt).getTime() : 0;
14598
+ }
14599
+ get localLastStoryExpires() {
14600
+ var _a, _b;
14601
+ return ((_a = this.cacheStoryExpireTime) === null || _a === void 0 ? void 0 : _a.data)
14602
+ ? new Date((_b = this.cacheStoryExpireTime) === null || _b === void 0 ? void 0 : _b.data).getTime()
14603
+ : 0;
14604
+ }
14605
+ get localLastStorySeenExpiresAt() {
14606
+ var _a, _b;
14607
+ 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;
14608
+ }
14609
+ get isContainUnSyncedStory() {
14610
+ const currentSyncingState = pullFromCache([
14611
+ "story-sync-state" /* STORY_KEY_CACHE.SYNC_STATE */,
14612
+ this._targetId,
14613
+ ]);
14614
+ if (!(currentSyncingState === null || currentSyncingState === void 0 ? void 0 : currentSyncingState.data))
14615
+ return false;
14616
+ return ["syncing" /* Amity.SyncState.Syncing */, "error" /* Amity.SyncState.Error */].includes(currentSyncingState.data);
14515
14617
  }
14516
- }
14517
-
14518
- /**
14519
- * Room statuses that are considered watchable
14520
- */
14521
- const WATCHABLE_ROOM_STATUSES = ['live', 'recorded'];
14522
- /**
14523
- * Generate a random jitter delay between 5 and 30 seconds
14524
- */
14525
- const getJitterDelay = () => {
14526
- const minDelay = 5000; // 5 seconds
14527
- const maxDelay = 30000; // 30 seconds
14528
- return Math.floor(Math.random() * (maxDelay - minDelay + 1)) + minDelay;
14529
- };
14530
- /**
14531
- * Wait for network connection with timeout
14532
- * @param maxWaitTime Maximum time to wait in milliseconds (default: 60000 = 60 seconds)
14533
- * @returns Promise that resolves when network is available or timeout is reached
14534
- */
14535
- const waitForNetwork = (maxWaitTime = 60000) => {
14536
- return new Promise(resolve => {
14537
- // Simple check - if navigator.onLine is available, use it
14538
- // Otherwise, assume network is available
14539
- if (typeof navigator === 'undefined' || typeof navigator.onLine === 'undefined') {
14540
- resolve();
14541
- return;
14618
+ getLocalLastSortingDate() {
14619
+ if (this.isContainUnSyncedStory) {
14620
+ return this.localLastStoryExpires;
14542
14621
  }
14543
- const startTime = Date.now();
14544
- const checkInterval = 1000; // 1 second
14545
- const checkConnection = () => {
14546
- if (navigator.onLine || Date.now() - startTime >= maxWaitTime) {
14547
- resolve();
14548
- }
14549
- else {
14550
- setTimeout(checkConnection, checkInterval);
14551
- }
14552
- };
14553
- checkConnection();
14554
- });
14555
- };
14556
- /**
14557
- * AmityRoomAnalytics provides analytics capabilities for room watch sessions
14558
- */
14559
- class AmityRoomAnalytics {
14560
- constructor(room) {
14561
- this.storage = getWatchSessionStorage();
14562
- this.client = getActiveClient();
14563
- this.room = room;
14622
+ return this.lastStoryExpiresAt;
14564
14623
  }
14565
- /**
14566
- * Create a new watch session for the current room
14567
- * @param startedAt The timestamp when watching started
14568
- * @returns Promise<string> sessionId unique identifier for this watch session
14569
- * @throws ASCApiError if room is not in watchable state (not LIVE or RECORDED)
14570
- */
14571
- async createWatchSession(startedAt) {
14572
- // Validate room status
14573
- if (!WATCHABLE_ROOM_STATUSES.includes(this.room.status)) {
14574
- throw new ASCApiError('room is not in watchable state', 500000 /* Amity.ServerError.BUSINESS_ERROR */, "error" /* Amity.ErrorLevel.ERROR */);
14624
+ getHasUnseenFlag() {
14625
+ const now = new Date().getTime();
14626
+ const highestSeen = Math.max(this.lastStorySeenExpiresAt, this.localLastStorySeenExpiresAt);
14627
+ pullFromCache([
14628
+ "story-sync-state" /* STORY_KEY_CACHE.SYNC_STATE */,
14629
+ this._targetId,
14630
+ ]);
14631
+ if (this.isContainUnSyncedStory) {
14632
+ return this.localLastStoryExpires > now && this.localLastStoryExpires > highestSeen;
14575
14633
  }
14576
- // Generate session ID with prefix
14577
- const prefix = this.room.status === 'live' ? 'room_' : 'room_playback_';
14578
- const sessionId = prefix + uuid__default["default"].v4();
14579
- // Create watch session entity
14580
- const session = {
14581
- sessionId,
14582
- roomId: this.room.roomId,
14583
- watchSeconds: 0,
14584
- startTime: startedAt,
14585
- endTime: null,
14586
- syncState: 'PENDING',
14587
- syncedAt: null,
14588
- retryCount: 0,
14589
- };
14590
- // Persist to storage
14591
- this.storage.addSession(session);
14592
- return sessionId;
14634
+ return this.lastStoryExpiresAt > now && this.lastStoryExpiresAt > highestSeen;
14593
14635
  }
14594
- /**
14595
- * Update an existing watch session with duration
14596
- * @param sessionId The unique identifier of the watch session
14597
- * @param duration The total watch duration in seconds
14598
- * @param endedAt The timestamp when this update occurred
14599
- * @returns Promise<void> Completion status
14600
- */
14601
- async updateWatchSession(sessionId, duration, endedAt) {
14602
- const session = this.storage.getSession(sessionId);
14603
- if (!session) {
14604
- throw new Error(`Watch session ${sessionId} not found`);
14636
+ getTotalStoryByStatus() {
14637
+ const stories = queryCache(["story" /* STORY_KEY_CACHE.STORY */, 'get']);
14638
+ if (!stories) {
14639
+ this._errorStoriesCount = 0;
14640
+ this._syncingStoriesCount = 0;
14641
+ return;
14605
14642
  }
14606
- // Update session
14607
- this.storage.updateSession(sessionId, {
14608
- watchSeconds: duration,
14609
- endTime: endedAt,
14643
+ const groupByType = stories.reduce((acc, story) => {
14644
+ const { data: { targetId, syncState, isDeleted }, } = story;
14645
+ if (targetId === this._targetId && !isDeleted) {
14646
+ acc[syncState] += 1;
14647
+ }
14648
+ return acc;
14649
+ }, {
14650
+ syncing: 0,
14651
+ error: 0,
14652
+ synced: 0,
14610
14653
  });
14654
+ this._errorStoriesCount = groupByType.error;
14655
+ this._syncingStoriesCount = groupByType.syncing;
14611
14656
  }
14612
- /**
14613
- * Sync all pending watch sessions to backend
14614
- * This function uses jitter delay and handles network resilience
14615
- */
14616
- syncPendingWatchSessions() {
14617
- // Execute with jitter delay (5-30 seconds)
14618
- const jitterDelay = getJitterDelay();
14619
- this.client.log('room/RoomAnalytics: syncPendingWatchSessions called, jitter delay:', `${jitterDelay}ms`);
14620
- setTimeout(async () => {
14621
- this.client.log('room/RoomAnalytics: Jitter delay completed, starting sync process');
14622
- try {
14623
- // Reset any SYNCING sessions back to PENDING
14624
- const syncingSessions = this.storage.getSyncingSessions();
14625
- this.client.log('room/RoomAnalytics: SYNCING sessions to reset:', syncingSessions.length);
14626
- syncingSessions.forEach(session => {
14627
- this.storage.updateSession(session.sessionId, { syncState: 'PENDING' });
14628
- });
14629
- // Wait for network connection (max 60 seconds)
14630
- await waitForNetwork(60000);
14631
- this.client.log('room/RoomAnalytics: Network available');
14632
- // Sync pending sessions
14633
- this.client.log('room/RoomAnalytics: Calling syncWatchSessions()');
14634
- await syncWatchSessions();
14635
- this.client.log('room/RoomAnalytics: syncWatchSessions completed');
14636
- }
14637
- catch (error) {
14638
- // Error is already handled in syncWatchSessions
14639
- console.error('Failed to sync watch sessions:', error);
14640
- }
14641
- }, jitterDelay);
14657
+ get syncingStoriesCount() {
14658
+ return this._syncingStoriesCount;
14659
+ }
14660
+ get failedStoriesCount() {
14661
+ return this._errorStoriesCount;
14642
14662
  }
14643
14663
  }
14644
14664
 
14645
- const roomLinkedObject = (room) => {
14646
- return Object.assign(Object.assign({}, room), { get post() {
14647
- var _a;
14648
- if (room.referenceType !== 'post')
14649
- return;
14650
- return (_a = pullFromCache(['post', 'get', room.referenceId])) === null || _a === void 0 ? void 0 : _a.data;
14665
+ const storyTargetLinkedObject = (storyTarget) => {
14666
+ const { targetType, targetId, lastStoryExpiresAt, lastStorySeenExpiresAt, targetUpdatedAt, localFilter, } = storyTarget;
14667
+ const computedValue = new StoryComputedValue(targetId, lastStoryExpiresAt, lastStorySeenExpiresAt);
14668
+ return {
14669
+ targetType,
14670
+ targetId,
14671
+ lastStoryExpiresAt,
14672
+ updatedAt: targetUpdatedAt,
14673
+ // Additional data
14674
+ hasUnseen: computedValue.getHasUnseenFlag(),
14675
+ syncingStoriesCount: computedValue.syncingStoriesCount,
14676
+ failedStoriesCount: computedValue.failedStoriesCount,
14677
+ localFilter,
14678
+ localLastExpires: computedValue.localLastStoryExpires,
14679
+ localLastSeen: computedValue.localLastStorySeenExpiresAt,
14680
+ localSortingDate: computedValue.getLocalLastSortingDate(),
14681
+ };
14682
+ };
14683
+
14684
+ const storyLinkedObject = (story) => {
14685
+ const analyticsEngineInstance = AnalyticsEngine$1.getInstance();
14686
+ const storyTargetCache = pullFromCache([
14687
+ "storyTarget" /* STORY_KEY_CACHE.STORY_TARGET */,
14688
+ 'get',
14689
+ story.targetId,
14690
+ ]);
14691
+ const communityCacheData = pullFromCache(['community', 'get', story.targetId]);
14692
+ return Object.assign(Object.assign({}, story), { analytics: {
14693
+ markAsSeen: () => {
14694
+ if (!story.expiresAt)
14695
+ return;
14696
+ if (story.syncState !== "synced" /* Amity.SyncState.Synced */)
14697
+ return;
14698
+ analyticsEngineInstance.markStoryAsViewed(story);
14699
+ },
14700
+ markLinkAsClicked: () => {
14701
+ if (!story.expiresAt)
14702
+ return;
14703
+ if (story.syncState !== "synced" /* Amity.SyncState.Synced */)
14704
+ return;
14705
+ analyticsEngineInstance.markStoryAsClicked(story);
14706
+ },
14707
+ }, get videoData() {
14708
+ var _a, _b;
14709
+ const cache = pullFromCache([
14710
+ 'file',
14711
+ 'get',
14712
+ (_b = (_a = story.data) === null || _a === void 0 ? void 0 : _a.videoFileId) === null || _b === void 0 ? void 0 : _b.original,
14713
+ ]);
14714
+ if (!cache)
14715
+ return undefined;
14716
+ const { data } = cache;
14717
+ return data || undefined;
14718
+ },
14719
+ get imageData() {
14720
+ var _a, _b;
14721
+ if (!((_a = story.data) === null || _a === void 0 ? void 0 : _a.fileId))
14722
+ return undefined;
14723
+ const cache = pullFromCache(['file', 'get', (_b = story.data) === null || _b === void 0 ? void 0 : _b.fileId]);
14724
+ if (!cache)
14725
+ return undefined;
14726
+ const { data } = cache;
14727
+ if (!data)
14728
+ return undefined;
14729
+ return Object.assign(Object.assign({}, data), { fileUrl: `${data.fileUrl}?size=full` });
14651
14730
  },
14652
14731
  get community() {
14653
- var _a;
14654
- if (room.targetType !== 'community')
14732
+ if (story.targetType !== 'community')
14733
+ return undefined;
14734
+ if (!(communityCacheData === null || communityCacheData === void 0 ? void 0 : communityCacheData.data))
14735
+ return undefined;
14736
+ return communityLinkedObject(communityCacheData.data);
14737
+ },
14738
+ get communityCategories() {
14739
+ if (story.targetType !== 'community')
14740
+ return undefined;
14741
+ if (!communityCacheData)
14742
+ return undefined;
14743
+ const { data: { categoryIds }, } = communityCacheData;
14744
+ if (categoryIds.length === 0)
14745
+ return undefined;
14746
+ return categoryIds
14747
+ .map(categoryId => {
14748
+ const categoryCacheData = pullFromCache(['category', 'get', categoryId]);
14749
+ return (categoryCacheData === null || categoryCacheData === void 0 ? void 0 : categoryCacheData.data) || undefined;
14750
+ })
14751
+ .filter(category => category !== undefined);
14752
+ },
14753
+ get creator() {
14754
+ const cacheData = pullFromCache(['user', 'get', story.creatorPublicId]);
14755
+ if (!(cacheData === null || cacheData === void 0 ? void 0 : cacheData.data))
14655
14756
  return;
14656
- return (_a = pullFromCache(['community', 'get', room.targetId])) === null || _a === void 0 ? void 0 : _a.data;
14757
+ return userLinkedObject(cacheData.data);
14657
14758
  },
14658
- get user() {
14659
- var _a;
14660
- const user = (_a = pullFromCache(['user', 'get', room.createdBy])) === null || _a === void 0 ? void 0 : _a.data;
14661
- return user ? userLinkedObject(user) : user;
14759
+ get storyTarget() {
14760
+ if (!(storyTargetCache === null || storyTargetCache === void 0 ? void 0 : storyTargetCache.data))
14761
+ return;
14762
+ return storyTargetLinkedObject(storyTargetCache.data);
14662
14763
  },
14663
- get childRooms() {
14664
- if (!room.childRoomIds || room.childRoomIds.length === 0)
14665
- return [];
14666
- return room.childRoomIds
14667
- .map(id => {
14668
- var _a;
14669
- const roomCache = (_a = pullFromCache(['room', 'get', id])) === null || _a === void 0 ? void 0 : _a.data;
14670
- if (!roomCache)
14671
- return undefined;
14672
- return roomLinkedObject(roomCache);
14673
- })
14674
- .filter(isNonNullable);
14675
- }, participants: room.participants.map(participant => (Object.assign(Object.assign({}, participant), { get user() {
14676
- var _a;
14677
- const user = (_a = pullFromCache(['user', 'get', participant.userId])) === null || _a === void 0 ? void 0 : _a.data;
14678
- return user ? userLinkedObject(user) : user;
14679
- } }))), getLiveChat: () => getLiveChat(room), createInvitation: (userId) => createInvitations({
14680
- type: "livestreamCohostInvite" /* InvitationTypeEnum.LivestreamCohostInvite */,
14681
- targetType: 'room',
14682
- targetId: room.roomId,
14683
- userIds: [userId],
14684
- }), getInvitations: async () => {
14685
- const { data } = await getInvitation({
14686
- targetId: room.roomId,
14687
- targetType: 'room',
14688
- type: "livestreamCohostInvite" /* InvitationTypeEnum.LivestreamCohostInvite */,
14689
- });
14690
- return data;
14691
- }, analytics() {
14692
- // Use 'this' to avoid creating a new room object
14693
- return new AmityRoomAnalytics(this);
14764
+ get isSeen() {
14765
+ const cacheData = pullFromCache(["story-last-seen" /* STORY_KEY_CACHE.LAST_SEEN */, story.targetId]);
14766
+ if (!(storyTargetCache === null || storyTargetCache === void 0 ? void 0 : storyTargetCache.data))
14767
+ return false;
14768
+ const localLastSeen = (cacheData === null || cacheData === void 0 ? void 0 : cacheData.data) ? new Date(cacheData.data).getTime() : 0;
14769
+ const serverLastSeen = new Date(storyTargetCache === null || storyTargetCache === void 0 ? void 0 : storyTargetCache.data.lastStorySeenExpiresAt).getTime() || 0;
14770
+ const expiresAt = new Date(story.expiresAt).getTime();
14771
+ return Math.max(localLastSeen, serverLastSeen) >= expiresAt;
14694
14772
  } });
14695
14773
  };
14696
14774
 
14697
- const pollLinkedObject = (poll) => {
14698
- return Object.assign(Object.assign({}, poll), { answers: poll.answers.map(answer => (Object.assign(Object.assign({}, answer), { get image() {
14699
- var _a;
14700
- if (!answer.fileId)
14701
- return undefined;
14702
- return (_a = pullFromCache(['file', 'get', answer.fileId])) === null || _a === void 0 ? void 0 : _a.data;
14703
- } }))) });
14704
- };
14705
-
14706
- /*
14707
- * verifies membership status
14708
- */
14709
- function isMember(membership) {
14710
- return membership !== 'none';
14711
- }
14712
- /*
14713
- * checks if currently logged in user is part of the community
14714
- */
14715
- function isCurrentUserPartOfCommunity(c, m) {
14716
- const { userId } = getActiveUser();
14717
- return c.communityId === m.communityId && m.userId === userId;
14718
- }
14719
- /*
14720
- * For mqtt events server will not send user specific data as it's broadcasted
14721
- * to multiple users and it also does not include communityUser
14722
- *
14723
- * Client SDK needs to check for the existing isJoined field in cache data before calculating.
14724
- * Althought this can be calculated, it's not scalable.
14725
- */
14726
- function updateMembershipStatus(communities, communityUsers) {
14727
- return communities.map(c => {
14728
- const cachedCommunity = pullFromCache([
14729
- 'community',
14730
- 'get',
14731
- c.communityId,
14732
- ]);
14733
- if ((cachedCommunity === null || cachedCommunity === void 0 ? void 0 : cachedCommunity.data) && (cachedCommunity === null || cachedCommunity === void 0 ? void 0 : cachedCommunity.data.hasOwnProperty('isJoined'))) {
14734
- return Object.assign(Object.assign({}, cachedCommunity.data), c);
14735
- }
14736
- const isJoined = c.isJoined !== undefined
14737
- ? c.isJoined
14738
- : communityUsers.some(m => isCurrentUserPartOfCommunity(c, m) && isMember(m.communityMembership));
14739
- return Object.assign(Object.assign({}, c), { isJoined });
14740
- });
14741
- }
14742
-
14743
- const getMatchPostSetting = (value) => {
14744
- var _a;
14745
- return (_a = Object.keys(CommunityPostSettingMaps).find(key => value.needApprovalOnPostCreation ===
14746
- CommunityPostSettingMaps[key].needApprovalOnPostCreation &&
14747
- value.onlyAdminCanPost === CommunityPostSettingMaps[key].onlyAdminCanPost)) !== null && _a !== void 0 ? _a : DefaultCommunityPostSetting;
14748
- };
14749
- function addPostSetting({ communities }) {
14750
- return communities.map((_a) => {
14751
- var { needApprovalOnPostCreation, onlyAdminCanPost } = _a, restCommunityPayload = __rest(_a, ["needApprovalOnPostCreation", "onlyAdminCanPost"]);
14752
- return (Object.assign({ postSetting: getMatchPostSetting({
14753
- needApprovalOnPostCreation,
14754
- onlyAdminCanPost,
14755
- }) }, restCommunityPayload));
14756
- });
14757
- }
14758
- const prepareCommunityPayload = (rawPayload) => {
14759
- const communitiesWithPostSetting = addPostSetting({ communities: rawPayload.communities });
14760
- // Convert users to internal format
14761
- const internalUsers = rawPayload.users.map(convertRawUserToInternalUser);
14762
- // map users with community
14763
- const mappedCommunityUsers = rawPayload.communityUsers.map(communityUser => {
14764
- const user = internalUsers.find(user => user.userId === communityUser.userId);
14765
- return Object.assign(Object.assign({}, communityUser), { user });
14766
- });
14767
- const communityWithMembershipStatus = updateMembershipStatus(communitiesWithPostSetting, mappedCommunityUsers);
14768
- return Object.assign(Object.assign({}, rawPayload), { users: rawPayload.users.map(convertRawUserToInternalUser), communities: communityWithMembershipStatus, communityUsers: mappedCommunityUsers });
14769
- };
14770
- const prepareCommunityJoinRequestPayload = (rawPayload) => {
14771
- const mappedJoinRequests = rawPayload.joinRequests.map(joinRequest => {
14772
- return Object.assign(Object.assign({}, joinRequest), { joinRequestId: joinRequest._id });
14773
- });
14774
- const users = rawPayload.users.map(convertRawUserToInternalUser);
14775
- return Object.assign(Object.assign({}, rawPayload), { joinRequests: mappedJoinRequests, users });
14776
- };
14777
- const prepareCommunityMembershipPayload = (rawPayload) => {
14778
- const communitiesWithPostSetting = addPostSetting({ communities: rawPayload.communities });
14779
- // map users with community
14780
- const mappedCommunityUsers = rawPayload.communityUsers.map(communityUser => {
14781
- const user = rawPayload.users.find(user => user.userId === communityUser.userId);
14782
- return Object.assign(Object.assign({}, communityUser), { user });
14783
- });
14784
- const communityWithMembershipStatus = updateMembershipStatus(communitiesWithPostSetting, mappedCommunityUsers);
14785
- return Object.assign(Object.assign({}, rawPayload), { communities: communityWithMembershipStatus, communityUsers: mappedCommunityUsers });
14786
- };
14787
- const prepareCommunityRequest = (params) => {
14788
- const { postSetting = undefined, storySetting } = params, restParam = __rest(params, ["postSetting", "storySetting"]);
14789
- return Object.assign(Object.assign(Object.assign({}, restParam), (postSetting ? CommunityPostSettingMaps[postSetting] : undefined)), {
14790
- // Convert story setting to the actual value. (Allow by default)
14791
- allowCommentInStory: typeof (storySetting === null || storySetting === void 0 ? void 0 : storySetting.enableComment) === 'boolean' ? storySetting.enableComment : true });
14792
- };
14793
- const prepareSemanticSearchCommunityPayload = (_a) => {
14794
- var communityPayload = __rest(_a, ["searchResult"]);
14795
- const processedCommunityPayload = prepareCommunityPayload(communityPayload);
14796
- return Object.assign({}, processedCommunityPayload);
14797
- };
14798
-
14799
14775
  /* begin_public_function
14800
- id: joinRequest.approve
14776
+ id: channel.create
14801
14777
  */
14802
14778
  /**
14803
14779
  * ```js
14804
- * import { joinRequest } from '@amityco/ts-sdk-react-native'
14805
- * const isAccepted = await joinRequest.approve()
14780
+ * import { createChannel } from '@amityco/ts-sdk-react-native'
14781
+ * const created = await createChannel({ displayName: 'foobar' })
14806
14782
  * ```
14807
14783
  *
14808
- * Accepts a {@link Amity.JoinRequest} object
14784
+ * Creates an {@link Amity.Channel}
14809
14785
  *
14810
- * @param joinRequest the {@link Amity.JoinRequest} to accept
14811
- * @returns A success boolean if the {@link Amity.JoinRequest} was accepted
14786
+ * @param bundle The data necessary to create a new {@link Amity.Channel}
14787
+ * @returns The newly created {@link Amity.Channel}
14812
14788
  *
14813
- * @category Join Request API
14789
+ * @category Channel API
14814
14790
  * @async
14815
14791
  */
14816
- const approveJoinRequest = async (joinRequest) => {
14817
- var _a;
14792
+ const createChannel = async (bundle) => {
14818
14793
  const client = getActiveClient();
14819
- client.log('joinRequest/approveJoinRequest', joinRequest.joinRequestId);
14820
- const { data } = await client.http.post(`/api/v4/communities/${joinRequest.targetId}/join/approve`, {
14821
- userId: joinRequest.requestorInternalId,
14822
- });
14823
- const joinRequestCache = (_a = pullFromCache([
14824
- 'joinRequest',
14825
- 'get',
14826
- joinRequest.joinRequestId,
14827
- ])) === null || _a === void 0 ? void 0 : _a.data;
14828
- if (joinRequestCache) {
14829
- upsertInCache(['joinRequest', 'get', joinRequest.joinRequestId], {
14830
- status: "approved" /* JoinRequestStatusEnum.Approved */,
14831
- });
14832
- fireEvent('local.joinRequest.updated', [joinRequestCache]);
14794
+ client.log('user/createChannel', bundle);
14795
+ let payload;
14796
+ /* c8 ignore next */
14797
+ if ((bundle === null || bundle === void 0 ? void 0 : bundle.type) === 'conversation') {
14798
+ payload = await client.http.post('/api/v3/channels/conversation', Object.assign(Object.assign({}, bundle), { isDistinct: true }));
14833
14799
  }
14834
- return data.success;
14800
+ else {
14801
+ const { isPublic } = bundle, restParams = __rest(bundle, ["isPublic"]);
14802
+ payload = await client.http.post('/api/v3/channels', Object.assign(Object.assign({}, restParams), {
14803
+ /* c8 ignore next */
14804
+ isPublic: (bundle === null || bundle === void 0 ? void 0 : bundle.type) === 'community' ? isPublic : undefined }));
14805
+ }
14806
+ const data = await prepareChannelPayload(payload.data);
14807
+ const cachedAt = client.cache && Date.now();
14808
+ if (client.cache)
14809
+ ingestInCache(data, { cachedAt });
14810
+ const { channels } = data;
14811
+ return {
14812
+ data: constructChannelObject(channels[0]),
14813
+ cachedAt,
14814
+ };
14835
14815
  };
14836
14816
  /* end_public_function */
14837
14817
 
14838
- /* begin_public_function
14839
- id: joinRequest.cancel
14840
- */
14841
14818
  /**
14842
14819
  * ```js
14843
- * import { joinRequest } from '@amityco/ts-sdk-react-native'
14844
- * const isCanceled = await joinRequest.cancel()
14820
+ * import { getChannel } from '@amityco/ts-sdk-react-native'
14821
+ * const channel = await getChannel('foobar')
14845
14822
  * ```
14846
14823
  *
14847
- * Cancels a {@link Amity.JoinRequest} object
14824
+ * Fetches a {@link Amity.Channel} object
14848
14825
  *
14849
- * @param joinRequest the {@link Amity.JoinRequest} to cancel
14850
- * @returns A success boolean if the {@link Amity.JoinRequest} was canceled
14826
+ * @param channelId the ID of the {@link Amity.Channel} to fetch
14827
+ * @returns the associated {@link Amity.Channel} object
14851
14828
  *
14852
- * @category Join Request API
14829
+ * @category Channel API
14853
14830
  * @async
14854
14831
  */
14855
- const cancelJoinRequest = async (joinRequest) => {
14856
- var _a;
14832
+ const getChannel$1 = async (channelId) => {
14857
14833
  const client = getActiveClient();
14858
- client.log('joinRequest/cancelJoinRequest', joinRequest.joinRequestId);
14859
- const { data } = await client.http.delete(`/api/v4/communities/${joinRequest.targetId}/join`);
14860
- const joinRequestCache = (_a = pullFromCache([
14861
- 'joinRequest',
14862
- 'get',
14863
- joinRequest.joinRequestId,
14864
- ])) === null || _a === void 0 ? void 0 : _a.data;
14865
- if (joinRequestCache) {
14866
- upsertInCache(['joinRequest', 'get', joinRequest.joinRequestId], {
14867
- status: "cancelled" /* JoinRequestStatusEnum.Cancelled */,
14868
- });
14869
- fireEvent('local.joinRequest.deleted', [joinRequestCache]);
14834
+ client.log('channel/getChannel', channelId);
14835
+ isInTombstone('channel', channelId);
14836
+ let data;
14837
+ try {
14838
+ const { data: payload } = await client.http.get(`/api/v3/channels/${encodeURIComponent(channelId)}`);
14839
+ data = await prepareChannelPayload(payload);
14840
+ if (client.isUnreadCountEnabled && client.getMarkerSyncConsistentMode()) {
14841
+ prepareUnreadCountInfo(payload);
14842
+ }
14870
14843
  }
14871
- return data.success;
14844
+ catch (error) {
14845
+ if (checkIfShouldGoesToTombstone(error === null || error === void 0 ? void 0 : error.code)) {
14846
+ // NOTE: use channelPublicId as tombstone cache key since we cannot get the channelPrivateId that come along with channel data from server
14847
+ pushToTombstone('channel', channelId);
14848
+ }
14849
+ throw error;
14850
+ }
14851
+ const cachedAt = client.cache && Date.now();
14852
+ if (client.cache)
14853
+ ingestInCache(data, { cachedAt });
14854
+ const { channels } = data;
14855
+ return {
14856
+ data: channels.find(channel => channel.channelId === channelId),
14857
+ cachedAt,
14858
+ };
14872
14859
  };
14873
- /* end_public_function */
14874
-
14875
- /* begin_public_function
14876
- id: joinRequest.reject
14877
- */
14878
14860
  /**
14879
14861
  * ```js
14880
- * import { joinRequest } from '@amityco/ts-sdk-react-native'
14881
- * const isRejected = await joinRequest.reject()
14862
+ * import { getChannel } from '@amityco/ts-sdk-react-native'
14863
+ * const channel = getChannel.locally('foobar')
14882
14864
  * ```
14883
14865
  *
14884
- * Rejects a {@link Amity.JoinRequest} object
14866
+ * Fetches a {@link Amity.Channel} object from cache
14885
14867
  *
14886
- * @param joinRequest the {@link Amity.JoinRequest} to reject
14887
- * @returns A success boolean if the {@link Amity.JoinRequest} was rejected
14868
+ * @param channelId the ID of the {@link Amity.Channel} to fetch
14869
+ * @returns the associated {@link Amity.Channel} object
14888
14870
  *
14889
- * @category Join Request API
14890
- * @async
14871
+ * @category Channel API
14891
14872
  */
14892
- const rejectJoinRequest = async (joinRequest) => {
14873
+ getChannel$1.locally = (channelId) => {
14893
14874
  var _a;
14894
14875
  const client = getActiveClient();
14895
- client.log('joinRequest/rejectJoinRequest', joinRequest.joinRequestId);
14896
- const { data } = await client.http.post(`/api/v4/communities/${joinRequest.targetId}/join/reject`, {
14897
- userId: joinRequest.requestorInternalId,
14876
+ client.log('channel/getChannel.locally', channelId);
14877
+ if (!client.cache)
14878
+ return;
14879
+ // use queryCache to get all channel caches and filter by channelPublicId since we use channelPrivateId as cache key
14880
+ const cached = (_a = queryCache(['channel', 'get'])) === null || _a === void 0 ? void 0 : _a.filter(({ data }) => {
14881
+ return data.channelPublicId === channelId;
14898
14882
  });
14899
- const joinRequestCache = (_a = pullFromCache([
14900
- 'joinRequest',
14901
- 'get',
14902
- joinRequest.joinRequestId,
14903
- ])) === null || _a === void 0 ? void 0 : _a.data;
14904
- if (joinRequestCache) {
14905
- upsertInCache(['joinRequest', 'get', joinRequest.joinRequestId], {
14906
- status: "rejected" /* JoinRequestStatusEnum.Rejected */,
14907
- });
14908
- fireEvent('local.joinRequest.updated', [joinRequestCache]);
14909
- }
14910
- return data.success;
14911
- };
14912
- /* end_public_function */
14913
-
14914
- const joinRequestLinkedObject = (joinRequest) => {
14915
- return Object.assign(Object.assign({}, joinRequest), { get user() {
14916
- var _a;
14917
- const user = (_a = pullFromCache([
14918
- 'user',
14919
- 'get',
14920
- joinRequest.requestorPublicId,
14921
- ])) === null || _a === void 0 ? void 0 : _a.data;
14922
- if (!user)
14923
- return undefined;
14924
- return userLinkedObject(user);
14925
- }, cancel: async () => {
14926
- await cancelJoinRequest(joinRequest);
14927
- }, approve: async () => {
14928
- await approveJoinRequest(joinRequest);
14929
- }, reject: async () => {
14930
- await rejectJoinRequest(joinRequest);
14931
- } });
14883
+ if (!cached || (cached === null || cached === void 0 ? void 0 : cached.length) === 0)
14884
+ return;
14885
+ return {
14886
+ data: cached[0].data,
14887
+ cachedAt: cached[0].cachedAt,
14888
+ };
14932
14889
  };
14933
14890
 
14934
- /* begin_public_function
14935
- id: community.getMyJoinRequest
14936
- */
14937
14891
  /**
14938
14892
  * ```js
14939
- * import { community } from '@amityco/ts-sdk-react-native'
14940
- * const isJoined = await community.getMyJoinRequest('foobar')
14893
+ * import { getStream } from '@amityco/ts-sdk-react-native'
14894
+ * const stream = await getStream('foobar')
14941
14895
  * ```
14942
14896
  *
14943
- * Joins a {@link Amity.Community} object
14897
+ * Fetches a {@link Amity.Channel} object linked with a current stream
14944
14898
  *
14945
- * @param communityId the {@link Amity.Community} to join
14946
- * @returns A success boolean if the {@link Amity.Community} was joined
14899
+ * @param stream {@link Amity.Stream} that has linked live channel
14900
+ * @returns the associated {@link Amity.Channel<'live'>} object
14947
14901
  *
14948
- * @category Community API
14902
+ * @category Stream API
14949
14903
  * @async
14950
14904
  */
14951
- const getMyJoinRequest = async (communityId) => {
14905
+ const getLiveChat$1 = async (stream) => {
14906
+ var _a;
14952
14907
  const client = getActiveClient();
14953
- client.log('community/myJoinRequest', communityId);
14954
- const { data: payload } = await client.http.get(`/api/v4/communities/${communityId}/join/me`);
14955
- const data = prepareCommunityJoinRequestPayload(payload);
14956
- const cachedAt = client.cache && Date.now();
14957
- if (client.cache)
14958
- ingestInCache(data, { cachedAt });
14959
- return {
14960
- data: data.joinRequests[0] ? joinRequestLinkedObject(data.joinRequests[0]) : undefined,
14961
- cachedAt,
14962
- };
14908
+ client.log('stream/getLiveChat', stream.streamId);
14909
+ if (stream.channelId) {
14910
+ const channel = (_a = pullFromCache([
14911
+ 'channel',
14912
+ 'get',
14913
+ stream.channelId,
14914
+ ])) === null || _a === void 0 ? void 0 : _a.data;
14915
+ if (channel)
14916
+ return channelLinkedObject(constructChannelObject(channel));
14917
+ const { data } = await getChannel$1(stream.channelId);
14918
+ return channelLinkedObject(constructChannelObject(data));
14919
+ }
14920
+ // No Channel ID
14921
+ // streamer: create a new live channel
14922
+ if (stream.userId === client.userId) {
14923
+ const { data: channel } = await createChannel({
14924
+ type: 'live',
14925
+ postId: stream.postId,
14926
+ videoStreamId: stream.streamId,
14927
+ });
14928
+ // Update channelId to stream object in cache
14929
+ mergeInCache(['stream', 'get', stream.streamId], {
14930
+ channelId: channel.channelId,
14931
+ });
14932
+ return channel;
14933
+ }
14934
+ // watcher: return undefined
14935
+ return undefined;
14963
14936
  };
14964
- /* end_public_function */
14965
14937
 
14966
- /* begin_public_function
14967
- id: community.join
14968
- */
14938
+ const GET_WATCHER_URLS = Symbol('getWatcherUrls');
14939
+ const streamLinkedObject = (stream) => {
14940
+ return Object.assign(Object.assign({}, stream), { get moderation() {
14941
+ var _a;
14942
+ return (_a = pullFromCache(['streamModeration', 'get', stream.streamId])) === null || _a === void 0 ? void 0 : _a.data;
14943
+ },
14944
+ get post() {
14945
+ var _a;
14946
+ if (stream.referenceType !== 'post')
14947
+ return;
14948
+ return (_a = pullFromCache(['post', 'get', stream.referenceId])) === null || _a === void 0 ? void 0 : _a.data;
14949
+ },
14950
+ get community() {
14951
+ var _a;
14952
+ if (stream.targetType !== 'community')
14953
+ return;
14954
+ return (_a = pullFromCache(['community', 'get', stream.targetId])) === null || _a === void 0 ? void 0 : _a.data;
14955
+ },
14956
+ get user() {
14957
+ var _a;
14958
+ return (_a = pullFromCache(['user', 'get', stream.userId])) === null || _a === void 0 ? void 0 : _a.data;
14959
+ },
14960
+ get childStreams() {
14961
+ if (!stream.childStreamIds || stream.childStreamIds.length === 0)
14962
+ return [];
14963
+ return stream.childStreamIds
14964
+ .map(id => {
14965
+ var _a;
14966
+ const streamCache = (_a = pullFromCache(['stream', 'get', id])) === null || _a === void 0 ? void 0 : _a.data;
14967
+ if (!streamCache)
14968
+ return undefined;
14969
+ return streamLinkedObject(streamCache);
14970
+ })
14971
+ .filter(isNonNullable);
14972
+ }, getLiveChat: () => getLiveChat$1(stream), isBanned: !stream.watcherUrl, watcherUrl: null, get [GET_WATCHER_URLS]() {
14973
+ return stream.watcherUrl;
14974
+ } });
14975
+ };
14976
+
14977
+ const commentLinkedObject = (comment) => {
14978
+ return Object.assign(Object.assign({}, comment), { get target() {
14979
+ const commentTypes = {
14980
+ type: comment.targetType,
14981
+ };
14982
+ if (comment.targetType === 'user') {
14983
+ return Object.assign(Object.assign({}, commentTypes), { userId: comment.targetId });
14984
+ }
14985
+ if (commentTypes.type === 'content') {
14986
+ return Object.assign(Object.assign({}, commentTypes), { contentId: comment.targetId });
14987
+ }
14988
+ if (commentTypes.type === 'community') {
14989
+ const cacheData = pullFromCache([
14990
+ 'communityUsers',
14991
+ 'get',
14992
+ `${comment.targetId}#${comment.userId}`,
14993
+ ]);
14994
+ return Object.assign(Object.assign({}, commentTypes), { communityId: comment.targetId, creatorMember: cacheData === null || cacheData === void 0 ? void 0 : cacheData.data });
14995
+ }
14996
+ return {
14997
+ type: 'unknown',
14998
+ };
14999
+ },
15000
+ get creator() {
15001
+ const cacheData = pullFromCache(['user', 'get', comment.userId]);
15002
+ if (cacheData === null || cacheData === void 0 ? void 0 : cacheData.data)
15003
+ return userLinkedObject(cacheData.data);
15004
+ return undefined;
15005
+ },
15006
+ get childrenComment() {
15007
+ return comment.children
15008
+ .map(childCommentId => {
15009
+ const commentCache = pullFromCache([
15010
+ 'comment',
15011
+ 'get',
15012
+ childCommentId,
15013
+ ]);
15014
+ if (!(commentCache === null || commentCache === void 0 ? void 0 : commentCache.data))
15015
+ return;
15016
+ return commentCache === null || commentCache === void 0 ? void 0 : commentCache.data;
15017
+ })
15018
+ .filter(isNonNullable)
15019
+ .map(item => commentLinkedObject(item));
15020
+ } });
15021
+ };
15022
+
15023
+ function isAmityImagePost(post) {
15024
+ return !!(post.data &&
15025
+ typeof post.data !== 'string' &&
15026
+ 'fileId' in post.data &&
15027
+ post.dataType === 'image');
15028
+ }
15029
+ function isAmityFilePost(post) {
15030
+ return !!(post.data &&
15031
+ typeof post.data !== 'string' &&
15032
+ 'fileId' in post.data &&
15033
+ post.dataType === 'file');
15034
+ }
15035
+ function isAmityVideoPost(post) {
15036
+ return !!(post.data &&
15037
+ typeof post.data !== 'string' &&
15038
+ 'videoFileId' in post.data &&
15039
+ 'thumbnailFileId' in post.data &&
15040
+ post.dataType === 'video');
15041
+ }
15042
+ function isAmityLivestreamPost(post) {
15043
+ return !!(post.data &&
15044
+ typeof post.data !== 'string' &&
15045
+ 'streamId' in post.data &&
15046
+ post.dataType === 'liveStream');
15047
+ }
15048
+ function isAmityPollPost(post) {
15049
+ return !!(post.data &&
15050
+ typeof post.data !== 'string' &&
15051
+ 'pollId' in post.data &&
15052
+ post.dataType === 'poll');
15053
+ }
15054
+ function isAmityClipPost(post) {
15055
+ return !!(post.data &&
15056
+ typeof post.data !== 'string' &&
15057
+ 'fileId' in post.data &&
15058
+ post.dataType === 'clip');
15059
+ }
15060
+ function isAmityAudioPost(post) {
15061
+ return !!(post.data &&
15062
+ typeof post.data !== 'string' &&
15063
+ 'fileId' in post.data &&
15064
+ post.dataType === 'audio');
15065
+ }
15066
+ function isAmityRoomPost(post) {
15067
+ return !!(post.data &&
15068
+ typeof post.data !== 'string' &&
15069
+ 'roomId' in post.data &&
15070
+ post.dataType === 'room');
15071
+ }
15072
+
14969
15073
  /**
14970
15074
  * ```js
14971
- * import { community } from '@amityco/ts-sdk-react-native'
14972
- * const isJoined = await community.join('foobar')
15075
+ * import { RoomRepository } from '@amityco/ts-sdk-react-native'
15076
+ * const stream = await getStream('foobar')
14973
15077
  * ```
14974
15078
  *
14975
- * Joins a {@link Amity.Community} object
15079
+ * Fetches a {@link Amity.Channel} object linked with a current stream
14976
15080
  *
14977
- * @param communityId the {@link Amity.Community} to join
14978
- * @returns A status join result
15081
+ * @param stream {@link Amity.Stream} that has linked live channel
15082
+ * @returns the associated {@link Amity.Channel<'live'>} object
14979
15083
  *
14980
- * @category Community API
15084
+ * @category Stream API
14981
15085
  * @async
14982
15086
  */
14983
- const joinRequest = async (communityId) => {
15087
+ const getLiveChat = async (room) => {
14984
15088
  var _a;
14985
15089
  const client = getActiveClient();
14986
- client.log('community/joinRequest', communityId);
14987
- const { data: payload } = await client.http.post(`/api/v4/communities/${communityId}/join`);
14988
- const data = prepareCommunityJoinRequestPayload(payload);
14989
- const cachedAt = client.cache && Date.now();
14990
- if (client.cache)
14991
- ingestInCache(data, { cachedAt });
14992
- const status = data.joinRequests[0].status === "approved" /* JoinRequestStatusEnum.Approved */
14993
- ? "success" /* JoinResultStatusEnum.Success */
14994
- : "pending" /* JoinResultStatusEnum.Pending */;
14995
- if (status === "success" /* JoinResultStatusEnum.Success */ && client.cache) {
14996
- const community = (_a = pullFromCache(['community', 'get', communityId])) === null || _a === void 0 ? void 0 : _a.data;
14997
- if (community) {
14998
- const updatedCommunity = Object.assign(Object.assign({}, community), { isJoined: true });
14999
- upsertInCache(['community', 'get', communityId], updatedCommunity);
15000
- }
15090
+ client.log('room/getLiveChat', room.roomId);
15091
+ if (room.liveChannelId) {
15092
+ const channel = (_a = pullFromCache([
15093
+ 'channel',
15094
+ 'get',
15095
+ room.liveChannelId,
15096
+ ])) === null || _a === void 0 ? void 0 : _a.data;
15097
+ if (channel)
15098
+ return channelLinkedObject(constructChannelObject(channel));
15099
+ const { data } = await getChannel$1(room.liveChannelId);
15100
+ return channelLinkedObject(constructChannelObject(data));
15001
15101
  }
15002
- fireEvent('v4.local.community.joined', data.joinRequests);
15003
- return status === "success" /* JoinResultStatusEnum.Success */
15004
- ? { status }
15005
- : { status, request: joinRequestLinkedObject(data.joinRequests[0]) };
15006
- };
15007
- /* end_public_function */
15008
-
15009
- /**
15010
- * TODO: handle cache receive cache option, and cache policy
15011
- * TODO: check if querybyIds is supported
15012
- */
15013
- class JoinRequestsPaginationController extends PaginationController {
15014
- async getRequest(queryParams, token) {
15015
- const { limit = 20, communityId } = queryParams, params = __rest(queryParams, ["limit", "communityId"]);
15016
- const options = token ? { token } : { limit };
15017
- const { data: queryResponse } = await this.http.get(`/api/v4/communities/${communityId}/join`, {
15018
- params: Object.assign(Object.assign({}, params), { options }),
15102
+ // No Channel ID
15103
+ // streamer: create a new live channel
15104
+ if (room.createdBy === client.userId) {
15105
+ const { data: channel } = await createChannel({
15106
+ type: 'live',
15107
+ postId: room.referenceId,
15108
+ roomId: room.roomId,
15019
15109
  });
15020
- return queryResponse;
15021
- }
15022
- }
15023
-
15024
- var EnumJoinRequestAction$1;
15025
- (function (EnumJoinRequestAction) {
15026
- EnumJoinRequestAction["OnLocalJoinRequestCreated"] = "OnLocalJoinRequestCreated";
15027
- EnumJoinRequestAction["OnLocalJoinRequestUpdated"] = "OnLocalJoinRequestUpdated";
15028
- EnumJoinRequestAction["OnLocalJoinRequestDeleted"] = "OnLocalJoinRequestDeleted";
15029
- })(EnumJoinRequestAction$1 || (EnumJoinRequestAction$1 = {}));
15030
-
15031
- class JoinRequestsQueryStreamController extends QueryStreamController {
15032
- constructor(query, cacheKey, notifyChange, preparePayload) {
15033
- super(query, cacheKey);
15034
- this.notifyChange = notifyChange;
15035
- this.preparePayload = preparePayload;
15036
- }
15037
- async saveToMainDB(response) {
15038
- const processedPayload = await this.preparePayload(response);
15039
- const client = getActiveClient();
15040
- const cachedAt = client.cache && Date.now();
15041
- if (client.cache) {
15042
- ingestInCache(processedPayload, { cachedAt });
15043
- }
15044
- }
15045
- appendToQueryStream(response, direction, refresh = false) {
15046
- var _a, _b;
15047
- if (refresh) {
15048
- pushToCache(this.cacheKey, {
15049
- data: response.joinRequests.map(joinRequest => getResolver('joinRequest')({ joinRequestId: joinRequest._id })),
15050
- });
15051
- }
15052
- else {
15053
- const collection = (_a = pullFromCache(this.cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
15054
- const joinRequests = (_b = collection === null || collection === void 0 ? void 0 : collection.data) !== null && _b !== void 0 ? _b : [];
15055
- pushToCache(this.cacheKey, Object.assign(Object.assign({}, collection), { data: [
15056
- ...new Set([
15057
- ...joinRequests,
15058
- ...response.joinRequests.map(joinRequest => getResolver('joinRequest')({ joinRequestId: joinRequest._id })),
15059
- ]),
15060
- ] }));
15061
- }
15062
- }
15063
- reactor(action) {
15064
- return (joinRequest) => {
15065
- var _a;
15066
- const collection = (_a = pullFromCache(this.cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
15067
- if (!collection)
15068
- return;
15069
- if (action === EnumJoinRequestAction$1.OnLocalJoinRequestUpdated) {
15070
- const isExist = collection.data.find(id => id === joinRequest[0].joinRequestId);
15071
- if (!isExist)
15072
- return;
15073
- }
15074
- if (action === EnumJoinRequestAction$1.OnLocalJoinRequestCreated) {
15075
- collection.data = [
15076
- ...new Set([
15077
- ...joinRequest.map(joinRequest => joinRequest.joinRequestId),
15078
- ...collection.data,
15079
- ]),
15080
- ];
15081
- }
15082
- if (action === EnumJoinRequestAction$1.OnLocalJoinRequestDeleted) {
15083
- collection.data = collection.data.filter(id => id !== joinRequest[0].joinRequestId);
15084
- }
15085
- pushToCache(this.cacheKey, collection);
15086
- this.notifyChange({ origin: "event" /* Amity.LiveDataOrigin.EVENT */, loading: false });
15087
- };
15088
- }
15089
- subscribeRTE(createSubscriber) {
15090
- return createSubscriber.map(subscriber => subscriber.fn(this.reactor(subscriber.action)));
15110
+ // Update channelId to stream object in cache
15111
+ mergeInCache(['room', 'get', room.roomId], {
15112
+ liveChannelId: channel.channelId,
15113
+ });
15114
+ return channel;
15091
15115
  }
15092
- }
15093
-
15094
- /**
15095
- * ```js
15096
- * import { onJoinRequestCreated } from '@amityco/ts-sdk-react-native'
15097
- * const dispose = onJoinRequestCreated(data => {
15098
- * // ...
15099
- * })
15100
- * ```
15101
- *
15102
- * Fired when an {@link Amity.CommunityJoinRequestPayload} has been created
15103
- *
15104
- * @param callback The function to call when the event was fired
15105
- * @returns an {@link Amity.Unsubscriber} function to stop listening
15106
- *
15107
- * @category JoinRequest Events
15108
- */
15109
- const onJoinRequestCreated = (callback) => {
15110
- const client = getActiveClient();
15111
- const disposers = [
15112
- createEventSubscriber(client, 'onJoinRequestCreated', 'local.joinRequest.created', payload => callback(payload)),
15113
- ];
15114
- return () => {
15115
- disposers.forEach(fn => fn());
15116
- };
15117
- };
15118
-
15119
- /**
15120
- * ```js
15121
- * import { onJoinRequestUpdated } from '@amityco/ts-sdk-react-native'
15122
- * const dispose = onJoinRequestUpdated(data => {
15123
- * // ...
15124
- * })
15125
- * ```
15126
- *
15127
- * Fired when an {@link Amity.CommunityJoinRequestPayload} has been created
15128
- *
15129
- * @param callback The function to call when the event was fired
15130
- * @returns an {@link Amity.Unsubscriber} function to stop listening
15131
- *
15132
- * @category JoinRequest Events
15133
- */
15134
- const onJoinRequestUpdated = (callback) => {
15135
- const client = getActiveClient();
15136
- const disposers = [
15137
- createEventSubscriber(client, 'onJoinRequestUpdated', 'local.joinRequest.updated', payload => callback(payload)),
15138
- ];
15139
- return () => {
15140
- disposers.forEach(fn => fn());
15141
- };
15116
+ // watcher: return undefined
15117
+ return undefined;
15142
15118
  };
15143
15119
 
15144
15120
  /**
15145
- * ```js
15146
- * import { onJoinRequestDeleted } from '@amityco/ts-sdk-react-native'
15147
- * const dispose = onJoinRequestDeleted(data => {
15148
- * // ...
15149
- * })
15150
- * ```
15151
- *
15152
- * Fired when an {@link Amity.CommunityJoinRequestPayload} has been created
15153
- *
15154
- * @param callback The function to call when the event was fired
15155
- * @returns an {@link Amity.Unsubscriber} function to stop listening
15156
- *
15157
- * @category JoinRequest Events
15121
+ * WatchSessionStorage manages watch session data in memory
15122
+ * Similar to UsageCollector for stream watch minutes
15158
15123
  */
15159
- const onJoinRequestDeleted = (callback) => {
15160
- const client = getActiveClient();
15161
- const disposers = [
15162
- createEventSubscriber(client, 'onJoinRequestDeleted', 'local.joinRequest.deleted', payload => callback(payload)),
15163
- ];
15164
- return () => {
15165
- disposers.forEach(fn => fn());
15166
- };
15167
- };
15168
-
15169
- class JoinRequestsLiveCollectionController extends LiveCollectionController {
15170
- constructor(query, callback) {
15171
- const queryStreamId = hash__default["default"](query);
15172
- const cacheKey = ['joinRequest', 'collection', queryStreamId];
15173
- const paginationController = new JoinRequestsPaginationController(query);
15174
- super(paginationController, queryStreamId, cacheKey, callback);
15175
- this.query = query;
15176
- this.queryStreamController = new JoinRequestsQueryStreamController(this.query, this.cacheKey, this.notifyChange.bind(this), prepareCommunityJoinRequestPayload);
15177
- this.callback = callback.bind(this);
15178
- this.loadPage({ initial: true });
15124
+ class WatchSessionStorage {
15125
+ constructor() {
15126
+ this.sessions = new Map();
15179
15127
  }
15180
- setup() {
15181
- var _a;
15182
- const collection = (_a = pullFromCache(this.cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
15183
- if (!collection) {
15184
- pushToCache(this.cacheKey, {
15185
- data: [],
15186
- params: this.query,
15187
- });
15188
- }
15128
+ /**
15129
+ * Add a new watch session
15130
+ */
15131
+ addSession(session) {
15132
+ this.sessions.set(session.sessionId, session);
15133
+ }
15134
+ /**
15135
+ * Get a watch session by sessionId
15136
+ */
15137
+ getSession(sessionId) {
15138
+ return this.sessions.get(sessionId);
15189
15139
  }
15190
- async persistModel(queryPayload) {
15191
- await this.queryStreamController.saveToMainDB(queryPayload);
15140
+ /**
15141
+ * Update a watch session
15142
+ */
15143
+ updateSession(sessionId, updates) {
15144
+ const session = this.sessions.get(sessionId);
15145
+ if (session) {
15146
+ this.sessions.set(sessionId, Object.assign(Object.assign({}, session), updates));
15147
+ }
15192
15148
  }
15193
- persistQueryStream({ response, direction, refresh, }) {
15194
- const joinRequestResponse = response;
15195
- this.queryStreamController.appendToQueryStream(joinRequestResponse, direction, refresh);
15149
+ /**
15150
+ * Get all sessions with a specific sync state
15151
+ */
15152
+ getSessionsByState(state) {
15153
+ return Array.from(this.sessions.values()).filter(session => session.syncState === state);
15196
15154
  }
15197
- startSubscription() {
15198
- return this.queryStreamController.subscribeRTE([
15199
- { fn: onJoinRequestCreated, action: EnumJoinRequestAction$1.OnLocalJoinRequestCreated },
15200
- { fn: onJoinRequestUpdated, action: EnumJoinRequestAction$1.OnLocalJoinRequestUpdated },
15201
- { fn: onJoinRequestDeleted, action: EnumJoinRequestAction$1.OnLocalJoinRequestDeleted },
15202
- ]);
15155
+ /**
15156
+ * Delete a session
15157
+ */
15158
+ deleteSession(sessionId) {
15159
+ this.sessions.delete(sessionId);
15203
15160
  }
15204
- notifyChange({ origin, loading, error }) {
15205
- var _a;
15206
- const collection = (_a = pullFromCache(this.cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
15207
- if (!collection)
15208
- return;
15209
- const data = this.applyFilter(collection.data
15210
- .map(id => pullFromCache(['joinRequest', 'get', id]))
15211
- .filter(isNonNullable)
15212
- .map(({ data }) => data)
15213
- .map(joinRequestLinkedObject));
15214
- if (!this.shouldNotify(data) && origin === 'event')
15215
- return;
15216
- this.callback({
15217
- onNextPage: () => this.loadPage({ direction: "next" /* Amity.LiveCollectionPageDirection.NEXT */ }),
15218
- data,
15219
- hasNextPage: !!this.paginationController.getNextToken(),
15220
- loading,
15221
- error,
15222
- });
15161
+ /**
15162
+ * Get all pending sessions
15163
+ */
15164
+ getPendingSessions() {
15165
+ return this.getSessionsByState('PENDING');
15223
15166
  }
15224
- applyFilter(data) {
15225
- let joinRequest = data;
15226
- if (this.query.status) {
15227
- joinRequest = joinRequest.filter(joinRequest => joinRequest.status === this.query.status);
15228
- }
15229
- const sortFn = (() => {
15230
- switch (this.query.sortBy) {
15231
- case 'firstCreated':
15232
- return sortByFirstCreated;
15233
- case 'lastCreated':
15234
- return sortByLastCreated;
15235
- default:
15236
- return sortByLastCreated;
15237
- }
15238
- })();
15239
- joinRequest = joinRequest.sort(sortFn);
15240
- return joinRequest;
15167
+ /**
15168
+ * Get all syncing sessions
15169
+ */
15170
+ getSyncingSessions() {
15171
+ return this.getSessionsByState('SYNCING');
15241
15172
  }
15242
15173
  }
15174
+ // Singleton instance
15175
+ let storageInstance = null;
15176
+ const getWatchSessionStorage = () => {
15177
+ if (!storageInstance) {
15178
+ storageInstance = new WatchSessionStorage();
15179
+ }
15180
+ return storageInstance;
15181
+ };
15243
15182
 
15244
- /**
15245
- * Get Join Requests
15246
- *
15247
- * @param params the query parameters
15248
- * @param callback the callback to be called when the join request are updated
15249
- * @returns joinRequests
15250
- *
15251
- * @category joinRequest Live Collection
15183
+ 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-----";
15184
+ /*
15185
+ * The crypto algorithm used for importing key and signing string
15186
+ */
15187
+ const ALGORITHM = {
15188
+ name: 'RSASSA-PKCS1-v1_5',
15189
+ hash: { name: 'SHA-256' },
15190
+ };
15191
+ /*
15192
+ * IMPORTANT!
15193
+ * If you are recieving key from other platforms use an online tool to convert
15194
+ * the PKCS1 to PKCS8. For instance the key from Android SDK is of the format
15195
+ * PKCS1.
15252
15196
  *
15197
+ * If recieving from the platform, verify if it's already in the expected
15198
+ * format. Otherwise the crypto.subtle.importKey will throw a DOMException
15253
15199
  */
15254
- const getJoinRequests = (params, callback, config) => {
15255
- const { log, cache } = getActiveClient();
15256
- if (!cache) {
15257
- console.log(ENABLE_CACHE_MESSAGE);
15258
- }
15259
- const timestamp = Date.now();
15260
- log(`getJoinRequests: (tmpid: ${timestamp}) > listen`);
15261
- const joinRequestLiveCollection = new JoinRequestsLiveCollectionController(params, callback);
15262
- const disposers = joinRequestLiveCollection.startSubscription();
15263
- const cacheKey = joinRequestLiveCollection.getCacheKey();
15264
- disposers.push(() => {
15265
- dropFromCache(cacheKey);
15200
+ const PRIVATE_KEY_SIGNATURE = 'pkcs8';
15201
+ /*
15202
+ * Ensure that the private key in the .env follows this format
15203
+ */
15204
+ const PEM_HEADER = '-----BEGIN PRIVATE KEY-----';
15205
+ const PEM_FOOTER = '-----END PRIVATE KEY-----';
15206
+ /*
15207
+ * The crypto.subtle.sign function returns an ArrayBuffer whereas the server
15208
+ * expects a base64 string. This util helps facilitate that process
15209
+ */
15210
+ function base64FromArrayBuffer(buffer) {
15211
+ const uint8Array = new Uint8Array(buffer);
15212
+ let binary = '';
15213
+ uint8Array.forEach(byte => {
15214
+ binary += String.fromCharCode(byte);
15266
15215
  });
15267
- return () => {
15268
- log(`getJoinRequests (tmpid: ${timestamp}) > dispose`);
15269
- disposers.forEach(fn => fn());
15270
- };
15271
- };
15272
-
15273
- var InvitationActionsEnum;
15274
- (function (InvitationActionsEnum) {
15275
- InvitationActionsEnum["OnLocalInvitationCreated"] = "onLocalInvitationCreated";
15276
- InvitationActionsEnum["OnLocalInvitationUpdated"] = "onLocalInvitationUpdated";
15277
- InvitationActionsEnum["OnLocalInvitationCanceled"] = "onLocalInvitationCanceled";
15278
- })(InvitationActionsEnum || (InvitationActionsEnum = {}));
15279
-
15280
- class InvitationsPaginationController extends PaginationController {
15281
- async getRequest(queryParams, token) {
15282
- const { limit = COLLECTION_DEFAULT_PAGINATION_LIMIT } = queryParams, params = __rest(queryParams, ["limit"]);
15283
- const options = token ? { token } : { limit };
15284
- const { data } = await this.http.get('/api/v1/invitations', { params: Object.assign(Object.assign({}, params), { options }) });
15285
- return data;
15286
- }
15216
+ return jsBase64.btoa(binary);
15287
15217
  }
15288
-
15289
- class InvitationsQueryStreamController extends QueryStreamController {
15290
- constructor(query, cacheKey, notifyChange, preparePayload) {
15291
- super(query, cacheKey);
15292
- this.notifyChange = notifyChange;
15293
- this.preparePayload = preparePayload;
15294
- }
15295
- async saveToMainDB(response) {
15296
- const processedPayload = await this.preparePayload(response);
15297
- const client = getActiveClient();
15298
- const cachedAt = client.cache && Date.now();
15299
- if (client.cache) {
15300
- ingestInCache(processedPayload, { cachedAt });
15301
- }
15218
+ /*
15219
+ * Encode ASN.1 length field
15220
+ */
15221
+ function encodeLength(length) {
15222
+ if (length < 128) {
15223
+ return new Uint8Array([length]);
15302
15224
  }
15303
- appendToQueryStream(response, direction, refresh = false) {
15304
- var _a, _b;
15305
- if (refresh) {
15306
- pushToCache(this.cacheKey, {
15307
- data: response.invitations.map(getResolver('invitation')),
15308
- });
15309
- }
15310
- else {
15311
- const collection = (_a = pullFromCache(this.cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
15312
- const invitations = (_b = collection === null || collection === void 0 ? void 0 : collection.data) !== null && _b !== void 0 ? _b : [];
15313
- pushToCache(this.cacheKey, Object.assign(Object.assign({}, collection), { data: [
15314
- ...new Set([...invitations, ...response.invitations.map(getResolver('invitation'))]),
15315
- ] }));
15316
- }
15225
+ if (length < 256) {
15226
+ return new Uint8Array([0x81, length]);
15317
15227
  }
15318
- reactor(action) {
15319
- return (invitations) => {
15320
- var _a;
15321
- const collection = (_a = pullFromCache(this.cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
15322
- if (!collection)
15323
- return;
15324
- if (action === InvitationActionsEnum.OnLocalInvitationUpdated) {
15325
- const isExist = collection.data.find(id => id === invitations[0].invitationId);
15326
- if (!isExist)
15327
- return;
15328
- }
15329
- if (action === InvitationActionsEnum.OnLocalInvitationCreated) {
15330
- collection.data = [
15331
- ...new Set([
15332
- ...invitations.map(invitation => invitation.invitationId),
15333
- ...collection.data,
15334
- ]),
15335
- ];
15336
- }
15337
- if (action === InvitationActionsEnum.OnLocalInvitationDeleted) {
15338
- collection.data = collection.data.filter(id => id !== invitations[0].invitationId);
15339
- }
15340
- pushToCache(this.cacheKey, collection);
15341
- this.notifyChange({ origin: "event" /* Amity.LiveDataOrigin.EVENT */, loading: false });
15342
- };
15228
+ // eslint-disable-next-line no-bitwise
15229
+ return new Uint8Array([0x82, (length >> 8) & 0xff, length & 0xff]);
15230
+ }
15231
+ /*
15232
+ * Convert PKCS1 private key to PKCS8 format
15233
+ * PKCS1 is RSA-specific format, PKCS8 is generic format that crypto.subtle requires
15234
+ * Android uses PKCS8EncodedKeySpec which expects PKCS8 format
15235
+ */
15236
+ function pkcs1ToPkcs8(pkcs1) {
15237
+ // Algorithm identifier for RSA
15238
+ const algorithmIdentifier = new Uint8Array([
15239
+ 0x30,
15240
+ 0x0d,
15241
+ 0x06,
15242
+ 0x09,
15243
+ 0x2a,
15244
+ 0x86,
15245
+ 0x48,
15246
+ 0x86,
15247
+ 0xf7,
15248
+ 0x0d,
15249
+ 0x01,
15250
+ 0x01,
15251
+ 0x01,
15252
+ 0x05,
15253
+ 0x00, // NULL
15254
+ ]);
15255
+ // Version (INTEGER 0)
15256
+ const version = new Uint8Array([0x02, 0x01, 0x00]);
15257
+ // OCTET STRING tag + length + pkcs1 data
15258
+ const octetStringTag = 0x04;
15259
+ const octetStringLength = encodeLength(pkcs1.length);
15260
+ // Calculate total content length (version + algorithm + octet string)
15261
+ const contentLength = version.length + algorithmIdentifier.length + 1 + octetStringLength.length + pkcs1.length;
15262
+ // SEQUENCE tag + length
15263
+ const sequenceTag = 0x30;
15264
+ const sequenceLength = encodeLength(contentLength);
15265
+ // Build the PKCS8 structure
15266
+ const pkcs8 = new Uint8Array(1 + sequenceLength.length + contentLength);
15267
+ let offset = 0;
15268
+ pkcs8[offset] = sequenceTag;
15269
+ offset += 1;
15270
+ pkcs8.set(sequenceLength, offset);
15271
+ offset += sequenceLength.length;
15272
+ pkcs8.set(version, offset);
15273
+ offset += version.length;
15274
+ pkcs8.set(algorithmIdentifier, offset);
15275
+ offset += algorithmIdentifier.length;
15276
+ pkcs8[offset] = octetStringTag;
15277
+ offset += 1;
15278
+ pkcs8.set(octetStringLength, offset);
15279
+ offset += octetStringLength.length;
15280
+ pkcs8.set(pkcs1, offset);
15281
+ return pkcs8;
15282
+ }
15283
+ async function importPrivateKey(keyString) {
15284
+ // Remove PEM headers if present and any whitespace
15285
+ let base64Key = keyString;
15286
+ if (keyString.includes(PEM_HEADER)) {
15287
+ base64Key = keyString
15288
+ .substring(PEM_HEADER.length, keyString.length - PEM_FOOTER.length)
15289
+ .replace(/\s/g, '');
15343
15290
  }
15344
- subscribeRTE(createSubscriber) {
15345
- return createSubscriber.map(subscriber => subscriber.fn(this.reactor(subscriber.action)));
15291
+ else {
15292
+ base64Key = keyString.replace(/\s/g, '');
15293
+ }
15294
+ // Base64 decode to get binary data
15295
+ const binaryDerString = jsBase64.atob(base64Key);
15296
+ // Convert to Uint8Array for manipulation
15297
+ const pkcs1 = new Uint8Array(binaryDerString.length);
15298
+ for (let i = 0; i < binaryDerString.length; i += 1) {
15299
+ pkcs1[i] = binaryDerString.charCodeAt(i);
15346
15300
  }
15301
+ // Convert PKCS1 to PKCS8 (crypto.subtle requires PKCS8)
15302
+ const pkcs8 = pkcs1ToPkcs8(pkcs1);
15303
+ // Import the key
15304
+ const key = await crypto.subtle.importKey(PRIVATE_KEY_SIGNATURE, pkcs8.buffer, ALGORITHM, false, ['sign']);
15305
+ return key;
15306
+ }
15307
+ async function createSignature({ timestamp, rooms, }) {
15308
+ const dataStr = rooms
15309
+ .map(item => Object.keys(item)
15310
+ .sort()
15311
+ .map(key => `${key}=${item[key]}`)
15312
+ .join('&'))
15313
+ .join(';');
15314
+ /*
15315
+ * nonceStr needs to be unique for each request
15316
+ */
15317
+ const nonceStr = uuid__default["default"].v4();
15318
+ const signStr = `nonceStr=${nonceStr}&timestamp=${timestamp}&data=${dataStr}==`;
15319
+ const encoder = new TextEncoder();
15320
+ const data = encoder.encode(signStr);
15321
+ const key = await importPrivateKey(privateKey);
15322
+ const sign = await crypto.subtle.sign(ALGORITHM, key, data);
15323
+ return { signature: base64FromArrayBuffer(sign), nonceStr };
15347
15324
  }
15348
15325
 
15349
15326
  /**
15350
- * ```js
15351
- * import { onLocalInvitationCreated } from '@amityco/ts-sdk-react-native'
15352
- * const dispose = onLocalInvitationCreated(data => {
15353
- * // ...
15354
- * })
15355
- * ```
15356
- *
15357
- * Fired when an {@link Amity.InvitationPayload} has been created
15358
- *
15359
- * @param callback The function to call when the event was fired
15360
- * @returns an {@link Amity.Unsubscriber} function to stop listening
15361
- *
15362
- * @category Invitation Events
15363
- */
15364
- const onLocalInvitationCreated = (callback) => {
15365
- const client = getActiveClient();
15366
- const disposers = [
15367
- createEventSubscriber(client, 'onLocalInvitationCreated', 'local.invitation.created', payload => callback(payload)),
15368
- ];
15369
- return () => {
15370
- disposers.forEach(fn => fn());
15371
- };
15372
- };
15373
-
15374
- /**
15375
- * ```js
15376
- * import { onLocalInvitationUpdated } from '@amityco/ts-sdk-react-native'
15377
- * const dispose = onLocalInvitationUpdated(data => {
15378
- * // ...
15379
- * })
15380
- * ```
15381
- *
15382
- * Fired when an {@link Amity.InvitationPayload} has been updated
15383
- *
15384
- * @param callback The function to call when the event was fired
15385
- * @returns an {@link Amity.Unsubscriber} function to stop listening
15386
- *
15387
- * @category Invitation Events
15388
- */
15389
- const onLocalInvitationUpdated = (callback) => {
15390
- const client = getActiveClient();
15391
- const disposers = [
15392
- createEventSubscriber(client, 'onLocalInvitationUpdated', 'local.invitation.updated', payload => callback(payload)),
15393
- ];
15394
- return () => {
15395
- disposers.forEach(fn => fn());
15396
- };
15397
- };
15398
-
15399
- /**
15400
- * ```js
15401
- * import { onLocalInvitationCanceled } from '@amityco/ts-sdk-react-native'
15402
- * const dispose = onLocalInvitationCanceled(data => {
15403
- * // ...
15404
- * })
15405
- * ```
15406
- *
15407
- * Fired when an {@link Amity.InvitationPayload} has been deleted
15408
- *
15409
- * @param callback The function to call when the event was fired
15410
- * @returns an {@link Amity.Unsubscriber} function to stop listening
15411
- *
15412
- * @category Invitation Events
15327
+ * Sync pending watch sessions to backend
15328
+ * This function implements the full sync flow with network resilience
15413
15329
  */
15414
- const onLocalInvitationCanceled = (callback) => {
15415
- const client = getActiveClient();
15416
- const disposers = [
15417
- createEventSubscriber(client, 'onLocalInvitationCanceled', 'local.invitation.canceled', payload => callback(payload)),
15418
- ];
15419
- return () => {
15420
- disposers.forEach(fn => fn());
15421
- };
15422
- };
15423
-
15424
- class InvitationsLiveCollectionController extends LiveCollectionController {
15425
- constructor(query, callback) {
15426
- const queryStreamId = hash__default["default"](query);
15427
- const cacheKey = ['invitation', 'collection', queryStreamId];
15428
- const paginationController = new InvitationsPaginationController(query);
15429
- super(paginationController, queryStreamId, cacheKey, callback);
15430
- this.query = query;
15431
- this.queryStreamController = new InvitationsQueryStreamController(this.query, this.cacheKey, this.notifyChange.bind(this), prepareInvitationPayload);
15432
- this.callback = callback.bind(this);
15433
- this.loadPage({ initial: true });
15330
+ async function syncWatchSessions() {
15331
+ const storage = getWatchSessionStorage();
15332
+ // Get all pending sessions
15333
+ const pendingSessions = storage.getPendingSessions();
15334
+ if (pendingSessions.length === 0) {
15335
+ return true;
15434
15336
  }
15435
- setup() {
15436
- var _a;
15437
- const collection = (_a = pullFromCache(this.cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
15438
- if (!collection) {
15439
- pushToCache(this.cacheKey, {
15440
- data: [],
15441
- params: this.query,
15442
- });
15337
+ try {
15338
+ const timestamp = new Date().toISOString();
15339
+ // Convert sessions to API format - always include all fields like syncUsage does
15340
+ const rooms = pendingSessions.map(session => ({
15341
+ sessionId: session.sessionId,
15342
+ roomId: session.roomId,
15343
+ watchSeconds: session.watchSeconds,
15344
+ startTime: session.startTime.toISOString(),
15345
+ endTime: session.endTime ? session.endTime.toISOString() : '',
15346
+ }));
15347
+ // Create signature (reuse from stream feature) - pass directly like syncUsage
15348
+ const signatureData = await createSignature({
15349
+ timestamp,
15350
+ rooms,
15351
+ });
15352
+ if (!signatureData || !signatureData.signature) {
15353
+ throw new Error('Signature is undefined');
15443
15354
  }
15444
- }
15445
- async persistModel(queryPayload) {
15446
- await this.queryStreamController.saveToMainDB(queryPayload);
15447
- }
15448
- persistQueryStream({ response, direction, refresh, }) {
15449
- this.queryStreamController.appendToQueryStream(response, direction, refresh);
15450
- }
15451
- startSubscription() {
15452
- return this.queryStreamController.subscribeRTE([
15453
- {
15454
- fn: onLocalInvitationCreated,
15455
- action: InvitationActionsEnum.OnLocalInvitationCreated,
15456
- },
15457
- {
15458
- fn: onLocalInvitationUpdated,
15459
- action: InvitationActionsEnum.OnLocalInvitationUpdated,
15460
- },
15461
- {
15462
- fn: onLocalInvitationCanceled,
15463
- action: InvitationActionsEnum.OnLocalInvitationCanceled,
15464
- },
15465
- ]);
15466
- }
15467
- notifyChange({ origin, loading, error }) {
15468
- var _a, _b;
15469
- const collection = (_a = pullFromCache(this.cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
15470
- if (!collection)
15471
- return;
15472
- const data = this.applyFilter((_b = collection.data
15473
- .map(id => pullFromCache(['invitation', 'get', id]))
15474
- .filter(isNonNullable)
15475
- .map(({ data }) => invitationLinkedObject(data))) !== null && _b !== void 0 ? _b : []);
15476
- if (!this.shouldNotify(data) && origin === 'event')
15477
- return;
15478
- this.callback({
15479
- onNextPage: () => this.loadPage({ direction: "next" /* Amity.LiveCollectionPageDirection.NEXT */ }),
15480
- data,
15481
- hasNextPage: !!this.paginationController.getNextToken(),
15482
- loading,
15483
- error,
15355
+ // Update sync state to SYNCING
15356
+ pendingSessions.forEach(session => {
15357
+ storage.updateSession(session.sessionId, { syncState: 'SYNCING' });
15358
+ });
15359
+ const payload = {
15360
+ signature: signatureData.signature,
15361
+ nonceStr: signatureData.nonceStr,
15362
+ timestamp,
15363
+ rooms,
15364
+ };
15365
+ const client = getActiveClient();
15366
+ // Send to backend
15367
+ await client.http.post('/api/v3/user-event/room', payload);
15368
+ // Success - update to SYNCED
15369
+ pendingSessions.forEach(session => {
15370
+ storage.updateSession(session.sessionId, {
15371
+ syncState: 'SYNCED',
15372
+ syncedAt: new Date(),
15373
+ });
15484
15374
  });
15375
+ return true;
15485
15376
  }
15486
- applyFilter(data) {
15487
- let invitations = data;
15488
- if (this.query.targetId) {
15489
- invitations = invitations.filter(invitation => invitation.targetId === this.query.targetId);
15490
- }
15491
- if (this.query.statuses) {
15492
- invitations = invitations.filter(invitation => { var _a; return (_a = this.query.statuses) === null || _a === void 0 ? void 0 : _a.includes(invitation.status); });
15493
- }
15494
- if (this.query.targetType) {
15495
- invitations = invitations.filter(invitation => invitation.targetType === this.query.targetType);
15496
- }
15497
- if (this.query.type) {
15498
- invitations = invitations.filter(invitation => invitation.type === this.query.type);
15499
- }
15500
- const sortFn = (() => {
15501
- switch (this.query.sortBy) {
15502
- case 'firstCreated':
15503
- return sortByFirstCreated;
15504
- case 'lastCreated':
15505
- return sortByLastCreated;
15506
- default:
15507
- return sortByLastCreated;
15377
+ catch (err) {
15378
+ console.error('[SDK syncWatchSessions] ERROR caught:', (err === null || err === void 0 ? void 0 : err.message) || err);
15379
+ // Failure - update back to PENDING and increment retry count
15380
+ pendingSessions.forEach(session => {
15381
+ const currentSession = storage.getSession(session.sessionId);
15382
+ if (currentSession) {
15383
+ const newRetryCount = currentSession.retryCount + 1;
15384
+ if (newRetryCount >= 3) {
15385
+ // Delete session if retry count exceeds 3
15386
+ storage.deleteSession(session.sessionId);
15387
+ }
15388
+ else {
15389
+ // Update to PENDING with incremented retry count
15390
+ storage.updateSession(session.sessionId, {
15391
+ syncState: 'PENDING',
15392
+ retryCount: newRetryCount,
15393
+ });
15394
+ }
15508
15395
  }
15509
- })();
15510
- invitations = invitations.sort(sortFn);
15511
- return invitations;
15396
+ });
15397
+ return false;
15512
15398
  }
15513
15399
  }
15514
15400
 
15515
15401
  /**
15516
- * Get invitations
15517
- *
15518
- * @param params the query parameters
15519
- * @param callback the callback to be called when the invitations are updated
15520
- * @returns invitations
15521
- *
15522
- * @category Invitation Live Collection
15523
- *
15402
+ * Room statuses that are considered watchable
15524
15403
  */
15525
- const getInvitations$1 = (params, callback, config) => {
15526
- const { log, cache } = getActiveClient();
15527
- if (!cache) {
15528
- console.log(ENABLE_CACHE_MESSAGE);
15529
- }
15530
- const timestamp = Date.now();
15531
- log(`getInvitations: (tmpid: ${timestamp}) > listen`);
15532
- const invitationsLiveCollection = new InvitationsLiveCollectionController(params, callback);
15533
- const disposers = invitationsLiveCollection.startSubscription();
15534
- const cacheKey = invitationsLiveCollection.getCacheKey();
15535
- disposers.push(() => {
15536
- dropFromCache(cacheKey);
15404
+ const WATCHABLE_ROOM_STATUSES = ['live', 'recorded'];
15405
+ /**
15406
+ * Generate a random jitter delay between 5 and 30 seconds
15407
+ */
15408
+ const getJitterDelay = () => {
15409
+ const minDelay = 5000; // 5 seconds
15410
+ const maxDelay = 30000; // 30 seconds
15411
+ return Math.floor(Math.random() * (maxDelay - minDelay + 1)) + minDelay;
15412
+ };
15413
+ /**
15414
+ * Wait for network connection with timeout
15415
+ * @param maxWaitTime Maximum time to wait in milliseconds (default: 60000 = 60 seconds)
15416
+ * @returns Promise that resolves when network is available or timeout is reached
15417
+ */
15418
+ const waitForNetwork = (maxWaitTime = 60000) => {
15419
+ return new Promise(resolve => {
15420
+ // Simple check - if navigator.onLine is available, use it
15421
+ // Otherwise, assume network is available
15422
+ if (typeof navigator === 'undefined' || typeof navigator.onLine === 'undefined') {
15423
+ resolve();
15424
+ return;
15425
+ }
15426
+ const startTime = Date.now();
15427
+ const checkInterval = 1000; // 1 second
15428
+ const checkConnection = () => {
15429
+ if (navigator.onLine || Date.now() - startTime >= maxWaitTime) {
15430
+ resolve();
15431
+ }
15432
+ else {
15433
+ setTimeout(checkConnection, checkInterval);
15434
+ }
15435
+ };
15436
+ checkConnection();
15537
15437
  });
15538
- return () => {
15539
- log(`getInvitations (tmpid: ${timestamp}) > dispose`);
15540
- disposers.forEach(fn => fn());
15541
- };
15542
15438
  };
15439
+ /**
15440
+ * AmityRoomAnalytics provides analytics capabilities for room watch sessions
15441
+ */
15442
+ class AmityRoomAnalytics {
15443
+ constructor(room) {
15444
+ this.storage = getWatchSessionStorage();
15445
+ this.client = getActiveClient();
15446
+ this.room = room;
15447
+ }
15448
+ /**
15449
+ * Create a new watch session for the current room
15450
+ * @param startedAt The timestamp when watching started
15451
+ * @returns Promise<string> sessionId unique identifier for this watch session
15452
+ * @throws ASCApiError if room is not in watchable state (not LIVE or RECORDED)
15453
+ */
15454
+ async createWatchSession(startedAt) {
15455
+ // Validate room status
15456
+ if (!WATCHABLE_ROOM_STATUSES.includes(this.room.status)) {
15457
+ throw new ASCApiError('room is not in watchable state', 500000 /* Amity.ServerError.BUSINESS_ERROR */, "error" /* Amity.ErrorLevel.ERROR */);
15458
+ }
15459
+ // Generate session ID with prefix
15460
+ const prefix = this.room.status === 'live' ? 'room_' : 'room_playback_';
15461
+ const sessionId = prefix + uuid__default["default"].v4();
15462
+ // Create watch session entity
15463
+ const session = {
15464
+ sessionId,
15465
+ roomId: this.room.roomId,
15466
+ watchSeconds: 0,
15467
+ startTime: startedAt,
15468
+ endTime: null,
15469
+ syncState: 'PENDING',
15470
+ syncedAt: null,
15471
+ retryCount: 0,
15472
+ };
15473
+ // Persist to storage
15474
+ this.storage.addSession(session);
15475
+ return sessionId;
15476
+ }
15477
+ /**
15478
+ * Update an existing watch session with duration
15479
+ * @param sessionId The unique identifier of the watch session
15480
+ * @param duration The total watch duration in seconds
15481
+ * @param endedAt The timestamp when this update occurred
15482
+ * @returns Promise<void> Completion status
15483
+ */
15484
+ async updateWatchSession(sessionId, duration, endedAt) {
15485
+ const session = this.storage.getSession(sessionId);
15486
+ if (!session) {
15487
+ throw new Error(`Watch session ${sessionId} not found`);
15488
+ }
15489
+ // Update session
15490
+ this.storage.updateSession(sessionId, {
15491
+ watchSeconds: duration,
15492
+ endTime: endedAt,
15493
+ });
15494
+ }
15495
+ /**
15496
+ * Sync all pending watch sessions to backend
15497
+ * This function uses jitter delay and handles network resilience
15498
+ */
15499
+ syncPendingWatchSessions() {
15500
+ // Execute with jitter delay (5-30 seconds)
15501
+ const jitterDelay = getJitterDelay();
15502
+ this.client.log('room/RoomAnalytics: syncPendingWatchSessions called, jitter delay:', `${jitterDelay}ms`);
15503
+ setTimeout(async () => {
15504
+ this.client.log('room/RoomAnalytics: Jitter delay completed, starting sync process');
15505
+ try {
15506
+ // Reset any SYNCING sessions back to PENDING
15507
+ const syncingSessions = this.storage.getSyncingSessions();
15508
+ this.client.log('room/RoomAnalytics: SYNCING sessions to reset:', syncingSessions.length);
15509
+ syncingSessions.forEach(session => {
15510
+ this.storage.updateSession(session.sessionId, { syncState: 'PENDING' });
15511
+ });
15512
+ // Wait for network connection (max 60 seconds)
15513
+ await waitForNetwork(60000);
15514
+ this.client.log('room/RoomAnalytics: Network available');
15515
+ // Sync pending sessions
15516
+ this.client.log('room/RoomAnalytics: Calling syncWatchSessions()');
15517
+ await syncWatchSessions();
15518
+ this.client.log('room/RoomAnalytics: syncWatchSessions completed');
15519
+ }
15520
+ catch (error) {
15521
+ // Error is already handled in syncWatchSessions
15522
+ console.error('Failed to sync watch sessions:', error);
15523
+ }
15524
+ }, jitterDelay);
15525
+ }
15526
+ }
15543
15527
 
15544
- const communityLinkedObject = (community) => {
15545
- return Object.assign(Object.assign({}, community), { get categories() {
15528
+ const roomLinkedObject = (room) => {
15529
+ return Object.assign(Object.assign({}, room), { get post() {
15546
15530
  var _a;
15547
- return ((_a = community === null || community === void 0 ? void 0 : community.categoryIds) !== null && _a !== void 0 ? _a : [])
15548
- .map(categoryId => {
15549
- const cacheData = pullFromCache(['category', 'get', categoryId]);
15550
- if (cacheData === null || cacheData === void 0 ? void 0 : cacheData.data)
15551
- return categoryLinkedObject(cacheData.data);
15552
- return undefined;
15553
- })
15554
- .filter(category => !!category);
15531
+ if (room.referenceType !== 'post')
15532
+ return;
15533
+ return (_a = pullFromCache(['post', 'get', room.referenceId])) === null || _a === void 0 ? void 0 : _a.data;
15555
15534
  },
15556
- get avatar() {
15535
+ get community() {
15557
15536
  var _a;
15558
- if (!community.avatarFileId)
15559
- return undefined;
15560
- const avatar = (_a = pullFromCache([
15561
- 'file',
15562
- 'get',
15563
- community.avatarFileId,
15564
- ])) === null || _a === void 0 ? void 0 : _a.data;
15565
- return avatar;
15566
- }, createInvitations: async (userIds) => {
15567
- await createInvitations({
15568
- type: "communityMemberInvite" /* InvitationTypeEnum.CommunityMemberInvite */,
15569
- targetType: 'community',
15570
- targetId: community.communityId,
15571
- userIds,
15572
- });
15573
- }, getMemberInvitations: (params, callback) => {
15574
- return getInvitations$1(Object.assign(Object.assign({}, params), { targetId: community.communityId, targetType: 'community', type: "communityMemberInvite" /* InvitationTypeEnum.CommunityMemberInvite */ }), callback);
15575
- }, getInvitation: async () => {
15537
+ if (room.targetType !== 'community')
15538
+ return;
15539
+ return (_a = pullFromCache(['community', 'get', room.targetId])) === null || _a === void 0 ? void 0 : _a.data;
15540
+ },
15541
+ get user() {
15542
+ var _a;
15543
+ const user = (_a = pullFromCache(['user', 'get', room.createdBy])) === null || _a === void 0 ? void 0 : _a.data;
15544
+ return user ? userLinkedObject(user) : user;
15545
+ },
15546
+ get childRooms() {
15547
+ if (!room.childRoomIds || room.childRoomIds.length === 0)
15548
+ return [];
15549
+ return room.childRoomIds
15550
+ .map(id => {
15551
+ var _a;
15552
+ const roomCache = (_a = pullFromCache(['room', 'get', id])) === null || _a === void 0 ? void 0 : _a.data;
15553
+ if (!roomCache)
15554
+ return undefined;
15555
+ return roomLinkedObject(roomCache);
15556
+ })
15557
+ .filter(isNonNullable);
15558
+ }, participants: room.participants.map(participant => (Object.assign(Object.assign({}, participant), { get user() {
15559
+ var _a;
15560
+ const user = (_a = pullFromCache(['user', 'get', participant.userId])) === null || _a === void 0 ? void 0 : _a.data;
15561
+ return user ? userLinkedObject(user) : user;
15562
+ } }))), getLiveChat: () => getLiveChat(room), createInvitation: (userId) => createInvitations({
15563
+ type: "livestreamCohostInvite" /* InvitationTypeEnum.LivestreamCohostInvite */,
15564
+ targetType: 'room',
15565
+ targetId: room.roomId,
15566
+ userIds: [userId],
15567
+ }), getInvitations: async () => {
15576
15568
  const { data } = await getInvitation({
15577
- targetType: 'community',
15578
- targetId: community.communityId,
15569
+ targetId: room.roomId,
15570
+ targetType: 'room',
15571
+ type: "livestreamCohostInvite" /* InvitationTypeEnum.LivestreamCohostInvite */,
15579
15572
  });
15580
15573
  return data;
15581
- }, join: async () => joinRequest(community.communityId), getJoinRequests: (params, callback) => {
15582
- return getJoinRequests(Object.assign(Object.assign({}, params), { communityId: community.communityId }), callback);
15583
- }, getMyJoinRequest: async () => {
15584
- const { data } = await getMyJoinRequest(community.communityId);
15585
- return data;
15574
+ }, analytics() {
15575
+ // Use 'this' to avoid creating a new room object
15576
+ return new AmityRoomAnalytics(this);
15586
15577
  } });
15587
15578
  };
15588
15579
 
15580
+ const pollLinkedObject = (poll) => {
15581
+ return Object.assign(Object.assign({}, poll), { answers: poll.answers.map(answer => (Object.assign(Object.assign({}, answer), { get image() {
15582
+ var _a;
15583
+ if (!answer.fileId)
15584
+ return undefined;
15585
+ return (_a = pullFromCache(['file', 'get', answer.fileId])) === null || _a === void 0 ? void 0 : _a.data;
15586
+ } }))) });
15587
+ };
15588
+
15589
15589
  const productLinkedObject = (product) => {
15590
15590
  const analyticsEngineInstance = AnalyticsEngine$1.getInstance();
15591
15591
  return Object.assign(Object.assign({}, product), { analytics: {