diff --git a/lib/permissions/minimally-encoded-thread-permissions-validators.js b/lib/permissions/minimally-encoded-thread-permissions-validators.js index 6239798bd..4fe35d250 100644 --- a/lib/permissions/minimally-encoded-thread-permissions-validators.js +++ b/lib/permissions/minimally-encoded-thread-permissions-validators.js @@ -1,95 +1,110 @@ // @flow import t, { type TInterface, type TUnion } from 'tcomb'; import { tHexEncodedPermissionsBitmask, tHexEncodedRolePermission, } from './minimally-encoded-thread-permissions.js'; +import { clientAvatarValidator } from '../types/avatar-types.js'; import type { MinimallyEncodedMemberInfo, RawThreadInfo, MinimallyEncodedRelativeMemberInfo, ResolvedThreadInfo, MinimallyEncodedRoleInfo, MinimallyEncodedThreadCurrentUserInfo, ThreadInfo, } from '../types/minimally-encoded-thread-permissions-types.js'; +import { threadTypeValidator } from '../types/thread-types-enum.js'; import { legacyMemberInfoValidator, legacyRawThreadInfoValidator, legacyRoleInfoValidator, threadCurrentUserInfoValidator, - legacyThreadInfoValidator, } from '../types/thread-types.js'; import type { LegacyRawThreadInfo } from '../types/thread-types.js'; +import { threadEntityValidator } from '../utils/entity-text.js'; import { tBool, tID, tShape } from '../utils/validation-utils.js'; const minimallyEncodedRoleInfoValidator: TInterface = tShape({ ...legacyRoleInfoValidator.meta.props, minimallyEncoded: tBool(true), permissions: t.list(tHexEncodedRolePermission), }); const minimallyEncodedThreadCurrentUserInfoValidator: TInterface = tShape({ ...threadCurrentUserInfoValidator.meta.props, minimallyEncoded: tBool(true), permissions: tHexEncodedPermissionsBitmask, }); const minimallyEncodedMemberInfoValidator: TInterface = tShape({ ...legacyMemberInfoValidator.meta.props, minimallyEncoded: tBool(true), permissions: tHexEncodedPermissionsBitmask, }); const minimallyEncodedRelativeMemberInfoValidator: TInterface = tShape({ ...minimallyEncodedMemberInfoValidator.meta.props, username: t.maybe(t.String), isViewer: t.Boolean, }); const minimallyEncodedThreadInfoValidator: TInterface = tShape({ - ...legacyThreadInfoValidator.meta.props, minimallyEncoded: tBool(true), + id: tID, + type: threadTypeValidator, + name: t.maybe(t.String), + uiName: t.union([t.String, threadEntityValidator]), + avatar: t.maybe(clientAvatarValidator), + description: t.maybe(t.String), + color: t.String, + creationTime: t.Number, + parentThreadID: t.maybe(tID), + containingThreadID: t.maybe(tID), + community: t.maybe(tID), members: t.list(minimallyEncodedRelativeMemberInfoValidator), roles: t.dict(tID, minimallyEncodedRoleInfoValidator), currentUser: minimallyEncodedThreadCurrentUserInfoValidator, + sourceMessageID: t.maybe(tID), + repliesCount: t.Number, + pinnedCount: t.maybe(t.Number), }); const resolvedThreadInfoValidator: TInterface = tShape({ ...minimallyEncodedThreadInfoValidator.meta.props, uiName: t.String, }); const minimallyEncodedRawThreadInfoValidator: TInterface = tShape({ ...legacyRawThreadInfoValidator.meta.props, minimallyEncoded: tBool(true), members: t.list(minimallyEncodedMemberInfoValidator), roles: t.dict(tID, minimallyEncodedRoleInfoValidator), currentUser: minimallyEncodedThreadCurrentUserInfoValidator, }); export const rawThreadInfoValidator: TUnion< LegacyRawThreadInfo | RawThreadInfo, > = t.union([ legacyRawThreadInfoValidator, minimallyEncodedRawThreadInfoValidator, ]); export { minimallyEncodedRoleInfoValidator, minimallyEncodedThreadCurrentUserInfoValidator, minimallyEncodedMemberInfoValidator, minimallyEncodedRelativeMemberInfoValidator, minimallyEncodedThreadInfoValidator, resolvedThreadInfoValidator, minimallyEncodedRawThreadInfoValidator, }; diff --git a/lib/types/minimally-encoded-thread-permissions-types.js b/lib/types/minimally-encoded-thread-permissions-types.js index b9dbe8a5a..ebc68e0c4 100644 --- a/lib/types/minimally-encoded-thread-permissions-types.js +++ b/lib/types/minimally-encoded-thread-permissions-types.js @@ -1,211 +1,226 @@ // @flow import invariant from 'invariant'; import _mapValues from 'lodash/fp/mapValues.js'; +import type { ClientAvatar } from './avatar-types.js'; +import type { ThreadType } from './thread-types-enum.js'; import type { LegacyMemberInfo, LegacyRawThreadInfo, LegacyRelativeMemberInfo, LegacyRoleInfo, - LegacyThreadInfo, ThreadCurrentUserInfo, } from './thread-types.js'; import { decodeThreadRolePermissionsBitmaskArray, permissionsToBitmaskHex, threadPermissionsFromBitmaskHex, threadRolePermissionsBlobToBitmaskArray, } from '../permissions/minimally-encoded-thread-permissions.js'; +import type { ThreadEntity } from '../utils/entity-text.js'; export type MinimallyEncodedRoleInfo = $ReadOnly<{ ...LegacyRoleInfo, +minimallyEncoded: true, +permissions: $ReadOnlyArray, }>; const minimallyEncodeRoleInfo = ( roleInfo: LegacyRoleInfo, ): MinimallyEncodedRoleInfo => { invariant( !('minimallyEncoded' in roleInfo), 'roleInfo is already minimally encoded.', ); return { ...roleInfo, minimallyEncoded: true, permissions: threadRolePermissionsBlobToBitmaskArray(roleInfo.permissions), }; }; const decodeMinimallyEncodedRoleInfo = ( minimallyEncodedRoleInfo: MinimallyEncodedRoleInfo, ): LegacyRoleInfo => { const { minimallyEncoded, ...rest } = minimallyEncodedRoleInfo; return { ...rest, permissions: decodeThreadRolePermissionsBitmaskArray( minimallyEncodedRoleInfo.permissions, ), }; }; export type MinimallyEncodedThreadCurrentUserInfo = $ReadOnly<{ ...ThreadCurrentUserInfo, +minimallyEncoded: true, +permissions: string, }>; const minimallyEncodeThreadCurrentUserInfo = ( threadCurrentUserInfo: ThreadCurrentUserInfo, ): MinimallyEncodedThreadCurrentUserInfo => { invariant( !('minimallyEncoded' in threadCurrentUserInfo), 'threadCurrentUserInfo is already minimally encoded.', ); return { ...threadCurrentUserInfo, minimallyEncoded: true, permissions: permissionsToBitmaskHex(threadCurrentUserInfo.permissions), }; }; const decodeMinimallyEncodedThreadCurrentUserInfo = ( minimallyEncodedThreadCurrentUserInfo: MinimallyEncodedThreadCurrentUserInfo, ): ThreadCurrentUserInfo => { const { minimallyEncoded, ...rest } = minimallyEncodedThreadCurrentUserInfo; return { ...rest, permissions: threadPermissionsFromBitmaskHex( minimallyEncodedThreadCurrentUserInfo.permissions, ), }; }; export type MinimallyEncodedMemberInfo = $ReadOnly<{ ...LegacyMemberInfo, +minimallyEncoded: true, +permissions: string, }>; const minimallyEncodeMemberInfo = ( memberInfo: LegacyMemberInfo, ): MinimallyEncodedMemberInfo => { invariant( !('minimallyEncoded' in memberInfo), 'memberInfo is already minimally encoded.', ); return { ...memberInfo, minimallyEncoded: true, permissions: permissionsToBitmaskHex(memberInfo.permissions), }; }; const decodeMinimallyEncodedMemberInfo = ( minimallyEncodedMemberInfo: MinimallyEncodedMemberInfo, ): LegacyMemberInfo => { const { minimallyEncoded, ...rest } = minimallyEncodedMemberInfo; return { ...rest, permissions: threadPermissionsFromBitmaskHex( minimallyEncodedMemberInfo.permissions, ), }; }; export type MinimallyEncodedRelativeMemberInfo = $ReadOnly<{ ...MinimallyEncodedMemberInfo, +username: ?string, +isViewer: boolean, }>; const minimallyEncodeRelativeMemberInfo = ( relativeMemberInfo: LegacyRelativeMemberInfo, ): MinimallyEncodedRelativeMemberInfo => { invariant( !('minimallyEncoded' in relativeMemberInfo), 'relativeMemberInfo is already minimally encoded.', ); return { ...relativeMemberInfo, minimallyEncoded: true, permissions: permissionsToBitmaskHex(relativeMemberInfo.permissions), }; }; const decodeMinimallyEncodedRelativeMemberInfo = ( minimallyEncodedRelativeMemberInfo: MinimallyEncodedRelativeMemberInfo, ): LegacyRelativeMemberInfo => { const { minimallyEncoded, ...rest } = minimallyEncodedRelativeMemberInfo; return { ...rest, permissions: threadPermissionsFromBitmaskHex( minimallyEncodedRelativeMemberInfo.permissions, ), }; }; export type RawThreadInfo = $ReadOnly<{ ...LegacyRawThreadInfo, +minimallyEncoded: true, +members: $ReadOnlyArray, +roles: { +[id: string]: MinimallyEncodedRoleInfo }, +currentUser: MinimallyEncodedThreadCurrentUserInfo, }>; const minimallyEncodeRawThreadInfo = ( rawThreadInfo: LegacyRawThreadInfo, ): RawThreadInfo => { invariant( !('minimallyEncoded' in rawThreadInfo), 'rawThreadInfo is already minimally encoded.', ); const { members, roles, currentUser, ...rest } = rawThreadInfo; return { ...rest, minimallyEncoded: true, members: members.map(minimallyEncodeMemberInfo), roles: _mapValues(minimallyEncodeRoleInfo)(roles), currentUser: minimallyEncodeThreadCurrentUserInfo(currentUser), }; }; const decodeMinimallyEncodedRawThreadInfo = ( minimallyEncodedRawThreadInfo: RawThreadInfo, ): LegacyRawThreadInfo => { const { minimallyEncoded, members, roles, currentUser, ...rest } = minimallyEncodedRawThreadInfo; return { ...rest, members: members.map(decodeMinimallyEncodedMemberInfo), roles: _mapValues(decodeMinimallyEncodedRoleInfo)(roles), currentUser: decodeMinimallyEncodedThreadCurrentUserInfo(currentUser), }; }; export type ThreadInfo = $ReadOnly<{ - ...LegacyThreadInfo, +minimallyEncoded: true, + +id: string, + +type: ThreadType, + +name: ?string, + +uiName: string | ThreadEntity, + +avatar?: ?ClientAvatar, + +description: ?string, + +color: string, // hex, without "#" or "0x" + +creationTime: number, // millisecond timestamp + +parentThreadID: ?string, + +containingThreadID: ?string, + +community: ?string, +members: $ReadOnlyArray, +roles: { +[id: string]: MinimallyEncodedRoleInfo }, +currentUser: MinimallyEncodedThreadCurrentUserInfo, + +sourceMessageID?: string, + +repliesCount: number, + +pinnedCount?: number, }>; export type ResolvedThreadInfo = $ReadOnly<{ ...ThreadInfo, +uiName: string, }>; export { minimallyEncodeRoleInfo, decodeMinimallyEncodedRoleInfo, minimallyEncodeThreadCurrentUserInfo, decodeMinimallyEncodedThreadCurrentUserInfo, minimallyEncodeMemberInfo, decodeMinimallyEncodedMemberInfo, minimallyEncodeRawThreadInfo, decodeMinimallyEncodedRawThreadInfo, minimallyEncodeRelativeMemberInfo, decodeMinimallyEncodedRelativeMemberInfo, }; diff --git a/lib/types/thread-types.js b/lib/types/thread-types.js index a37fe4fbe..668bdaf3d 100644 --- a/lib/types/thread-types.js +++ b/lib/types/thread-types.js @@ -1,483 +1,435 @@ // @flow import t, { type TInterface } from 'tcomb'; import { type AvatarDBContent, type ClientAvatar, clientAvatarValidator, type UpdateUserAvatarRequest, } from './avatar-types.js'; import type { CalendarQuery } from './entry-types.js'; import type { Media } from './media-types.js'; import type { MessageTruncationStatuses, RawMessageInfo, } from './message-types.js'; import type { MinimallyEncodedMemberInfo, RawThreadInfo, MinimallyEncodedRelativeMemberInfo, ResolvedThreadInfo, MinimallyEncodedRoleInfo, ThreadInfo, } from './minimally-encoded-thread-permissions-types.js'; import { type ThreadSubscription, threadSubscriptionValidator, } from './subscription-types.js'; import { type ThreadPermissionsInfo, threadPermissionsInfoValidator, type ThreadRolePermissionsBlob, threadRolePermissionsBlobValidator, type UserSurfacedPermission, } from './thread-permission-types.js'; import { type ThreadType, threadTypeValidator } from './thread-types-enum.js'; import type { ClientUpdateInfo, ServerUpdateInfo } from './update-types.js'; import type { UserInfo, UserInfos } from './user-types.js'; -import { - type ThreadEntity, - threadEntityValidator, -} from '../utils/entity-text.js'; +import { type ThreadEntity } from '../utils/entity-text.js'; import { tID, tShape } from '../utils/validation-utils.js'; export type LegacyMemberInfo = { +id: string, +role: ?string, +permissions: ThreadPermissionsInfo, +isSender: boolean, }; export const legacyMemberInfoValidator: TInterface = tShape({ id: t.String, role: t.maybe(tID), permissions: threadPermissionsInfoValidator, isSender: t.Boolean, }); export type MemberInfo = LegacyMemberInfo | MinimallyEncodedMemberInfo; export type LegacyRelativeMemberInfo = $ReadOnly<{ ...LegacyMemberInfo, +username: ?string, +isViewer: boolean, }>; -const legacyRelativeMemberInfoValidator = tShape({ - ...legacyMemberInfoValidator.meta.props, - username: t.maybe(t.String), - isViewer: t.Boolean, -}); export type RelativeMemberInfo = | LegacyRelativeMemberInfo | MinimallyEncodedRelativeMemberInfo; export type LegacyRoleInfo = { +id: string, +name: string, +permissions: ThreadRolePermissionsBlob, +isDefault: boolean, }; export const legacyRoleInfoValidator: TInterface = tShape({ id: tID, name: t.String, permissions: threadRolePermissionsBlobValidator, isDefault: t.Boolean, }); export type RoleInfo = LegacyRoleInfo | MinimallyEncodedRoleInfo; export type ThreadCurrentUserInfo = { +role: ?string, +permissions: ThreadPermissionsInfo, +subscription: ThreadSubscription, +unread: ?boolean, }; export const threadCurrentUserInfoValidator: TInterface = tShape({ role: t.maybe(tID), permissions: threadPermissionsInfoValidator, subscription: threadSubscriptionValidator, unread: t.maybe(t.Boolean), }); export type LegacyRawThreadInfo = { +id: string, +type: ThreadType, +name: ?string, +avatar?: ?ClientAvatar, +description: ?string, +color: string, // hex, without "#" or "0x" +creationTime: number, // millisecond timestamp +parentThreadID: ?string, +containingThreadID: ?string, +community: ?string, +members: $ReadOnlyArray, +roles: { +[id: string]: LegacyRoleInfo }, +currentUser: ThreadCurrentUserInfo, +sourceMessageID?: string, +repliesCount: number, +pinnedCount?: number, }; export type LegacyRawThreadInfos = { +[id: string]: LegacyRawThreadInfo, }; export const legacyRawThreadInfoValidator: TInterface = tShape({ id: tID, type: threadTypeValidator, name: t.maybe(t.String), avatar: t.maybe(clientAvatarValidator), description: t.maybe(t.String), color: t.String, creationTime: t.Number, parentThreadID: t.maybe(tID), containingThreadID: t.maybe(tID), community: t.maybe(tID), members: t.list(legacyMemberInfoValidator), roles: t.dict(tID, legacyRoleInfoValidator), currentUser: threadCurrentUserInfoValidator, sourceMessageID: t.maybe(tID), repliesCount: t.Number, pinnedCount: t.maybe(t.Number), }); export type MixedRawThreadInfos = { +[id: string]: LegacyRawThreadInfo | RawThreadInfo, }; export type RawThreadInfos = { +[id: string]: RawThreadInfo, }; -export type LegacyThreadInfo = { - +id: string, - +type: ThreadType, - +name: ?string, - +uiName: string | ThreadEntity, - +avatar?: ?ClientAvatar, - +description: ?string, - +color: string, // hex, without "#" or "0x" - +creationTime: number, // millisecond timestamp - +parentThreadID: ?string, - +containingThreadID: ?string, - +community: ?string, - +members: $ReadOnlyArray, - +roles: { +[id: string]: LegacyRoleInfo }, - +currentUser: ThreadCurrentUserInfo, - +sourceMessageID?: string, - +repliesCount: number, - +pinnedCount?: number, -}; -export const legacyThreadInfoValidator: TInterface = - tShape({ - id: tID, - type: threadTypeValidator, - name: t.maybe(t.String), - uiName: t.union([t.String, threadEntityValidator]), - avatar: t.maybe(clientAvatarValidator), - description: t.maybe(t.String), - color: t.String, - creationTime: t.Number, - parentThreadID: t.maybe(tID), - containingThreadID: t.maybe(tID), - community: t.maybe(tID), - members: t.list(legacyRelativeMemberInfoValidator), - roles: t.dict(tID, legacyRoleInfoValidator), - currentUser: threadCurrentUserInfoValidator, - sourceMessageID: t.maybe(tID), - repliesCount: t.Number, - pinnedCount: t.maybe(t.Number), - }); - export type ServerMemberInfo = { +id: string, +role: ?string, +permissions: ThreadPermissionsInfo, +subscription: ThreadSubscription, +unread: ?boolean, +isSender: boolean, }; export type ServerThreadInfo = { +id: string, +type: ThreadType, +name: ?string, +avatar?: AvatarDBContent, +description: ?string, +color: string, // hex, without "#" or "0x" +creationTime: number, // millisecond timestamp +parentThreadID: ?string, +containingThreadID: ?string, +community: ?string, +depth: number, +members: $ReadOnlyArray, +roles: { +[id: string]: LegacyRoleInfo }, +sourceMessageID?: string, +repliesCount: number, +pinnedCount: number, }; export type LegacyThreadStore = { +threadInfos: MixedRawThreadInfos, }; export type ThreadStore = { +threadInfos: RawThreadInfos, }; export type ClientDBThreadInfo = { +id: string, +type: number, +name: ?string, +avatar?: ?string, +description: ?string, +color: string, +creationTime: string, +parentThreadID: ?string, +containingThreadID: ?string, +community: ?string, +members: string, +roles: string, +currentUser: string, +sourceMessageID?: string, +repliesCount: number, +pinnedCount?: number, }; export type ThreadDeletionRequest = { +threadID: string, +accountPassword?: empty, }; export type RemoveMembersRequest = { +threadID: string, +memberIDs: $ReadOnlyArray, }; export type RoleChangeRequest = { +threadID: string, +memberIDs: $ReadOnlyArray, +role: string, }; export type ChangeThreadSettingsResult = { +updatesResult: { +newUpdates: $ReadOnlyArray, }, +newMessageInfos: $ReadOnlyArray, }; export type ChangeThreadSettingsPayload = { +threadID: string, +updatesResult: { +newUpdates: $ReadOnlyArray, }, +newMessageInfos: $ReadOnlyArray, }; export type LeaveThreadRequest = { +threadID: string, }; export type LeaveThreadResult = { +updatesResult: { +newUpdates: $ReadOnlyArray, }, }; export type LeaveThreadPayload = { +updatesResult: { +newUpdates: $ReadOnlyArray, }, }; export type ThreadChanges = Partial<{ +type: ThreadType, +name: string, +description: string, +color: string, +parentThreadID: ?string, +newMemberIDs: $ReadOnlyArray, +avatar: UpdateUserAvatarRequest, }>; export type UpdateThreadRequest = { +threadID: string, +changes: ThreadChanges, +accountPassword?: empty, }; export type BaseNewThreadRequest = { +id?: ?string, +name?: ?string, +description?: ?string, +color?: ?string, +parentThreadID?: ?string, +initialMemberIDs?: ?$ReadOnlyArray, +ghostMemberIDs?: ?$ReadOnlyArray, }; type NewThreadRequest = | { +type: 3 | 4 | 6 | 7 | 8 | 9 | 10 | 11 | 12, ...BaseNewThreadRequest, } | { +type: 5, +sourceMessageID: string, ...BaseNewThreadRequest, }; export type ClientNewThreadRequest = { ...NewThreadRequest, +calendarQuery: CalendarQuery, }; export type ServerNewThreadRequest = { ...NewThreadRequest, +calendarQuery?: ?CalendarQuery, }; export type NewThreadResponse = { +updatesResult: { +newUpdates: $ReadOnlyArray, }, +newMessageInfos: $ReadOnlyArray, +userInfos: UserInfos, +newThreadID: string, }; export type NewThreadResult = { +updatesResult: { +newUpdates: $ReadOnlyArray, }, +newMessageInfos: $ReadOnlyArray, +userInfos: UserInfos, +newThreadID: string, }; export type ServerThreadJoinRequest = { +threadID: string, +calendarQuery?: ?CalendarQuery, +inviteLinkSecret?: string, }; export type ClientThreadJoinRequest = { +threadID: string, +calendarQuery: CalendarQuery, +inviteLinkSecret?: string, }; export type ThreadJoinResult = { +updatesResult: { +newUpdates: $ReadOnlyArray, }, +rawMessageInfos: $ReadOnlyArray, +truncationStatuses: MessageTruncationStatuses, +userInfos: UserInfos, }; export type ThreadJoinPayload = { +updatesResult: { newUpdates: $ReadOnlyArray, }, +rawMessageInfos: $ReadOnlyArray, +truncationStatuses: MessageTruncationStatuses, +userInfos: $ReadOnlyArray, }; export type ThreadFetchMediaResult = { +media: $ReadOnlyArray, }; export type ThreadFetchMediaRequest = { +threadID: string, +limit: number, +offset: number, }; export type SidebarInfo = { +threadInfo: ThreadInfo, +lastUpdatedTime: number, +mostRecentNonLocalMessage: ?string, }; export type ToggleMessagePinRequest = { +messageID: string, +action: 'pin' | 'unpin', }; export type ToggleMessagePinResult = { +newMessageInfos: $ReadOnlyArray, +threadID: string, }; type CreateRoleAction = { +community: string, +name: string, +permissions: $ReadOnlyArray, +action: 'create_role', }; type EditRoleAction = { +community: string, +existingRoleID: string, +name: string, +permissions: $ReadOnlyArray, +action: 'edit_role', }; export type RoleModificationRequest = CreateRoleAction | EditRoleAction; export type RoleModificationResult = { +threadInfo: LegacyRawThreadInfo | RawThreadInfo, +updatesResult: { +newUpdates: $ReadOnlyArray, }, }; export type RoleModificationPayload = { +threadInfo: LegacyRawThreadInfo | RawThreadInfo, +updatesResult: { +newUpdates: $ReadOnlyArray, }, }; export type RoleDeletionRequest = { +community: string, +roleID: string, }; export type RoleDeletionResult = { +threadInfo: LegacyRawThreadInfo | RawThreadInfo, +updatesResult: { +newUpdates: $ReadOnlyArray, }, }; export type RoleDeletionPayload = { +threadInfo: LegacyRawThreadInfo | RawThreadInfo, +updatesResult: { +newUpdates: $ReadOnlyArray, }, }; // We can show a max of 3 sidebars inline underneath their parent in the chat // tab. If there are more, we show a button that opens a modal to see the rest export const maxReadSidebars = 3; // We can show a max of 5 sidebars inline underneath their parent // in the chat tab if every one of the displayed sidebars is unread export const maxUnreadSidebars = 5; export type ThreadStoreThreadInfos = LegacyRawThreadInfos; export type ChatMentionCandidate = { +threadInfo: ResolvedThreadInfo, +rawChatName: string | ThreadEntity, }; export type ChatMentionCandidates = { +[id: string]: ChatMentionCandidate, }; export type ChatMentionCandidatesObj = { +[id: string]: ChatMentionCandidates, }; export type UserProfileThreadInfo = { +threadInfo: ThreadInfo, +pendingPersonalThreadUserInfo?: UserInfo, }; diff --git a/web/types/nav-types.js b/web/types/nav-types.js index 2dc8e19ea..4de574584 100644 --- a/web/types/nav-types.js +++ b/web/types/nav-types.js @@ -1,60 +1,60 @@ // @flow import type { TInterface } from 'tcomb'; import t from 'tcomb'; +import { minimallyEncodedThreadInfoValidator } from 'lib/permissions/minimally-encoded-thread-permissions-validators.js'; import type { ThreadInfo } from 'lib/types/minimally-encoded-thread-permissions-types.js'; import { type BaseNavInfo } from 'lib/types/nav-types.js'; -import { legacyThreadInfoValidator } from 'lib/types/thread-types.js'; import { type AccountUserInfo, accountUserInfoValidator, } from 'lib/types/user-types.js'; import { tID, tShape } from 'lib/utils/validation-utils.js'; export type NavigationTab = 'calendar' | 'chat' | 'settings'; const navigationTabValidator = t.enums.of(['calendar', 'chat', 'settings']); export type LoginMethod = 'form' | 'qr-code'; const loginMethodValidator = t.enums.of(['form', 'qr-code']); export type NavigationSettingsSection = | 'account' | 'friend-list' | 'block-list' | 'keyservers' | 'danger-zone'; const navigationSettingsSectionValidator = t.enums.of([ 'account', 'friend-list', 'block-list', 'keyservers', 'danger-zone', ]); export type NavigationChatMode = 'view' | 'create'; const navigationChatModeValidator = t.enums.of(['view', 'create']); export type NavInfo = { ...$Exact, +tab: NavigationTab, +activeChatThreadID: ?string, +pendingThread?: ThreadInfo, +settingsSection?: NavigationSettingsSection, +selectedUserList?: $ReadOnlyArray, +chatMode?: NavigationChatMode, +inviteSecret?: ?string, +loginMethod?: LoginMethod, }; export const navInfoValidator: TInterface = tShape<$Exact>({ startDate: t.String, endDate: t.String, tab: navigationTabValidator, activeChatThreadID: t.maybe(tID), - pendingThread: t.maybe(legacyThreadInfoValidator), + pendingThread: t.maybe(minimallyEncodedThreadInfoValidator), settingsSection: t.maybe(navigationSettingsSectionValidator), selectedUserList: t.maybe(t.list(accountUserInfoValidator)), chatMode: t.maybe(navigationChatModeValidator), inviteSecret: t.maybe(t.String), loginMethod: t.maybe(loginMethodValidator), });