Skip to content

OC: Timestamp and avatar grouping (Jul 1) #2939

@compulim

Description

@compulim

Feature Request

Background of this work can be found in BasicTranscript.js.

Currently, timestamp grouping is based on nextVisibleActivity (the activity rendered below the current one). For example, if the next visible activity fall into the same timestamp group (e.g. within 5 minutes of each other), only one timestamp will be shown.

Avatar is more-or-less the same, but it requires prevVisibleActivity (the activity rendered above).

Today, the activity renderer (or middleware) is also responsible for rendering timestamp and avatar. The function call is like renderActivity(): false | React.Element.

That means, when we call renderActivity, it either return false if the activity should be hidden (e.g. event activity), or, it immediate render as React.Element.

Since renderer is responsible for rendering timestamp and avatar, when we call this function, the renderer need to know nextVisibleActivity (note the word "visible", because renderer can hide activity by returning false).

Today, we do it by calling renderActivity in a reverse way (render most recent activity first). This will help us to construct the nextVisibleActivity. But it is technically impossible to construct prevVisibleActivity.

In order to group both timestamp and avatar, we need to update the activity renderer signature to renderActivity(): false | () => React.Element.

That means, the renderer can decide if they want to hide, or return a function which will definitely rendering an activity.

In this way, we can easily do a two-pass rendering and pass nextVisibleActivity and prevVisibleActivity to activity renderer. Thus, activity renderer can group both timestamp and avatar.

However, signature change is not trivial. We need some designs and possibly trade-offs (e.g. if devs are not using the new signature, avatar grouping will be disabled, plus warning on deprecations).

The new signature will be:

renderWebChat({
  activityMiddleware: () => next => ({ activity }) => {
    if (activity.type !== 'message') {
      return false;
    }

    return ({ nextVisibleActivity, prevVisibleActivity }) => (
      <div>...</div>
    );
  }
});

Comparing to the old signature:

renderWebChat({
  activityMiddleware: () => next => ({ activity, nextVisibleActivity }) => {
    if (activity.type !== 'message') {
      return false;
    }

    return (
      <div>...</div>
    );
  }
});

Additional Context

Introduce <ActivityContainer>, a common container

While working on this feature, we can consider creating a <ActivityContainer> component, which handle both avatar and timestamp. The user of <ActivityContainer> will only need to take care about the actual content.

This may significantly simplify the common code in <CarouselLayout> and <StackedLayout>, especially given RTL + bubble nub already added quite some complexity.

Also, we could easily allow developers to move timestamp on top of the bubble.

We should also expose this component for developers to use.

Converting all renderers

To reduce confusions, we should also consider converting all renderers to use this new signature.

Consolidating <BasicTranscript> and <BasicTranscriptContent>

As we added "enable composition mode" feature, the <BasicTranscriptContent> is pretty empty and we should consolidate it back.

[Enhancement]

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions