Import/export additional message flags

This commit is contained in:
Fedor Indutny 2024-06-13 16:26:26 -07:00 committed by GitHub
parent cf8023821c
commit de638fbc2b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
14 changed files with 85 additions and 2 deletions

View file

@ -0,0 +1,10 @@
<svg width="12" height="12" viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_1619_1707)">
<path d="M9 0C7.34 0 6 1.34 6 3V4.5H2C0.9 4.5 0 5.4 0 6.5V10C0 11.1 0.9 12 2 12H7C8.1 12 9 11.1 9 10V6.5C9 5.4 8.1 4.5 7 4.5V3C7 1.9 7.9 1 9 1C10.1 1 11 1.9 11 3V5H12V3C12 1.34 10.66 0 9 0ZM8 6.5V10C8 10.55 7.55 11 7 11H2C1.45 11 1 10.55 1 10V6.5C1 5.95 1.45 5.5 2 5.5H7C7.55 5.5 8 5.95 8 6.5ZM5 8.35V10H4V8.35C3.71 8.18 3.5 7.87 3.5 7.5C3.5 6.95 3.95 6.5 4.5 6.5C5.05 6.5 5.5 6.95 5.5 7.5C5.5 7.87 5.29 8.17 5 8.35Z" fill="black" fill-opacity="0.72"/>
</g>
<defs>
<clipPath id="clip0_1619_1707">
<rect width="12" height="12" fill="white"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 702 B

View file

@ -1205,6 +1205,29 @@ $message-padding-horizontal: 12px;
}
}
.module-message__metadata__sms {
width: 12px;
height: 12px;
display: inline-block;
margin-inline-start: 6px;
// High margin to leave space for the increase when we go to two checks
margin-bottom: 2px;
@include color-svg(
'../images/icons/v2/lock-unlock-outline-12.svg',
$color-white
);
}
.module-message__metadata__sms--incoming {
@include light-theme {
background-color: $color-gray-60;
}
@include dark-theme {
background-color: $color-gray-25;
}
}
.module-message__container--outgoing .module-message__metadata__edited {
color: $color-white-alpha-80;
}

View file

