@corva/chat-core 0.1.6 → 0.1.8

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.d.ts CHANGED
@@ -1175,6 +1175,7 @@ interface CorvaRevoltAuthResponse {
1175
1175
  revolt_channel_id: string;
1176
1176
  revolt_channel_server_id?: string;
1177
1177
  revolt_channel_company_id?: number;
1178
+ revolt_channel_joined?: boolean;
1178
1179
  revolt_chat_channels?: AssetChatChannel[];
1179
1180
  chat_used?: boolean | null;
1180
1181
  }
@@ -1246,8 +1247,11 @@ interface AssetChatSession {
1246
1247
  channelId: string;
1247
1248
  serverId: string | null;
1248
1249
  companyId: number | null;
1250
+ joined: boolean;
1249
1251
  }
1250
- declare function getAssetChatSession(assetId: string, assetType: ChatAssetType): Promise<AssetChatSession>;
1252
+ declare function getAssetChatSession(assetId: string, assetType: ChatAssetType, { join }?: {
1253
+ join?: boolean;
1254
+ }): Promise<AssetChatSession>;
1251
1255
  declare function getAssetChatChannel(assetId: string, assetType: ChatAssetType): Promise<string>;
1252
1256
 
1253
1257
  type StoredCorvaUser = CorvaUser | CorvaAPIUser;
