Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions packages/core-data/src/awareness/post-editor-awareness.ts
Original file line number Diff line number Diff line change
Expand Up @@ -219,8 +219,8 @@ export class PostEditorAwareness extends BaseAwarenessState< PostEditorState > {
( [ clientId, collaboratorState ] ) => [
String( clientId ),
{
name: collaboratorState.collaboratorInfo.name,
wpUserId: collaboratorState.collaboratorInfo.id,
name: collaboratorState?.collaboratorInfo?.name,
wpUserId: collaboratorState?.collaboratorInfo?.id,
},
]
)
Expand Down
11 changes: 9 additions & 2 deletions packages/editor/src/components/collaborators-presence/avatar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import './styles/avatar.scss';
type AvatarSize = 'small' | 'medium';

interface AvatarProps {
collaboratorInfo: PostEditorAwarenessState[ 'collaboratorInfo' ];
collaboratorInfo?: PostEditorAwarenessState[ 'collaboratorInfo' ] | null;
showCollaboratorColorBorder?: boolean;
size?: AvatarSize;
}
Expand All @@ -23,6 +23,13 @@ export function Avatar( {
showCollaboratorColorBorder,
size = 'small',
}: AvatarProps ) {
// collaboratorInfo can be undefined while awareness state is syncing (e.g. before
// getCurrentUser() resolves for the local user, or for remote users before their
// state is fully propagated).
if ( ! collaboratorInfo ) {
return null;
}

const className = clsx(
'editor-collaborators-presence__avatar',
`editor-collaborators-presence__avatar--${ size }`,
Expand All @@ -36,7 +43,7 @@ export function Avatar( {
collaboratorInfo.avatar_urls?.[ 24 ];

const avatarStyles = {
'--avatar-url': `url(${ avatarUrl })`,
'--avatar-url': avatarUrl ? `url(${ avatarUrl })` : undefined,
'--collaborator-color': collaboratorInfo.color,
} as React.CSSProperties;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,11 @@ export function CollaboratorsPresence( {
postType
) as PostEditorAwarenessState[];

// Filter out current user - we never show ourselves in the list
// Filter out current user - we never show ourselves in the list.
// Also filter out collaborators whose info is not yet available (can happen
// while awareness state is syncing, e.g. before getCurrentUser() resolves).
const otherActiveCollaborators = activeCollaborators.filter(
( collaborator ) => ! collaborator.isMe
( collaborator ) => ! collaborator.isMe && collaborator.collaboratorInfo
);

const [ isPopoverVisible, setIsPopoverVisible ] = useState( false );
Expand All @@ -56,6 +58,7 @@ export function CollaboratorsPresence( {
const visibleCollaborators = otherActiveCollaborators.slice( 0, 3 );
const remainingCollaborators = otherActiveCollaborators.slice( 3 );
const remainingCollaboratorsText = remainingCollaborators
.filter( ( { collaboratorInfo } ) => collaboratorInfo )
.map( ( { collaboratorInfo } ) => collaboratorInfo.name )
.join( ', ' );

Expand Down
62 changes: 37 additions & 25 deletions packages/editor/src/components/collaborators-presence/list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,34 @@ interface CollaboratorsListProps {
setIsPopoverVisible: ( isVisible: boolean ) => void;
}

function CollaboratorsListItem( {
collaboratorState,
}: {
collaboratorState: PostEditorAwarenessState;
} ) {
return (
<button
key={ collaboratorState.clientId }
className="editor-collaborators-presence__list-item"
disabled
style={ {
opacity: collaboratorState.isConnected ? 1 : 0.5,
} }
>
<Avatar
collaboratorInfo={ collaboratorState.collaboratorInfo }
showCollaboratorColorBorder
size="medium"
/>
<div className="editor-collaborators-presence__list-item-info">
<div className="editor-collaborators-presence__list-item-name">
{ collaboratorState.collaboratorInfo.name }
</div>
</div>
</button>
);
}

/**
* Renders a list showing all active collaborators with their details.
* Note: activeUsers should already exclude the current user (filtered by parent component).
Expand Down Expand Up @@ -51,31 +79,15 @@ export function CollaboratorsList( {
</div>
</div>
<div className="editor-collaborators-presence__list-items">
{ activeCollaborators.map( ( collaboratorState ) => (
<button
key={ collaboratorState.clientId }
className="editor-collaborators-presence__list-item"
disabled
style={ {
opacity: collaboratorState.isConnected
? 1
: 0.5,
} }
>
<Avatar
collaboratorInfo={
collaboratorState.collaboratorInfo
}
showCollaboratorColorBorder
size="medium"
/>
<div className="editor-collaborators-presence__list-item-info">
<div className="editor-collaborators-presence__list-item-name">
{ collaboratorState.collaboratorInfo.name }
</div>
</div>
</button>
) ) }
{ activeCollaborators.map(
( collaboratorState ) =>
collaboratorState.collaboratorInfo && (
<CollaboratorsListItem
key={ collaboratorState.clientId }
collaboratorState={ collaboratorState }
/>
)
) }
</div>
</div>
</Popover>
Expand Down
Loading