diff --git a/lib/utils/entity-text.js b/lib/utils/entity-text.js --- a/lib/utils/entity-text.js +++ b/lib/utils/entity-text.js @@ -5,7 +5,12 @@ import { threadNoun } from '../shared/thread-utils'; import { stringForUser } from '../shared/user-utils'; -import { threadTypes, type ThreadType } from '../types/thread-types'; +import { + threadTypes, + type ThreadType, + type RawThreadInfo, + type ThreadInfo, +} from '../types/thread-types'; type UserEntity = { +type: 'user', @@ -47,10 +52,10 @@ // ET is a JS tag function used in template literals, eg. ET`something` // It allows you to compose raw text and "entities" together -function ET( +const entityTextFunction = ( strings: $ReadOnlyArray, ...entities: $ReadOnlyArray -): EntityText { +) => { const result = []; for (let i = 0; i < strings.length; i++) { const str = strings[i]; @@ -68,7 +73,112 @@ } } return result; -} +}; + +// defaults to shortName +type EntityTextThreadInput = + | { + +display: 'uiName', + +threadInfo: ThreadInfo, + } + | { + +display?: 'shortName', + +threadInfo: ThreadInfo | RawThreadInfo, + +possessive?: ?boolean, + } + | { + +display: 'alwaysDisplayShortName', + +threadInfo: ThreadInfo | RawThreadInfo, + +possessive?: ?boolean, + } + | { + +display: 'alwaysDisplayShortName', + +threadID: string, + +possessive?: ?boolean, + }; +entityTextFunction.thread = (input: EntityTextThreadInput) => { + if (input.display === 'uiName') { + const { threadInfo } = input; + return { + type: 'thread', + id: threadInfo.id, + name: threadInfo.name, + display: 'uiName', + uiName: threadInfo.uiName, + }; + } + if (input.display === 'alwaysDisplayShortName' && input.threadID) { + const { threadID, possessive } = input; + return { + type: 'thread', + id: threadID, + name: undefined, + display: 'shortName', + threadType: undefined, + alwaysDisplayShortName: true, + possessive, + }; + } else if (input.display === 'alwaysDisplayShortName' && input.threadInfo) { + const { threadInfo, possessive } = input; + return { + type: 'thread', + id: threadInfo.id, + name: threadInfo.name, + display: 'shortName', + threadType: threadInfo.type, + alwaysDisplayShortName: true, + possessive, + }; + } else if (input.display === 'shortName' || !input.display) { + const { threadInfo, possessive } = input; + return { + type: 'thread', + id: threadInfo.id, + name: threadInfo.name, + display: 'shortName', + threadType: threadInfo.type, + possessive, + }; + } + invariant( + false, + `ET.thread passed unexpected display type: ${input.display}`, + ); +}; + +type EntityTextUserInput = { + +userInfo: { + +id: string, + +username?: ?string, + +isViewer?: ?boolean, + ... + }, + +possessive?: ?boolean, +}; +entityTextFunction.user = (input: EntityTextUserInput) => ({ + type: 'user', + id: input.userInfo.id, + username: input.userInfo.username, + isViewer: input.userInfo.isViewer, + possessive: input.possessive, +}); + +type EntityTextColorInput = { +hex: string }; +entityTextFunction.color = (input: EntityTextColorInput) => ({ + type: 'color', + hex: input.hex, +}); + +type EntityTextFunction = (( + strings: $ReadOnlyArray, + ...entities: $ReadOnlyArray +) => EntityText) & { + +thread: EntityTextThreadInput => ThreadEntity, + +user: EntityTextUserInput => UserEntity, + +color: EntityTextColorInput => ColorEntity, + ... +}; +const ET: EntityTextFunction = entityTextFunction; type MakePossessiveInput = { +str: string, +isViewer?: ?boolean }; function makePossessive(input: MakePossessiveInput) { @@ -84,10 +194,11 @@ if (entity.display === 'uiName') { name = userGeneratedName ? userGeneratedName : entity.uiName; } else if (entity.display === 'shortName') { + const threadType = entity.threadType ?? threadTypes.PERSONAL; name = userGeneratedName && !entity.alwaysDisplayShortName ? userGeneratedName - : threadNoun(entity.threadType ?? threadTypes.PERSONAL); + : `this ${threadNoun(threadType)}`; if (entity.possessive) { name = makePossessive({ str: name }); }