Indicating User Presence With Collaboration Avatar Group

Collaboration Engine includes an extension to Vaadin’s AvatarGroup component, called CollaborationAvatarGroup. It automatically updates the displayed avatars based on the users who are currently present in a view. More specifically, when CollaborationAvatarGroup is attached, the user’s avatar will be added to the group for all users. When the component becomes detached, often because of navigating to another view or closing the browser tab, the user’s avatar is removed from the group.

Example of a CollaborationAvatarGroup

To get started with CollaborationAvatarGroup, provide the UserInfo that represents the current active user and the id of the topic to connect to. Then add the component to your view:

User userEntity = userService.getCurrentUser();
UserInfo userInfo = new UserInfo(userEntity.getId());

CollaborationAvatarGroup avatarGroup = new CollaborationAvatarGroup(
        userInfo, "ensuranceClaims");
add(avatarGroup);
Note
User, UserService and "ensuranceClaims" are examples
The User and UserService classes are not available in Collaboration Engine. They are examples of classes that might exist in your application for user management. The topic ID "ensuranceClaims" can be any string to identify what the users are collaborating on.

After running the app and opening the view, you should see your own avatar. Try opening the view in another browser tab at the same time, as a separate user entity (distinguished by the id provided to UserInfo). Both tabs should display the avatars of both users.

Configuring the Avatars

The avatars are mostly configured through the UserInfo object. When no other information is available, the avatar displays a generic icon.

Name and Abbreviation

When a user name is provided via UserInfo::setName, an automatically generated abbreviation will be displayed in the avatar. To display a custom abbreviation, UserInfo::setAbbreviation can be used. Hovering the mouse over the avatar displays the full name in a tooltip. The name is also presented in the overflow dropdown; when all of the avatars don’t fit into the group, the last avatar, which has text such as "+3", can be clicked to show the overflowing avatars and names in a dropdown.

Loading Images From a URL

To display an image inside the avatar, there are two options. First of all, if the image is already hosted somewhere, you can provide its URL as a string to UserInfo::setImage. Note that setting an image is not a replacement for the name property. When an image is provided, name is still displayed in a tooltip on hover and in the overflow dropdown.

Loading Images From a Backend

The way to load images from a database to components such as Image or Avatar with Vaadin is to use StreamResources. CollaborationAvatarGroup supports stream resources with the setImageProvider method. It takes a function that generates StreamResources for users based on their UserInfo. For example, if the user entity contains the image as a byte array, you can create a StreamResource that loads those bytes and let the framework take care of hosting the image:

avatarGroup.setImageProvider(userInfo -> {
    StreamResource streamResource = new StreamResource(
            "avatar_" + userInfo.getId(), () -> {
                User userEntity = userService
                        .findById(userInfo.getId());
                byte[] imageBytes = userEntity.getImage();
                return new ByteArrayInputStream(imageBytes);
            });
    streamResource.setContentType("image/png");
    return streamResource;
});

The explanation for this image provider pattern is, that StreamResource is not serializable as JSON, so it can’t be included in UserInfo and sent back and forth through Collaboration Engine.

Scoping the Avatars With Topics

Using different topic ids in the setTopic method allows defining which users can see each others' avatars in the group. If everyone in the view should see each other in the same avatar group, the topic id can be any constant string, as long as it doesn’t conflict with potential other avatar groups in other views. For example, the view name could be used as the topic id in this case.

In many cases, the same CollaborationAvatarGroup component should be re-used for different topics. Think about a form view that is used for editing different entities, where you want to see only the avatars of the users who are editing the same entity. In this case, the topic id should be specific to the edited entity. For example, consider a form for editing different Person entities. When selecting the entity to edit, the topic could be updated as follows:

private void personSelected(long personId) {
    avatarGroup.setTopic("person/" + personId);
}

If the form uses CollaborationBinder, it makes sense to use the same topic id for the binder and the avatar group.

Setting null topic disables the connection to Collaboration Engine. The group won’t display any avatars until a non-null topic id is provided.

Displaying User’s Own Avatar Separately

It’s a common design pattern to display the user’s own avatar somewhere separately from the group of collaborators' avatars. To achieve this, you can exclude the user’s own avatar from the CollaborationAvatarGroup and create a separate Avatar component. You can then add it anywhere in your view, independently of the other avatars.

// Exclude own avatar from the group:
avatarGroup.setOwnAvatarVisible(false);

// Create another component for own avatar:
Avatar ownAvatar = new Avatar();
ownAvatar.setName(userEntity.getName());
ownAvatar.setImage(userEntity.getImageUrl());

add(ownAvatar);

You can set the same name, abbreviation and image properties as for the UserInfo. To load the image from a backend, you can pass a StreamResource directly to the Avatar::setImageResource method.