use a HOC to fetch closed group conversations for avatar rendering

This commit is contained in:
Audric Ackermann 2020-09-14 16:06:24 +10:00
parent 9584d0a1af
commit b845ba9642
No known key found for this signature in database
GPG key ID: 999F434D76324AD4
9 changed files with 101 additions and 47 deletions

View file

@ -30,10 +30,10 @@ const {
const { ContactListItem } = require('../../ts/components/ContactListItem');
const { ContactName } = require('../../ts/components/conversation/ContactName');
const {
ConversationHeader,
ConversationHeaderWithDetails,
} = require('../../ts/components/conversation/ConversationHeader');
const {
SessionGroupSettings,
SessionGroupSettingsWithDetails,
} = require('../../ts/components/session/SessionGroupSettings');
const {
EmbeddedContact,
@ -275,8 +275,8 @@ exports.setup = (options = {}) => {
ContactDetail,
ContactListItem,
ContactName,
ConversationHeader,
SessionGroupSettings,
ConversationHeaderWithDetails,
SessionGroupSettingsWithDetails,
SettingsView,
EmbeddedContact,
Emojify,

View file

@ -325,7 +325,7 @@
};
this.titleView = new Whisper.ReactWrapperView({
className: 'title-wrapper',
Component: window.Signal.Components.ConversationHeader,
Component: window.Signal.Components.ConversationHeaderWithDetails,
props: getHeaderProps(),
});
this.updateHeader = () => this.titleView.update(getHeaderProps());
@ -359,7 +359,7 @@
if (!this.groupSettings) {
this.groupSettings = new Whisper.ReactWrapperView({
className: 'group-settings',
Component: window.Signal.Components.SessionGroupSettings,
Component: window.Signal.Components.SessionGroupSettingsWithDetails,
props: getGroupSettingsProps(this.model),
});
this.$('.conversation-content-right').append(this.groupSettings.el);

View file

@ -20,10 +20,8 @@ import {
getInviteContactMenuItem,
getLeaveGroupMenuItem,
} from '../session/utils/Menu';
import { ConversationAttributes } from '../../js/models/conversations';
import { GroupUtils } from '../session/utils';
import { PubKey } from '../session/types';
import { UserUtil } from '../util';
import { usingClosedConversationDetails } from './session/usingClosedConversationDetails';
export type PropsData = {
id: string;
@ -57,6 +55,7 @@ export type PropsData = {
isSecondary?: boolean;
isGroupInvitation?: boolean;
isKickedFromGroup?: boolean;
closedMemberConversations?: any; // this is added by usingClosedConversationDetails
};
type PropsHousekeeping = {
@ -75,34 +74,9 @@ type PropsHousekeeping = {
type Props = PropsData & PropsHousekeeping;
type State = {
closedMemberConversations?: Array<ConversationAttributes>;
};
export class ConversationListItem extends React.PureComponent<Props, State> {
class ConversationListItem extends React.PureComponent<Props> {
public constructor(props: Props) {
super(props);
this.state = { closedMemberConversations: undefined };
}
public componentDidMount() {
void this.fetchClosedConversationDetails();
}
public async fetchClosedConversationDetails() {
if (!this.props.isPublic && this.props.type === 'group') {
const groupId = this.props.phoneNumber;
let members = await GroupUtils.getGroupMembers(PubKey.cast(groupId));
const ourPrimary = await UserUtil.getPrimary();
members = members.filter(m => m.key !== ourPrimary.key);
members.sort((a, b) => (a.key < b.key ? -1 : a.key > b.key ? 1 : 0));
const membersConvos = members.map(
m => window.ConversationController.get(m.key).cachedProps
);
// no need to forward more than 2 conversation for rendering the group avatar
membersConvos.slice(0, 2);
this.setState({ closedMemberConversations: membersConvos });
}
}
public renderAvatar() {
@ -133,7 +107,7 @@ export class ConversationListItem extends React.PureComponent<Props, State> {
profileName={profileName}
size={iconSize}
isPublic={isPublic}
closedMemberConversations={this.state.closedMemberConversations}
closedMemberConversations={this.props.closedMemberConversations}
/>
</div>
);
@ -399,3 +373,7 @@ export class ConversationListItem extends React.PureComponent<Props, State> {
);
}
}
export const ConversationListItemWithDetails = usingClosedConversationDetails(
ConversationListItem
);

View file

@ -1,6 +1,6 @@
import React from 'react';
import {
ConversationListItem,
ConversationListItemWithDetails,
PropsData as ConversationListItemPropsType,
} from './ConversationListItem';
import {
@ -62,7 +62,7 @@ export class SearchResults extends React.Component<Props> {
{i18n('conversationsHeader')}
</div>
{conversations.map(conversation => (
<ConversationListItem
<ConversationListItemWithDetails
key={conversation.phoneNumber}
{...conversation}
onClick={openConversation}
@ -106,7 +106,7 @@ export class SearchResults extends React.Component<Props> {
<div className="module-search-results__contacts">
<div className="module-search-results__contacts-header">{header}</div>
{items.map(contact => (
<ConversationListItem
<ConversationListItemWithDetails
key={contact.phoneNumber}
{...contact}
onClick={openConversation}

View file

@ -16,6 +16,7 @@ import {
SessionButtonType,
} from '../session/SessionButton';
import * as Menu from '../../session/utils/Menu';
import { usingClosedConversationDetails } from '../session/usingClosedConversationDetails';
export interface TimerOption {
name: string;
@ -91,9 +92,10 @@ interface Props {
onUpdateGroupName: () => void;
i18n: LocalizerType;
closedMemberConversations?: any; // this is added by usingClosedConversationDetails
}
export class ConversationHeader extends React.Component<Props> {
class ConversationHeader extends React.Component<Props> {
public showMenuBound: (event: React.MouseEvent<HTMLDivElement>) => void;
public onAvatarClickBound: (userPubKey: string) => void;
public menuTriggerRef: React.RefObject<any>;
@ -196,6 +198,7 @@ export class ConversationHeader extends React.Component<Props> {
public renderAvatar() {
const {
avatarPath,
closedMemberConversations,
i18n,
isGroup,
isMe,
@ -217,11 +220,12 @@ export class ConversationHeader extends React.Component<Props> {
name={name}
phoneNumber={phoneNumber}
profileName={profileName}
size={28}
size={36}
onAvatarClick={() => {
this.onAvatarClickBound(phoneNumber);
}}
isPublic={isPublic}
closedMemberConversations={closedMemberConversations}
/>
</span>
);
@ -497,3 +501,7 @@ export class ConversationHeader extends React.Component<Props> {
);
}
}
export const ConversationHeaderWithDetails = usingClosedConversationDetails(
ConversationHeader
);

View file

@ -1,7 +1,7 @@
import React from 'react';
import {
ConversationListItem,
ConversationListItemWithDetails,
PropsData as ConversationListItemPropsType,
} from '../ConversationListItem';
import { PropsData as SearchResultsProps } from '../SearchResults';
@ -116,7 +116,7 @@ export class LeftPaneContactSection extends React.Component<Props, State> {
const item = contacts[index];
return (
<ConversationListItem
<ConversationListItemWithDetails
key={key}
style={style}
{...item}

View file

@ -4,7 +4,7 @@ import { AutoSizer, List } from 'react-virtualized';
import { MainViewController } from '../MainViewController';
import {
ConversationListItem,
ConversationListItemWithDetails,
PropsData as ConversationListItemPropsType,
} from '../ConversationListItem';
import { ConversationType } from '../../state/ducks/conversations';
@ -113,7 +113,7 @@ export class LeftPaneMessageSection extends React.Component<Props, State> {
const conversation = conversations[index];
return (
<ConversationListItem
<ConversationListItemWithDetails
key={key}
style={style}
{...conversation}

View file

@ -10,6 +10,7 @@ import { SessionDropdown } from './SessionDropdown';
import { MediaGallery } from '../conversation/media-gallery/MediaGallery';
import _ from 'lodash';
import { TimerOption } from '../conversation/ConversationHeader';
import { usingClosedConversationDetails } from '../session/usingClosedConversationDetails';
interface Props {
id: string;
@ -23,6 +24,7 @@ interface Props {
amMod: boolean;
isKickedFromGroup: boolean;
isBlocked: boolean;
closedMemberConversations?: any; // this is added by usingClosedConversationDetails
onGoBack: () => void;
onInviteContacts: () => void;
@ -33,7 +35,7 @@ interface Props {
onSetDisappearingMessages: (seconds: number) => void;
}
export class SessionGroupSettings extends React.Component<Props, any> {
class SessionGroupSettings extends React.Component<Props, any> {
public constructor(props: Props) {
super(props);
@ -309,6 +311,7 @@ export class SessionGroupSettings extends React.Component<Props, any> {
private renderHeader() {
const {
closedMemberConversations,
id,
onGoBack,
onInviteContacts,
@ -336,6 +339,7 @@ export class SessionGroupSettings extends React.Component<Props, any> {
conversationType="group"
size={80}
isPublic={isPublic}
closedMemberConversations={closedMemberConversations}
/>
<div className="invite-friends-container">
{showInviteContacts && (
@ -350,3 +354,7 @@ export class SessionGroupSettings extends React.Component<Props, any> {
);
}
}
export const SessionGroupSettingsWithDetails = usingClosedConversationDetails(
SessionGroupSettings
);

View file

@ -0,0 +1,60 @@
import { GroupUtils } from '../../session/utils';
import { UserUtil } from '../../util';
import { PubKey } from '../../session/types';
import React from 'react';
import { ConversationAttributes } from '../../../js/models/conversations';
type State = {
closedMemberConversations?: Array<ConversationAttributes>;
};
export function usingClosedConversationDetails(WrappedComponent: any) {
return class extends React.Component<any, State> {
constructor(props: any) {
super(props);
this.state = {
closedMemberConversations: undefined,
};
}
public componentDidMount() {
void this.fetchClosedConversationDetails();
}
public render() {
return (
<WrappedComponent
closedMemberConversations={this.state.closedMemberConversations}
{...this.props}
/>
);
}
private async fetchClosedConversationDetails() {
const {
isPublic,
type,
conversationType,
isGroup,
phoneNumber,
id,
} = this.props;
if (
!isPublic &&
(conversationType === 'group' || type === 'group' || isGroup)
) {
console.warn('fetchClosedConversationDetails');
const groupId = id || phoneNumber;
let members = await GroupUtils.getGroupMembers(PubKey.cast(groupId));
const ourPrimary = await UserUtil.getPrimary();
members = members.filter(m => m.key !== ourPrimary.key);
members.sort((a, b) => (a.key < b.key ? -1 : a.key > b.key ? 1 : 0));
const membersConvos = members.map(
m => window.ConversationController.get(m.key).cachedProps
);
// no need to forward more than 2 conversation for rendering the group avatar
membersConvos.slice(0, 2);
this.setState({ closedMemberConversations: membersConvos });
}
}
};
}