@@ -1517,6 +1521,12 @@ interface UIStore {
1517
1521
  declare const uiStore: zustand_vanilla.StoreApi<UIStore>;
1518
1522
  declare const resetUIStore: () => void;
1519
1523
 
1524
+ interface JoinRequired {
1525
+ assetId: string;
1526
+ assetType: ChatAssetType;
1527
+ companyId: number | null;
1528
+ companyName: string | null;
1529
+ }
1520
1530
  type LockedAsset = ChatAsset & {
1521
1531
  type: ChatAssetType;
1522
1532
  };
@@ -1527,6 +1537,7 @@ interface AssetStore {
1527
1537
  currentAssetStatus: string | null;
1528
1538
  assetChatId: string | null;
1529
1539
  assetChatError: string | null;
1540
+ joinRequired: JoinRequired | null;
1530
1541
  knownAssetChatIds: Set<string>;
1531
1542
  panelSyncedAssetId: string | null;
1532
1543
  isAssetLocked: boolean;
@@ -1534,6 +1545,7 @@ interface AssetStore {
1534
1545
  isAssetSwitching: boolean;
1535
1546
  setAssetContext: (assetId: string, assetType: ChatAssetType, assetName?: string, assetStatus?: string, skipAutoSelect?: boolean) => Promise<void>;
1536
1547
  clearAssetContext: () => void;
1548
+ joinAssetChat: () => Promise<void>;
1537
1549
  ensureAssetChatSubscription: () => Promise<Subscription | null>;
1538
1550
  toggleAssetLock: () => void;
1539
1551
  relockToAsset: (assetId: string, assetType: ChatAssetType, assetName: string) => Promise<void>;
@@ -1722,4 +1734,4 @@ declare const createSocketEventHandlers: (config: SocketEventHandlersConfig) =>
1722
1734
 
1723
1735
  declare const installUnreadWatcher: () => void;
1724
1736
 
1725
- export { ALERT_SEVERITY, ASSET_API_FIELDS, ASSET_CHAT_PREFIXES, ASSET_NOUN, type AckScheduler, type AlertData, type AlertSeverity, type AlertWirePayload, type AppCommentAttachment, type AppCommentData, type AppCommentWirePayload, type AppStateAdapter, type AskCorvaData, type AskCorvaWirePayload, type AssetChatChannel, type AssetChatSession, type AssetStore, type Attachment, type AuthStore, CHANNEL_NAME_MAX_LENGTH, CHANNEL_TYPES, CORVA_MESSAGE_TYPES, CORVA_SYS_PREFIX, type ChannelAsset, type ChannelContentFilter, type ChannelContentFilterStore, type ChannelContentFilters, type ChannelNameValidation, type ChannelNotificationPreference, type ChannelNotificationSetting, type ChannelUnread, type ChatAsset, type ChatAssetIdentity, type ChatAssetType, type ChatDates, type ChatHost, type ChatNotifier, type ChatPlatform, type CorvaAPIUser, type CorvaApiAdapter, type CorvaRevoltAuthResponse, type CorvaSystemMessage, type CorvaUser, type CorvaUserService, DATE_SEPARATOR_LABELS, DEFAULT_CHANNEL_CONTENT_FILTER, DEFAULT_CHANNEL_CONTENT_FILTERS, DEFAULT_CHANNEL_PREFERENCE, DEFAULT_FAVORITE_ROOMS_SETTINGS, DEFAULT_HIDDEN_ROOMS_SETTINGS, DEFAULT_NOTIFICATION_PREFERENCES, DEFAULT_NOTIFICATION_SETTINGS, DEFAULT_ROOM_LIST_ORDER, DIRECT_MESSAGE_PLACEHOLDER, type ExternalChannel, type FavoriteRoomsSettings, type FavoriteRoomsStore, type FeedItemData, type FeedWirePayload, type FileAttachment, type FilterEntityWindow, type ForwardWirePayload, type ForwardedFrom, GENERAL_CHAT_NAME, type HiddenRoomsSettings, type HttpClient, type HttpClientConfig, HttpError, type HttpRequestInit, type HttpResponseLike, type KeyValueStorage, type LocatorContext, type LoginCredentials, MAX_ATTACHMENT_SIZE_BYTES, MAX_ATTACHMENT_SIZE_MB, MAX_NAVIGATION_HISTORY, MENTION_REPLACE_PATTERN, MENTION_SPLIT_PATTERN, MUTE_PRESET_OPTIONS, type MemberStore, type Message, type MessageCache, type MessageFormData, type MessageStore, NOTIFICATION_DESTINATIONS, NOTIFICATION_SETTING_ALL, NOTIFICATION_SETTING_MENTIONS, NOTIFICATION_SETTING_NOTHING, type NavigationEntry, type NavigationHistoryStore, type NotificationDestination, type NotificationPreferences, type NotificationSettings, type NotificationStore, PAUSE_INDEFINITELY, PAUSE_PRESETS, PAUSE_PRESET_OPTIONS, type PausePreset, type PausePresetOption, REVOLT_SYSTEM_USER_ID, ROOM_LIST_ORDER, type ReadyChannelData, type RevoltAPIInstance, type RevoltChannel, type RevoltIncomingMessagePayload, type RevoltLoginResponse, type RevoltMessage, type RevoltMessageResponse, type RevoltSocketConfig, type RevoltSocketEventHandlers, type RevoltSocketInstance, type RevoltUploadResponse, type RevoltUserResponse, type Room, type RoomListOrder, type RoomStore, type RoomType, SESSION_STORAGE_KEY, SIDEBAR_SECTIONS, SIDEBAR_TABS, SOFT_DELETE_MARKER, SYSTEM_MESSAGE_TEXTS, type SaveSessionParams, type SelectableAssetType, type SessionData, SessionManager, type SharedFile, type SharedRefs, type SidebarSectionKey, type SidebarTabKey, type SocketCloseEventLike, type SocketEventHandlersConfig, type StoredChannelPreference, type Subscription, type TracesViewportRequest, type TypingManager, type UIStore, type UploadAndSendResult, type UploadFile, type UploadedFile, type User, type UserStatus, type ViewportDeepLink, type ViewportIndexCurve, type ViewportMode, WEBSOCKET_CONNECTING, WEBSOCKET_OPEN, type WebSocketLike, type WireSeverity, addMessage, addOrUpdateSubscription, alertMessageAsText, assetStore, authStore, buildAppCommentMessageContent, buildAskCorvaMessageContent, buildFinalMessage, buildForwardMessageContent, buildGroupChannelName, canDeleteMessage, canEditMessage, channelContentFilterStore, channelToAsset, chatToastStore, clearLastOpenedRoom, compareByActivity, compareByName, compareByRecencyDesc, configureChat, configureChatStorage, createAckScheduler, createCorvaUserService, createDMSubscription, createGroupSubscription, createHttpClient, createLatestWinsQueue, createMemoryStorage, createMessageCache, createRevoltAPI, createRevoltSocket, createRoomTaskQueue, createSocketEventHandlers, createSoftDeletedMessage, createTypingManager, deriveAllowedChatAsset, enrichWithCorvaData, ensureChatSession, extractTimestampFromULID, failOptimisticMessage, favoriteRoomsStore, findGeneralRoom, formatAssetChatName, getAppCommentAttachments, getAssetChatChannel, getAssetChatSession, getAssetTypeFromDisplayName, getChatHost, getChatStorage, getCorvaUserFields, getExternalChannel, getLastOpenedRoom, getMessageTimestamp, getPauseUntil, getReactionCount, getRoomDisplayName, getSystemMessageWithCorvaNames, getUserDisplayName, getUserSecondaryText, handleUnauthorized, hasReactions, hasUserReacted, initChat, installUnreadWatcher, isAlertMessage, isAppCommentMessage, isAskCorvaMessage, isChannelMuted, isChatAssetTypeAllowed, isChatStorageConfigured, isCurrentRoomSelection, isDeepEqual, isDefaultChannelPreference, isDisallowedAssetChatRoom, isDmGroup, isExternalServerChannel, isForwardedMessage, isGeneralRoom, isNotificationsPaused, isPauseActive, isSoftDeletedMessage, isSystemMessage, isUnread, isUserOnline, isValidPausePreset, isVisibleUnread, keepChatUsed, loadUntilFound, memberStore, messageStore, navigationHistoryStore, notificationStore, onChatStorageConfigured, parseCorvaSystemMessage, prepareRoomSelection, removeMessageFromList, removeSubscription, resetAssetStore, resetAuthStore, resetChannelContentFilterStore, resetChatAssetPermissionsSnapshot, resetChatHost, resetFavoriteRoomsStore, resetMemberStore, resetMessageStore, resetNavigationHistoryStore, resetNotificationStore, resetRoomStore, resetUIStore, roomStore, saveLastChatActivity, saveLastOpenedRoom, searchMessages, searchRooms, searchUsers, selectCanGoBack, selectCanGoForward, setAllowedChatAssetTypes, settleOptimisticMessage, sharedRefs, sortChannels, sortDMs, sortMessagesByTime, sortUsersByStatus, stripPlatformMentions, uiStore, updateMessageInList, uploadAndSend, validateChannelName, waitForNextPaint, wasRecentlyActive, withChannelPreferenceDefaults };
1737
+ export { ALERT_SEVERITY, ASSET_API_FIELDS, ASSET_CHAT_PREFIXES, ASSET_NOUN, type AckScheduler, type AlertData, type AlertSeverity, type AlertWirePayload, type AppCommentAttachment, type AppCommentData, type AppCommentWirePayload, type AppStateAdapter, type AskCorvaData, type AskCorvaWirePayload, type AssetChatChannel, type AssetChatSession, type AssetStore, type Attachment, type AuthStore, CHANNEL_NAME_MAX_LENGTH, CHANNEL_TYPES, CORVA_MESSAGE_TYPES, CORVA_SYS_PREFIX, type ChannelAsset, type ChannelContentFilter, type ChannelContentFilterStore, type ChannelContentFilters, type ChannelNameValidation, type ChannelNotificationPreference, type ChannelNotificationSetting, type ChannelUnread, type ChatAsset, type ChatAssetIdentity, type ChatAssetType, type ChatDates, type ChatHost, type ChatNotifier, type ChatPlatform, type CorvaAPIUser, type CorvaApiAdapter, type CorvaRevoltAuthResponse, type CorvaSystemMessage, type CorvaUser, type CorvaUserService, DATE_SEPARATOR_LABELS, DEFAULT_CHANNEL_CONTENT_FILTER, DEFAULT_CHANNEL_CONTENT_FILTERS, DEFAULT_CHANNEL_PREFERENCE, DEFAULT_FAVORITE_ROOMS_SETTINGS, DEFAULT_HIDDEN_ROOMS_SETTINGS, DEFAULT_NOTIFICATION_PREFERENCES, DEFAULT_NOTIFICATION_SETTINGS, DEFAULT_ROOM_LIST_ORDER, DIRECT_MESSAGE_PLACEHOLDER, type ExternalChannel, type FavoriteRoomsSettings, type FavoriteRoomsStore, type FeedItemData, type FeedWirePayload, type FileAttachment, type FilterEntityWindow, type ForwardWirePayload, type ForwardedFrom, GENERAL_CHAT_NAME, type HiddenRoomsSettings, type HttpClient, type HttpClientConfig, HttpError, type HttpRequestInit, type HttpResponseLike, type JoinRequired, type KeyValueStorage, type LocatorContext, type LoginCredentials, MAX_ATTACHMENT_SIZE_BYTES, MAX_ATTACHMENT_SIZE_MB, MAX_NAVIGATION_HISTORY, MENTION_REPLACE_PATTERN, MENTION_SPLIT_PATTERN, MUTE_PRESET_OPTIONS, type MemberStore, type Message, type MessageCache, type MessageFormData, type MessageStore, NOTIFICATION_DESTINATIONS, NOTIFICATION_SETTING_ALL, NOTIFICATION_SETTING_MENTIONS, NOTIFICATION_SETTING_NOTHING, type NavigationEntry, type NavigationHistoryStore, type NotificationDestination, type NotificationPreferences, type NotificationSettings, type NotificationStore, PAUSE_INDEFINITELY, PAUSE_PRESETS, PAUSE_PRESET_OPTIONS, type PausePreset, type PausePresetOption, REVOLT_SYSTEM_USER_ID, ROOM_LIST_ORDER, type ReadyChannelData, type RevoltAPIInstance, type RevoltChannel, type RevoltIncomingMessagePayload, type RevoltLoginResponse, type RevoltMessage, type RevoltMessageResponse, type RevoltSocketConfig, type RevoltSocketEventHandlers, type RevoltSocketInstance, type RevoltUploadResponse, type RevoltUserResponse, type Room, type RoomListOrder, type RoomStore, type RoomType, SESSION_STORAGE_KEY, SIDEBAR_SECTIONS, SIDEBAR_TABS, SOFT_DELETE_MARKER, SYSTEM_MESSAGE_TEXTS, type SaveSessionParams, type SelectableAssetType, type SessionData, SessionManager, type SharedFile, type SharedRefs, type SidebarSectionKey, type SidebarTabKey, type SocketCloseEventLike, type SocketEventHandlersConfig, type StoredChannelPreference, type Subscription, type TracesViewportRequest, type TypingManager, type UIStore, type UploadAndSendResult, type UploadFile, type UploadedFile, type User, type UserStatus, type ViewportDeepLink, type ViewportIndexCurve, type ViewportMode, WEBSOCKET_CONNECTING, WEBSOCKET_OPEN, type WebSocketLike, type WireSeverity, addMessage, addOrUpdateSubscription, alertMessageAsText, assetStore, authStore, buildAppCommentMessageContent, buildAskCorvaMessageContent, buildFinalMessage, buildForwardMessageContent, buildGroupChannelName, canDeleteMessage, canEditMessage, channelContentFilterStore, channelToAsset, chatToastStore, clearLastOpenedRoom, compareByActivity, compareByName, compareByRecencyDesc, configureChat, configureChatStorage, createAckScheduler, createCorvaUserService, createDMSubscription, createGroupSubscription, createHttpClient, createLatestWinsQueue, createMemoryStorage, createMessageCache, createRevoltAPI, createRevoltSocket, createRoomTaskQueue, createSocketEventHandlers, createSoftDeletedMessage, createTypingManager, deriveAllowedChatAsset, enrichWithCorvaData, ensureChatSession, extractTimestampFromULID, failOptimisticMessage, favoriteRoomsStore, findGeneralRoom, formatAssetChatName, getAppCommentAttachments, getAssetChatChannel, getAssetChatSession, getAssetTypeFromDisplayName, getChatHost, getChatStorage, getCorvaUserFields, getExternalChannel, getLastOpenedRoom, getMessageTimestamp, getPauseUntil, getReactionCount, getRoomDisplayName, getSystemMessageWithCorvaNames, getUserDisplayName, getUserSecondaryText, handleUnauthorized, hasReactions, hasUserReacted, initChat, installUnreadWatcher, isAlertMessage, isAppCommentMessage, isAskCorvaMessage, isChannelMuted, isChatAssetTypeAllowed, isChatStorageConfigured, isCurrentRoomSelection, isDeepEqual, isDefaultChannelPreference, isDisallowedAssetChatRoom, isDmGroup, isExternalServerChannel, isForwardedMessage, isGeneralRoom, isNotificationsPaused, isPauseActive, isSoftDeletedMessage, isSystemMessage, isUnread, isUserOnline, isValidPausePreset, isVisibleUnread, keepChatUsed, loadUntilFound, memberStore, messageStore, navigationHistoryStore, notificationStore, onChatStorageConfigured, parseCorvaSystemMessage, prepareRoomSelection, removeMessageFromList, removeSubscription, resetAssetStore, resetAuthStore, resetChannelContentFilterStore, resetChatAssetPermissionsSnapshot, resetChatHost, resetFavoriteRoomsStore, resetMemberStore, resetMessageStore, resetNavigationHistoryStore, resetNotificationStore, resetRoomStore, resetUIStore, roomStore, saveLastChatActivity, saveLastOpenedRoom, searchMessages, searchRooms, searchUsers, selectCanGoBack, selectCanGoForward, setAllowedChatAssetTypes, settleOptimisticMessage, sharedRefs, sortChannels, sortDMs, sortMessagesByTime, sortUsersByStatus, stripPlatformMentions, uiStore, updateMessageInList, uploadAndSend, validateChannelName, waitForNextPaint, wasRecentlyActive, withChannelPreferenceDefaults };
package/dist/index.js CHANGED
@@ -2988,11 +2988,11 @@ var ASSET_ID_PARAM = {
2988
2988
  frac_fleet: "frac_fleet_id",
2989
2989
  intervention_unit: "intervention_unit_id"
2990
2990
  };
2991
- async function getAssetChatSession(assetId, assetType) {
2991
+ async function getAssetChatSession(assetId, assetType, { join = false } = {}) {
2992
2992
  if (!assetId || Number.isNaN(Number(assetId))) {
2993
2993
  throw new Error("Asset ID is required");
2994
2994
  }
2995
- const body = { [ASSET_ID_PARAM[assetType]]: Number(assetId) };
2995
+ const body = { [ASSET_ID_PARAM[assetType]]: Number(assetId), ...join && { join: true } };
2996
2996
  const response = await getChatHost().corvaApi.post(
2997
2997
  "/v2/integration/revolt_chat_sessions",
2998
2998
  body
@@ -3003,7 +3003,8 @@ async function getAssetChatSession(assetId, assetType) {
3003
3003
  return {
3004
3004
  channelId: response.revolt_channel_id,
3005
3005
  serverId: response.revolt_channel_server_id ?? null,
3006
- companyId: response.revolt_channel_company_id ?? null
3006
+ companyId: response.revolt_channel_company_id ?? null,
3007
+ joined: response.revolt_channel_joined ?? true
3007
3008
  };
3008
3009
  }
3009
3010
  async function getAssetChatChannel(assetId, assetType) {
@@ -3598,6 +3599,75 @@ var resetMemberStore = () => {
3598
3599
  invalidateVisibleUsers();
3599
3600
  memberStore.setState(getInitialState());
3600
3601
  };
3602
+
3603
+ // src/store/services/externalChatJoin.ts
3604
+ var ASSET_RESOURCE = {
3605
+ rig: "rigs",
3606
+ frac_fleet: "frac_fleets",
3607
+ intervention_unit: "intervention_units"
3608
+ };
3609
+ var ownerRequests = /* @__PURE__ */ new Map();
3610
+ async function fetchAssetOwnerCompany(assetId, assetType) {
3611
+ const response = await getChatHost().corvaApi.get(
3612
+ `/v2/${ASSET_RESOURCE[assetType]}/${assetId}`,
3613
+ { fields: [`${assetType}.company`, "company.name"], include: "company" }
3614
+ );
3615
+ const companyId = Number(response?.data?.relationships?.company?.data?.id);
3616
+ if (!Number.isFinite(companyId)) throw new Error("Asset company is missing");
3617
+ const company = response?.included?.find(
3618
+ (item) => item.type === "company" && Number(item.id) === companyId
3619
+ );
3620
+ return { id: companyId, name: company?.attributes?.name ?? null };
3621
+ }
3622
+ function getAssetOwnerCompany(assetId, assetType) {
3623
+ const key = `${assetType}:${assetId}`;
3624
+ const cached = ownerRequests.get(key);
3625
+ if (cached) return cached;
3626
+ const request = fetchAssetOwnerCompany(assetId, assetType);
3627
+ request.catch(() => ownerRequests.delete(key));
3628
+ ownerRequests.set(key, request);
3629
+ return request;
3630
+ }
3631
+ function resetAssetOwnerCompanies() {
3632
+ ownerRequests.clear();
3633
+ }
3634
+
3635
+ // src/store/stores/assetStore.ts
3636
+ var joinApprovedAssets = /* @__PURE__ */ new Set();
3637
+ var assetKey = (assetType, assetId) => `${assetType}:${assetId}`;
3638
+ var isJoinUnderway = (assetType, assetId) => joinApprovedAssets.has(assetKey(assetType, assetId)) || assetStore.getState().currentAssetId === assetId && !!assetStore.getState().assetChatId;
3639
+ async function toJoinRequired(assetId, assetType, session) {
3640
+ const owner = await getAssetOwnerCompany(assetId, assetType).catch(() => null);
3641
+ return {
3642
+ assetId,
3643
+ assetType,
3644
+ companyId: session.companyId ?? owner?.id ?? null,
3645
+ companyName: owner?.name ?? null
3646
+ };
3647
+ }
3648
+ async function fetchJoinedAssetChatId(assetId, assetType) {
3649
+ let session;
3650
+ try {
3651
+ session = await getAssetChatSession(assetId, assetType);
3652
+ } catch (e) {
3653
+ console.error("Failed to fetch asset chat channel:", e);
3654
+ return null;
3655
+ }
3656
+ if (!session.joined) {
3657
+ const joinRequired = await toJoinRequired(assetId, assetType, session);
3658
+ const isCurrent = assetStore.getState().currentAssetId === assetId;
3659
+ if (isCurrent && !isJoinUnderway(assetType, assetId)) assetStore.setState({ joinRequired });
3660
+ return null;
3661
+ }
3662
+ const chatId = session.channelId;
3663
+ registerChannelServer(session);
3664
+ registerAssetChatChannel(chatId, assetId, assetType);
3665
+ assetStore.setState((state) => ({
3666
+ assetChatId: chatId,
3667
+ knownAssetChatIds: new Set(Array.from(state.knownAssetChatIds).concat(chatId))
3668
+ }));
3669
+ return chatId;
3670
+ }
3601
3671
  var registerAssetChatChannel = (channelId, assetId, assetType) => {
3602
3672
  const id = Number(assetId);
3603
3673
  if (!Number.isFinite(id)) return;
@@ -3636,6 +3706,7 @@ var getInitialState2 = () => ({
3636
3706
  currentAssetStatus: null,
3637
3707
  assetChatId: null,
3638
3708
  assetChatError: null,
3709
+ joinRequired: null,
3639
3710
  knownAssetChatIds: /* @__PURE__ */ new Set(),
3640
3711
  panelSyncedAssetId: null,
3641
3712
  isAssetLocked: false,
@@ -3648,7 +3719,9 @@ var assetStore = createStore()((set, get) => ({
3648
3719
  setAssetContext: async (assetId, assetType, assetName, assetStatus, skipAutoSelect) => {
3649
3720
  const currentState = get();
3650
3721
  const isSameAsset = currentState.currentAssetId === assetId;
3651
- if (isSameAsset && (currentState.assetChatId || currentState.assetChatError)) return;
3722
+ if (isSameAsset && (currentState.assetChatId || currentState.assetChatError || currentState.joinRequired)) {
3723
+ return;
3724
+ }
3652
3725
  const isAssetChanging = !isSameAsset;
3653
3726
  uiStore.setState({ isLoading: true });
3654
3727
  set({
@@ -3657,18 +3730,29 @@ var assetStore = createStore()((set, get) => ({
3657
3730
  currentAssetName: assetName || assetId,
3658
3731
  currentAssetStatus: assetStatus ?? null,
3659
3732
  assetChatError: null,
3733
+ joinRequired: null,
3660
3734
  ...isSameAsset ? {} : { assetChatId: null },
3661
3735
  ...isAssetChanging && { isAssetSwitching: true }
3662
3736
  });
3663
3737
  const isStale = () => get().currentAssetId !== assetId;
3664
3738
  try {
3665
- const session = await getAssetChatSession(assetId, assetType);
3739
+ const join = joinApprovedAssets.has(assetKey(assetType, assetId));
3740
+ const session = await getAssetChatSession(assetId, assetType, { join });
3666
3741
  if (isStale()) return;
3742
+ if (!session.joined) {
3743
+ if (join) throw new Error("Could not join this chat");
3744
+ const joinRequired = await toJoinRequired(assetId, assetType, session);
3745
+ if (isStale() || isJoinUnderway(assetType, assetId)) return;
3746
+ set({ joinRequired });
3747
+ uiStore.setState({ isLoading: false });
3748
+ return;
3749
+ }
3667
3750
  const chatId = session.channelId;
3668
3751
  registerChannelServer(session);
3669
3752
  registerAssetChatChannel(chatId, assetId, assetType);
3670
3753
  set({
3671
3754
  assetChatId: chatId,
3755
+ joinRequired: null,
3672
3756
  knownAssetChatIds: new Set(Array.from(currentState.knownAssetChatIds).concat(chatId))
3673
3757
  });
3674
3758
  uiStore.setState({ isLoading: false });
@@ -3698,7 +3782,8 @@ var assetStore = createStore()((set, get) => ({
3698
3782
  assetChatId: null,
3699
3783
  panelSyncedAssetId: null,
3700
3784
  lockedAsset: null,
3701
- assetChatError: null
3785
+ assetChatError: null,
3786
+ joinRequired: null
3702
3787
  });
3703
3788
  if (currentUser && previousAssetChatId && roomStore.getState().currentRoom?._id === previousAssetChatId) {
3704
3789
  const generalChat = findGeneralRoom(roomStore.getState().subscriptions);
@@ -3707,30 +3792,35 @@ var assetStore = createStore()((set, get) => ({
3707
3792
  }
3708
3793
  }
3709
3794
  },
3795
+ joinAssetChat: async () => {
3796
+ const { joinRequired } = get();
3797
+ if (!joinRequired) return;
3798
+ const approvalKey = assetKey(joinRequired.assetType, joinRequired.assetId);
3799
+ joinApprovedAssets.add(approvalKey);
3800
+ set({ joinRequired: null });
3801
+ const { currentAssetName, currentAssetStatus } = get();
3802
+ try {
3803
+ await get().setAssetContext(
3804
+ joinRequired.assetId,
3805
+ joinRequired.assetType,
3806
+ currentAssetName ?? void 0,
3807
+ currentAssetStatus ?? void 0
3808
+ );
3809
+ } finally {
3810
+ joinApprovedAssets.delete(approvalKey);
3811
+ }
3812
+ },
3710
3813
  ensureAssetChatSubscription: async () => {
3711
- const { currentAssetId, currentAssetType } = get();
3814
+ const { currentAssetId, currentAssetType, joinRequired: pendingJoin } = get();
3712
3815
  if (!currentAssetId || !currentAssetType) return null;
3713
3816
  if (!isChatAssetTypeAllowed(currentAssetType)) return null;
3817
+ if (pendingJoin?.assetId === currentAssetId) return null;
3714
3818
  const cached = inFlightByAsset.get(currentAssetId);
3715
3819
  if (cached) return cached;
3716
3820
  const promise = (async () => {
3717
3821
  try {
3718
- let chatId = get().assetChatId;
3719
- if (!chatId) {
3720
- try {
3721
- const session = await getAssetChatSession(currentAssetId, currentAssetType);
3722
- chatId = session.channelId;
3723
- registerChannelServer(session);
3724
- registerAssetChatChannel(chatId, currentAssetId, currentAssetType);
3725
- set({
3726
- assetChatId: chatId,
3727
- knownAssetChatIds: new Set(Array.from(get().knownAssetChatIds).concat(chatId))
3728
- });
3729
- } catch (e) {
3730
- console.error("Failed to fetch asset chat channel:", e);
3731
- return null;
3732
- }
3733
- }
3822
+ const chatId = get().assetChatId ?? await fetchJoinedAssetChatId(currentAssetId, currentAssetType);
3823
+ if (!chatId) return null;
3734
3824
  const existing = roomStore.getState().subscriptions.find((s) => s.rid === chatId);
3735
3825
  if (existing) return existing;
3736
3826
  const { api } = sharedRefs;
@@ -4685,6 +4775,7 @@ var authStore = createStore()((set, get) => ({
4685
4775
  getChatHost().notifier?.onLogout?.();
4686
4776
  resetRoomStore();
4687
4777
  resetAssetStore();
4778
+ resetAssetOwnerCompanies();
4688
4779
  resetMessageStore();
4689
4780
  resetChatAssetPermissionsSnapshot();
4690
4781
  resetUIStore();