Skip to content

Commit

Permalink
feat: Clickable read receipt on Ping Message (#18308)
Browse files Browse the repository at this point in the history
* feat: Clickable read receipt on Ping Message

* update test

* fix ui glitch
  • Loading branch information
przemvs authored Nov 14, 2024
1 parent b1eb679 commit e1e6ce8
Show file tree
Hide file tree
Showing 7 changed files with 56 additions and 37 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ export const ContentMessageComponent = ({
const {
senderName,
timestamp,
ephemeral_caption: ephemeralCaption,
ephemeralCaption,
ephemeral_status,
assets,
was_edited,
Expand All @@ -114,7 +114,7 @@ export const ContentMessageComponent = ({
} = useKoSubscribableChildren(message, [
'senderName',
'timestamp',
'ephemeral_caption',
'ephemeralCaption',
'ephemeral_status',
'assets',
'was_edited',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,7 @@ export const MessageWrapper: React.FC<MessageParams> = ({
message={message}
is1to1Conversation={conversation.is1to1()}
isLastDeliveredMessage={isLastDeliveredMessage}
onClickDetails={onClickDetails}
/>
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ describe('PingMessage', () => {
isMessageFocused: true,
is1to1Conversation: false,
isLastDeliveredMessage: false,
onClickDetails: jest.fn(),
message: createPingMessage({
caption: ko.pureComputed(() => 'caption'),
unsafeSenderName: ko.pureComputed(() => 'sender'),
Expand Down
63 changes: 38 additions & 25 deletions src/script/components/MessagesList/Message/PingMessage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,53 +26,66 @@ import {t} from 'Util/LocalizerUtil';

import {ReadReceiptStatus} from './ReadReceiptStatus';

import {Message} from '../../../entity/message/Message';
import {PingMessage as PingMessageEntity} from '../../../entity/message/PingMessage';

export interface PingMessageProps {
message: PingMessageEntity;
is1to1Conversation: boolean;
isLastDeliveredMessage: boolean;
onClickDetails: (message: Message) => void;
}

const PingMessage = ({message, is1to1Conversation, isLastDeliveredMessage}: PingMessageProps) => {
const {unsafeSenderName, caption, ephemeral_caption, isObfuscated, get_icon_classes} = useKoSubscribableChildren(
message,
['unsafeSenderName', 'caption', 'ephemeral_caption', 'isObfuscated', 'get_icon_classes'],
);
export const PingMessage = ({
message,
is1to1Conversation,
isLastDeliveredMessage,
onClickDetails,
}: PingMessageProps) => {
const {unsafeSenderName, caption, ephemeralCaption, isObfuscated, iconClasses} = useKoSubscribableChildren(message, [
'unsafeSenderName',
'caption',
'ephemeralCaption',
'isObfuscated',
'iconClasses',
]);

return (
<div className="message-header" data-uie-name="element-message-ping">
<div className="message-header-icon">
<div className={`icon-ping ${get_icon_classes}`} />
<div className={cx('icon-ping', iconClasses)} />
</div>

<div
className={cx('message-header-label message-header-ping', {
'ephemeral-message-obfuscated': isObfuscated,
})}
title={ephemeral_caption}
title={ephemeralCaption}
data-uie-name="element-message-ping-text"
>
<p className="message-header-label__multiline">
<span className="message-header-sender-name">{unsafeSenderName}</span>
<span className="ellipsis">{caption}</span>
</p>

<div>
<ReadReceiptStatus message={message} is1to1Conversation={is1to1Conversation} />
<div className="message-header-content">
<p className="message-header-label__multiline message-ping__content">
<span className="message-header-sender-name">{unsafeSenderName}</span>
<span className="ellipsis">{caption}</span>
</p>

{message.expectsReadConfirmation && is1to1Conversation && isLastDeliveredMessage && (
<div
data-uie-name="status-message-read-receipt-delivered"
title={t('conversationMessageDelivered')}
className="delivered-message-icon"
>
<OutlineCheck />
</div>
)}
<ReadReceiptStatus
message={message}
is1to1Conversation={is1to1Conversation}
onClickDetails={onClickDetails}
/>
</div>

{message.expectsReadConfirmation && is1to1Conversation && isLastDeliveredMessage && (
<div
data-uie-name="status-message-read-receipt-delivered"
title={t('conversationMessageDelivered')}
className="delivered-message-icon"
>
<OutlineCheck />
</div>
)}
</div>
</div>
);
};

export {PingMessage};
4 changes: 2 additions & 2 deletions src/script/entity/message/Message.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ export class Message {
public id: string;
public primary_key?: string;
public readonly accent_color: ko.PureComputed<string>;
public readonly ephemeral_caption: ko.PureComputed<string>;
public readonly ephemeralCaption: ko.PureComputed<string>;
public readonly ephemeral_expires: ko.Observable<boolean | number | string>;
public readonly ephemeral_remaining: ko.Observable<number>;
public readonly ephemeral_started: ko.Observable<number>;
Expand All @@ -88,7 +88,7 @@ export class Message {
constructor(id: string = '0', super_type?: SuperType) {
this.id = id;
this.super_type = super_type;
this.ephemeral_caption = ko.pureComputed(() => {
this.ephemeralCaption = ko.pureComputed(() => {
const remainingTime = this.ephemeral_remaining();
return remainingTime ? `${formatDurationCaption(remainingTime)} ${t('ephemeralRemaining')}` : '';
});
Expand Down
15 changes: 7 additions & 8 deletions src/script/entity/message/PingMessage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,24 +24,23 @@ import {t} from 'Util/LocalizerUtil';
import {Message} from './Message';

import {SuperType} from '../../message/SuperType';
import {ReactionMap} from '../../storage';

export class PingMessage extends Message {
public readonly caption: ko.PureComputed<string>;
public readonly get_icon_classes: ko.PureComputed<string>;
public readonly iconClasses: ko.PureComputed<string>;
readonly reactions = ko.observable<ReactionMap>([]);

constructor() {
super();
this.super_type = SuperType.PING;

this.caption = ko.pureComputed(() => (this.user().isMe ? t('conversationPingYou') : t('conversationPing')));

this.get_icon_classes = ko.pureComputed(() => {
const show_ping_animation = Date.now() - this.timestamp() < 2000;
let css_classes = this.accent_color();
if (show_ping_animation) {
css_classes += ' ping-animation ping-animation-soft';
}
return css_classes;
this.iconClasses = ko.pureComputed(() => {
const showPingAnimation = Date.now() - this.timestamp() < 2000;
const cssClasses = this.accent_color();
return showPingAnimation ? `${cssClasses} ping-animation ping-animation-soft` : cssClasses;
});
}
}
5 changes: 5 additions & 0 deletions src/style/content/conversation/message-list.less
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,11 @@
justify-content: center;
}

.message-header-content {
display: flex;
align-items: center;
}

.message-header-label {
display: flex;
min-width: 0; // fixes ellipsis not working with flexbox (FF)
Expand Down

0 comments on commit e1e6ce8

Please sign in to comment.