feat(presence): ajouter une pastille de présence sur l'avatar des membres

watcha-develop
dlamarcheteamnet 6 days ago
parent 5be2596c0b
commit 3294477a1a
  1. 36
      res/css/views/rooms/_EntityTile.pcss
  2. 20
      src/components/views/rooms/EntityTile.tsx

@ -126,6 +126,42 @@ limitations under the License.
z-index: 1;
}
/* watcha+ : pastille de présence sur l'avatar (liste des membres) */
.mx_EntityTile_presenceDot {
position: absolute;
left: 28px;
bottom: 3px;
width: 10px;
height: 10px;
border-radius: 50%;
box-sizing: border-box;
border: 2px solid $background;
z-index: 3;
}
.mx_EntityTile_presenceDot_online {
background-color: #2dbd59; /* vert : disponible */
}
.mx_EntityTile_presenceDot_busy {
background-color: #ff5b55; /* rouge : occupé */
}
.mx_EntityTile_presenceDot_unavailable {
background-color: #fdbd64; /* orange : absent */
}
.mx_EntityTile_presenceDot_offline {
background-color: $secondary-content; /* gris : hors ligne */
}
/* Salons chiffrés : l'icône E2E occupe le coin bas-droit, on remonte la pastille en haut-droit */
.mx_EntityTile_avatar:has(.mx_E2EIcon) .mx_EntityTile_presenceDot {
top: 3px;
bottom: auto;
}
/* +watcha */
.mx_EntityTile_name {
flex: 1 1 0;
overflow: hidden;

@ -44,6 +44,15 @@ const PRESENCE_CLASS: Record<PresenceState, string> = {
"io.element.unreachable": "mx_EntityTile_unreachable",
};
// watcha+ : classe de la pastille de présence affichée sur l'avatar (liste des membres).
// "busy" relève de MSC3026 (org.matrix.msc3026.busy) et n'est pas dans le type PresenceState.
const PRESENCE_DOT_CLASS: Record<string, string> = {
"online": "mx_EntityTile_presenceDot_online",
"unavailable": "mx_EntityTile_presenceDot_unavailable",
"org.matrix.msc3026.busy": "mx_EntityTile_presenceDot_busy",
};
// +watcha
function presenceClassForMember(presenceState?: PresenceState, lastActiveAgo?: number, showPresence?: boolean): string {
if (showPresence === false) {
return "mx_EntityTile_online_beenactive";
@ -201,6 +210,14 @@ export default class EntityTile extends React.PureComponent<IProps, IState> {
// Vérifie si userIdPart est dans la liste
const crownClass = userIdReplace && userIdPart && allowedValues.includes(userIdPart) ? `mx_EntityTile_avatar_crown_${userIdReplace}` : '';
// Pastille de présence sur l'avatar (disponible / occupé / absent / hors ligne)
let presenceDot;
if (this.props.showPresence) {
const presenceDotClass =
PRESENCE_DOT_CLASS[this.props.presenceState as string] || "mx_EntityTile_presenceDot_offline";
presenceDot = <span className={classNames("mx_EntityTile_presenceDot", presenceDotClass)} />;
}
return (
<div>
<AccessibleButton
@ -209,8 +226,9 @@ export default class EntityTile extends React.PureComponent<IProps, IState> {
onClick={this.props.onClick}
>
<div className="mx_EntityTile_avatar">
{crownClass && ( <div className={crownClass} ></div>)}
{crownClass && ( <div className={crownClass} ></div>)}
{av}
{presenceDot}
{e2eIcon}
</div>
{nameAndPresence}

Loading…
Cancel
Save