@ -51,6 +51,7 @@ const MESSAGE_DEFAULT_PROPS = {
isMessageRequestAccepted: true,
isSelected: false,
isSelectMode: false,
isSMS: false,
onToggleSelect: shouldNeverBeCalled,
onReplyToMessage: shouldNeverBeCalled,
kickOffAttachmentDownload: shouldNeverBeCalled,

View file

@ -99,6 +99,7 @@ import { UserText } from '../UserText';
const GUESS_METADATA_WIDTH_TIMESTAMP_SIZE = 16;
const GUESS_METADATA_WIDTH_EXPIRE_TIMER_SIZE = 18;
const GUESS_METADATA_WIDTH_SMS_SIZE = 18;
const GUESS_METADATA_WIDTH_EDITED_SIZE = 40;
const GUESS_METADATA_WIDTH_OUTGOING_SIZE: Record<MessageStatusType, number> = {
delivered: 24,
@ -218,6 +219,7 @@ export type PropsData = {
isTargetedCounter?: number;
isSelected: boolean;
isSelectMode: boolean;
isSMS: boolean;
isSpoilerExpanded?: Record<number, boolean>;
direction: DirectionType;
timestamp: number;
@ -628,7 +630,8 @@ export class Message extends React.PureComponent<Props, State> {
* because it can reduce layout jumpiness.
*/
private guessMetadataWidth(): number {
const { direction, expirationLength, status, isEditedMessage } = this.props;
const { direction, expirationLength, isSMS, status, isEditedMessage } =
this.props;
let result = GUESS_METADATA_WIDTH_TIMESTAMP_SIZE;
@ -641,6 +644,10 @@ export class Message extends React.PureComponent<Props, State> {
result += GUESS_METADATA_WIDTH_EXPIRE_TIMER_SIZE;
}
if (isSMS) {
result += GUESS_METADATA_WIDTH_SMS_SIZE;
}
if (direction === 'outgoing' && status) {
result += GUESS_METADATA_WIDTH_OUTGOING_SIZE[status];
}
@ -811,6 +818,7 @@ export class Message extends React.PureComponent<Props, State> {
i18n,
id,
isEditedMessage,
isSMS,
isSticker,
isTapToViewExpired,
retryMessageSend,
@ -834,6 +842,7 @@ export class Message extends React.PureComponent<Props, State> {
i18n={i18n}
id={id}
isEditedMessage={isEditedMessage}
isSMS={isSMS}
isInline={isInline}
isOutlineOnlyBubble={
deletedForEveryone || (attachmentDroppedDueToSize && !text)

View file

@ -36,6 +36,7 @@ const defaultMessage: MessageDataPropsType = {
isMessageRequestAccepted: true,
isSelected: false,
isSelectMode: false,
isSMS: false,
isSpoilerExpanded: {},
previews: [],
readStatus: ReadStatus.Read,

View file

@ -27,6 +27,7 @@ type PropsType = {
i18n: LocalizerType;
id: string;
isEditedMessage?: boolean;
isSMS?: boolean;
isInline?: boolean;
isOutlineOnlyBubble?: boolean;
isShowingImage: boolean;
@ -56,6 +57,7 @@ export const MessageMetadata = forwardRef<HTMLDivElement, Readonly<PropsType>>(
i18n,
id,
isEditedMessage,
isSMS,
isOutlineOnlyBubble,
isInline,
isShowingImage,
@ -211,6 +213,11 @@ export const MessageMetadata = forwardRef<HTMLDivElement, Readonly<PropsType>>(
</button>
)}
{timestampNode}
{isSMS ? (
<div
className={`module-message__metadata__sms module-message__metadata__sms--${direction}`}
/>
) : null}
{expirationLength ? (
<ExpireTimer
direction={metadataDirection}

View file

@ -105,6 +105,7 @@ const defaultMessageProps: TimelineMessagesProps = {
isMessageRequestAccepted: true,
isSelected: false,
isSelectMode: false,
isSMS: false,
isSpoilerExpanded: {},
toggleSelectMessage: action('toggleSelectMessage'),
kickOffAttachmentDownload: action('default--kickOffAttachmentDownload'),

View file

@ -67,6 +67,7 @@ function mockMessageTimelineItem(
isMessageRequestAccepted: true,
isSelected: false,
isSelectMode: false,
isSMS: false,
isSpoilerExpanded: {},
previews: [],
readStatus: ReadStatus.Read,

View file

@ -295,6 +295,7 @@ const createProps = (overrideProps: Partial<Props> = {}): Props => ({
isSelectMode: isBoolean(overrideProps.isSelectMode)
? overrideProps.isSelectMode
: false,
isSMS: isBoolean(overrideProps.isSMS) ? overrideProps.isSMS : false,
isSpoilerExpanded: overrideProps.isSpoilerExpanded || {},
isTapToView: overrideProps.isTapToView,
isTapToViewError: overrideProps.isTapToViewError,
@ -2060,6 +2061,12 @@ PaymentNotification.args = {
},
};
export const SMS = Template.bind({});
SMS.args = {
isSMS: true,
text: 'hello',
};
function MultiSelectMessage() {
const [selected, setSelected] = React.useState(false);

1
ts/model-types.d.ts vendored
View file

@ -198,6 +198,7 @@ export type MessageAttributesType = {
quote?: QuotedMessageType;
reactions?: ReadonlyArray<MessageReactionType>;
requiredProtocolVersion?: number;
sms?: boolean;
sourceDevice?: number;
storyDistributionListId?: StoryDistributionIdString;
storyId?: string;

View file

@ -747,7 +747,7 @@ export class BackupExportStream extends Readable {
expireStartDate,
expiresInMs,
revisions: [],
sms: false,
sms: message.sms === true,
};
if (!isNormalBubble(message)) {

View file

@ -881,6 +881,7 @@ export class BackupImportStream extends Writable {
item.expiresInMs && !item.expiresInMs.isZero()
? DurationInSeconds.fromMillis(item.expiresInMs.toNumber())
: undefined,
sms: item.sms === true ? true : undefined,
...directionDetails,
};
const additionalMessages: Array<MessageAttributesType> = [];

View file

@ -761,6 +761,7 @@ export const getPropsForMessage = (
isMessageRequestAccepted: conversation?.acceptedMessageRequest ?? true,
isSelected,
isSelectMode,
isSMS: message.sms === true,
isSpoilerExpanded: message.isSpoilerExpanded,
isSticker: Boolean(sticker),
isTargeted,

View file

@ -363,4 +363,24 @@ describe('backup/bubble messages', () => {
},
]);
});
it('roundtrips sms messages', async () => {
await symmetricRoundtripHarness([
{
conversationId: contactA.id,
id: generateGuid(),
type: 'incoming',
received_at: 3,
received_at_ms: 3,
sent_at: 3,
timestamp: 3,
sourceServiceId: CONTACT_A,
body: 'd',
readStatus: ReadStatus.Unread,
seenStatus: SeenStatus.Unseen,
unidentifiedDeliveryReceived: true,
sms: true,
},
]);
});
});