diff --git a/lib/shared/notif-utils.js b/lib/shared/notif-utils.js --- a/lib/shared/notif-utils.js +++ b/lib/shared/notif-utils.js @@ -2,6 +2,9 @@ import invariant from 'invariant'; +import { robotextForMessageInfo } from './message-utils'; +import { messageSpecs } from './messages/message-specs'; +import { threadNoun } from './thread-utils'; import { type MessageInfo, type RawMessageInfo, @@ -17,15 +20,11 @@ import { ET, getEntityTextAsString, - pluralizeEntityText, type EntityText, - type UserEntity, + type ThreadEntity, } from '../utils/entity-text'; import { promiseAll } from '../utils/promises'; import { trimText } from '../utils/text-utils'; -import { robotextForMessageInfo } from './message-utils'; -import { messageSpecs } from './messages/message-specs'; -import { threadNoun } from './thread-utils'; async function notifTextsForMessageInfo( messageInfos: MessageInfo[], @@ -98,7 +97,7 @@ +threadType: ThreadType, +parentThreadInfo: ThreadInfo, +childThreadName: ?string, - +childThreadUIName: string | $ReadOnlyArray, + +childThreadUIName: string | ThreadEntity, }; function notifTextsForSubthreadCreation( input: NotifTextsForSubthreadCreationInput, @@ -181,15 +180,10 @@ ); return notifString; }; - const unresolvedTitle = unresolvedNotifTexts.title; - const pluralizedTitle = - typeof unresolvedTitle === 'string' - ? unresolvedTitle - : pluralizeEntityText(unresolvedTitle.map(entity => [entity])); let promises = { merged: resolveToString(unresolvedNotifTexts.merged), body: resolveToString(unresolvedNotifTexts.body), - title: resolveToString(pluralizedTitle), + title: resolveToString(ET`${unresolvedNotifTexts.title}`), }; if (unresolvedNotifTexts.prefix) { promises = { diff --git a/lib/shared/thread-utils.js b/lib/shared/thread-utils.js --- a/lib/shared/thread-utils.js +++ b/lib/shared/thread-utils.js @@ -6,6 +6,10 @@ import stringHash from 'string-hash'; import tinycolor from 'tinycolor2'; +import { type ParserRules } from './markdown'; +import { getMessageTitle } from './message-utils'; +import { relationshipBlockedInEitherDirection } from './relationship-utils'; +import threadWatcher from './thread-watcher'; import { fetchMostRecentMessagesActionTypes, fetchMostRecentMessages, @@ -76,16 +80,12 @@ ET, entityTextToRawString, getEntityTextAsString, - type UserEntity, + type ThreadEntity, } from '../utils/entity-text'; import { values } from '../utils/objects'; import { useSelector } from '../utils/redux-utils'; import { firstLine } from '../utils/string-utils'; import { trimText } from '../utils/text-utils'; -import { type ParserRules } from './markdown'; -import { getMessageTitle } from './message-utils'; -import { relationshipBlockedInEitherDirection } from './relationship-utils'; -import threadWatcher from './thread-watcher'; function colorIsDark(color: string): boolean { return tinycolor(`#${color}`).isDark(); @@ -774,16 +774,23 @@ return newPermissions; } -function threadUIName( - threadInfo: ThreadInfo, -): string | $ReadOnlyArray { +function threadUIName(threadInfo: ThreadInfo): string | ThreadEntity { if (threadInfo.name) { return firstLine(threadInfo.name); } const threadMembers = threadInfo.members.filter( memberInfo => memberInfo.role, ); - return threadMembers.map(member => ET.user({ userInfo: member })); + const memberEntities = threadMembers.map(member => + ET.user({ userInfo: member }), + ); + return { + type: 'thread', + id: threadInfo.id, + name: threadInfo.name, + display: 'uiName', + uiName: memberEntities, + }; } function threadInfoFromRawThreadInfo( diff --git a/lib/types/notif-types.js b/lib/types/notif-types.js --- a/lib/types/notif-types.js +++ b/lib/types/notif-types.js @@ -1,11 +1,11 @@ // @flow -import type { EntityText, UserEntity } from '../utils/entity-text'; +import type { EntityText, ThreadEntity } from '../utils/entity-text'; export type NotifTexts = { +merged: string | EntityText, +body: string | EntityText, - +title: string | $ReadOnlyArray, + +title: string | ThreadEntity, +prefix?: string | EntityText, }; diff --git a/lib/types/thread-types.js b/lib/types/thread-types.js --- a/lib/types/thread-types.js +++ b/lib/types/thread-types.js @@ -2,7 +2,6 @@ import invariant from 'invariant'; -import type { UserEntity } from '../utils/entity-text'; import type { Shape } from './core'; import type { CalendarQuery, RawEntryInfo } from './entry-types'; import type { @@ -12,6 +11,7 @@ import type { ThreadSubscription } from './subscription-types'; import type { ServerUpdateInfo, ClientUpdateInfo } from './update-types'; import type { UserInfo, UserInfos } from './user-types'; +import type { ThreadEntity } from '../utils/entity-text'; export const threadTypes = Object.freeze({ //OPEN: 0, (DEPRECATED) @@ -208,7 +208,7 @@ +id: string, +type: ThreadType, +name: ?string, - +uiName: string | $ReadOnlyArray, + +uiName: string | ThreadEntity, +description: ?string, +color: string, // hex, without "#" or "0x" +creationTime: number, // millisecond timestamp diff --git a/lib/utils/entity-helpers.js b/lib/utils/entity-helpers.js --- a/lib/utils/entity-helpers.js +++ b/lib/utils/entity-helpers.js @@ -3,22 +3,19 @@ import invariant from 'invariant'; import * as React from 'react'; -import type { ThreadInfo, ResolvedThreadInfo } from '../types/thread-types'; -import { values } from '../utils/objects'; import { ET, useENSNamesForEntityText, entityTextToRawString, } from './entity-text'; +import type { ThreadInfo, ResolvedThreadInfo } from '../types/thread-types'; +import { values } from '../utils/objects'; function useResolvedThreadInfos( threadInfos: $ReadOnlyArray, ): $ReadOnlyArray { const entityText = React.useMemo( - () => - threadInfos.map(threadInfo => - ET.thread({ display: 'uiName', threadInfo }), - ), + () => threadInfos.map(threadInfo => threadInfo.uiName), [threadInfos], ); const withENSNames = useENSNamesForEntityText(entityText); 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 @@ -3,6 +3,7 @@ import invariant from 'invariant'; import * as React from 'react'; +import type { GetENSNames } from './ens-helpers'; import { useENSNames } from '../hooks/ens-cache'; import { threadNoun } from '../shared/thread-utils'; import { stringForUser } from '../shared/user-utils'; @@ -13,9 +14,8 @@ type ThreadInfo, } from '../types/thread-types'; import { basePluralize } from '../utils/text-utils'; -import type { GetENSNames } from './ens-helpers'; -export type UserEntity = { +type UserEntity = { +type: 'user', +id: string, +username?: ?string, @@ -24,7 +24,7 @@ }; // Comments explain how thread name will appear from user4's perspective -type ThreadEntity = +export type ThreadEntity = | { +type: 'thread', +id: string, @@ -119,6 +119,9 @@ entityTextFunction.thread = (input: EntityTextThreadInput) => { if (input.display === 'uiName') { const { threadInfo } = input; + if (typeof threadInfo.uiName !== 'string') { + return threadInfo.uiName; + } return { type: 'thread', id: threadInfo.id,