fix: only show "you set disappearing timer" when you actually did it

pull/3206/head
Audric Ackermann 7 months ago
parent 802fe71629
commit b0af0d651c
No known key found for this signature in database

@ -10,8 +10,6 @@ import {
useSelectedExpireTimer,
useSelectedIsGroupOrCommunity,
useSelectedIsGroupV2,
useSelectedIsNoteToSelf,
useSelectedIsPrivate,
useSelectedIsPrivateFriend,
} from '../../state/selectors/selectedConversation';
import { ReleasedFeatures } from '../../util/releaseFeature';
@ -47,17 +45,17 @@ function useFollowSettingsButtonClick(
? window.i18n('disappearingMessagesTypeRead')
: window.i18n('disappearingMessagesTypeSent');
const i18nMessage = props.disabled
? ({
const i18nMessage: LocalizerComponentProps<LocalizerToken> = props.disabled
? {
token: 'disappearingMessagesFollowSettingOff',
} as LocalizerComponentProps<'disappearingMessagesFollowSettingOff'>)
: ({
}
: {
token: 'disappearingMessagesFollowSettingOn',
args: {
time: props.timespanText,
disappearing_messages_type: localizedMode,
},
} as LocalizerComponentProps<'disappearingMessagesFollowSettingOn'>);
};
const okText = props.disabled ? window.i18n('yes') : window.i18n('set');
@ -142,21 +140,21 @@ const FollowSettingsButton = (props: PropsForExpirationTimer) => {
);
};
function useTextToRenderI18nProps(props: PropsForExpirationTimer) {
const { pubkey, profileName, expirationMode, timespanText: time, type, disabled } = props;
function useTextToRenderI18nProps(
props: PropsForExpirationTimer
): LocalizerComponentProps<LocalizerToken> {
const { pubkey: authorPk, profileName, expirationMode, timespanText: time, disabled } = props;
const isPrivate = useSelectedIsPrivate();
const isNoteToSelf = useSelectedIsNoteToSelf();
const isPrivateAndNotNoteToSelf = isPrivate && !isNoteToSelf;
const authorIsUs = authorPk === UserUtils.getOurPubKeyStrFromCache();
const name = profileName ?? pubkey;
const name = profileName ?? authorPk;
// TODO: legacy messages support will be removed in a future release
if (isLegacyDisappearingModeEnabled(expirationMode)) {
return {
token: 'deleteAfterLegacyDisappearingMessagesTheyChangedTimer',
args: {
name: type === 'fromOther' ? name : window.i18n('you'),
name: authorIsUs ? window.i18n('you') : name,
time,
},
};
@ -168,7 +166,7 @@ function useTextToRenderI18nProps(props: PropsForExpirationTimer) {
: window.i18n('disappearingMessagesTypeSent');
if (disabled) {
if (type === 'fromMe' || isPrivateAndNotNoteToSelf) {
if (authorIsUs) {
return {
token: 'disappearingMessagesTurnedOffYou',
};
@ -180,12 +178,22 @@ function useTextToRenderI18nProps(props: PropsForExpirationTimer) {
},
};
}
if (authorIsUs) {
return {
token: 'disappearingMessagesSetYou',
args: {
time,
disappearing_messages_type,
},
};
}
return {
token: 'disappearingMessagesSetYou',
token: 'disappearingMessagesSet',
args: {
time,
disappearing_messages_type,
name,
},
};
}
@ -193,7 +201,7 @@ function useTextToRenderI18nProps(props: PropsForExpirationTimer) {
export const TimerNotification = (props: PropsForExpirationTimer) => {
const { messageId } = props;
const i18nProps = useTextToRenderI18nProps(props) as LocalizerComponentProps<LocalizerToken>;
const i18nProps = useTextToRenderI18nProps(props);
const isGroupOrCommunity = useSelectedIsGroupOrCommunity();
const isGroupV2 = useSelectedIsGroupV2();
// renderOff is true when the update is put to off, or when we have a legacy group control message (as they are not expiring at all)

@ -246,26 +246,119 @@ export class MessageModel extends Backbone.Model<MessageAttributes> {
}
public getNotificationText() {
let description = this.getDescription();
if (description) {
// regex with a 'g' to ignore part groups
const regex = new RegExp(`@${PubKey.regexForPubkeys}`, 'g');
const pubkeysInDesc = description.match(regex);
(pubkeysInDesc || []).forEach((pubkeyWithAt: string) => {
const pubkey = pubkeyWithAt.slice(1);
const isUS = isUsAnySogsFromCache(pubkey);
const displayName =
getConversationController().getContactProfileNameOrShortenedPubKey(pubkey);
if (isUS) {
description = description?.replace(pubkeyWithAt, `@${window.i18n('you')}`);
} else if (displayName && displayName.length) {
description = description?.replace(pubkeyWithAt, `@${displayName}`);
}
const groupUpdate = this.getGroupUpdateAsArray();
if (groupUpdate) {
const groupName =
this.getConversation()?.getNicknameOrRealUsernameOrPlaceholder() || window.i18n('unknown');
if (groupUpdate.left) {
// @ts-expect-error -- TODO: Fix by using new i18n builder
const { token, args } = getLeftGroupUpdateChangeStr(groupUpdate.left, groupName);
// TODO: clean up this typing
return window.i18n.stripped(...([token, args] as GetMessageArgs<LocalizerToken>));
}
if (groupUpdate.name) {
return window.i18n.stripped('groupNameNew', { group_name: groupUpdate.name });
}
if (groupUpdate.joined?.length) {
// @ts-expect-error -- TODO: Fix by using new i18n builder
const { token, args } = getJoinedGroupUpdateChangeStr(groupUpdate.joined, groupName);
// TODO: clean up this typing
return window.i18n.stripped(...([token, args] as GetMessageArgs<LocalizerToken>));
}
if (groupUpdate.kicked?.length) {
// @ts-expect-error -- TODO: Fix by using new i18n builder
const { token, args } = getKickedGroupUpdateStr(groupUpdate.kicked, groupName);
// TODO: clean up this typing
return window.i18n.stripped(...([token, args] as GetMessageArgs<LocalizerToken>));
}
window.log.warn('did not build a specific change for getDescription of ', groupUpdate);
return window.i18n.stripped('groupUpdated');
}
if (this.isGroupInvitation()) {
return `😎 ${window.i18n.stripped('communityInvitation')}`;
}
if (this.isDataExtractionNotification()) {
const dataExtraction = this.get(
'dataExtractionNotification'
) as DataExtractionNotificationMsg;
if (dataExtraction.type === SignalService.DataExtractionNotification.Type.SCREENSHOT) {
return window.i18n.stripped('screenshotTaken', {
name: getConversationController().getContactProfileNameOrShortenedPubKey(
dataExtraction.source
),
});
}
return window.i18n.stripped('attachmentsMediaSaved', {
name: getConversationController().getContactProfileNameOrShortenedPubKey(
dataExtraction.source
),
});
return description;
}
if ((this.get('attachments') || []).length > 0) {
return window.i18n.stripped('contentDescriptionMediaMessage');
if (this.isCallNotification()) {
const name = getConversationController().getContactProfileNameOrShortenedPubKey(
this.get('conversationId')
);
const callNotificationType = this.get('callNotificationType');
if (callNotificationType === 'missed-call') {
return window.i18n.stripped('callsMissedCallFrom', { name });
}
if (callNotificationType === 'started-call') {
return window.i18n.stripped('callsYouCalled', { name });
}
if (callNotificationType === 'answered-a-call') {
return window.i18n.stripped('callsInProgress');
}
}
const interactionNotification = this.getInteractionNotification();
if (interactionNotification) {
const { interactionType, interactionStatus } = interactionNotification;
// NOTE For now we only show interaction errors in the message history
if (interactionStatus === ConversationInteractionStatus.Error) {
const convo = getConversationController().get(this.get('conversationId'));
if (convo) {
const isGroup = !convo.isPrivate();
const isCommunity = convo.isPublic();
switch (interactionType) {
case ConversationInteractionType.Hide:
// there is no text for hiding changes
return '';
case ConversationInteractionType.Leave:
return isCommunity
? window.i18n.stripped('communityLeaveError', {
community_name: convo.getNicknameOrRealUsernameOrPlaceholder(),
})
: isGroup
? window.i18n.stripped('groupLeaveErrorFailed', {
group_name: convo.getNicknameOrRealUsernameOrPlaceholder(),
})
: '';
default:
assertUnreachable(
interactionType,
`Message.getDescription: Missing case error "${interactionType}"`
);
}
}
}
}
if (this.get('reaction')) {
const reaction = this.get('reaction');
if (reaction && reaction.emoji && reaction.emoji !== '') {
return window.i18n.stripped('emojiReactsNotification', { emoji: reaction.emoji });
}
}
if (this.isExpirationTimerUpdate()) {
const expireTimerUpdate = this.getExpirationTimerUpdate();
@ -282,12 +375,17 @@ export class MessageModel extends Backbone.Model<MessageAttributes> {
);
const source = expireTimerUpdate?.source;
const isUs = UserUtils.isUsFromCache(source);
const authorName =
getConversationController()
.get(source || '')
?.getNicknameOrRealUsernameOrPlaceholder() || window.i18n.stripped('unknown');
if (!expireTimerUpdate || expirationMode === 'off' || !expireTimer || expireTimer === 0) {
if (isUs) {
return window.i18n.stripped('disappearingMessagesTurnedOffYou');
}
return window.i18n.stripped('disappearingMessagesTurnedOff', {
name: authorName,
});
@ -298,12 +396,49 @@ export class MessageModel extends Backbone.Model<MessageAttributes> {
? window.i18n.stripped('disappearingMessagesTypeRead')
: window.i18n.stripped('disappearingMessagesTypeSent');
if (isUs) {
return window.i18n.stripped('disappearingMessagesSetYou', {
time: TimerOptions.getAbbreviated(expireTimerUpdate.expireTimer || 0),
disappearing_messages_type: localizedMode,
});
}
return window.i18n.stripped('disappearingMessagesSet', {
time: TimerOptions.getAbbreviated(expireTimerUpdate.expireTimer || 0),
name: authorName,
disappearing_messages_type: localizedMode,
});
}
const body = this.get('body');
if (body) {
let bodyMentionsMappedToNames = body;
// regex with a 'g' to ignore part groups
const regex = new RegExp(`@${PubKey.regexForPubkeys}`, 'g');
const pubkeysInDesc = body.match(regex);
(pubkeysInDesc || []).forEach((pubkeyWithAt: string) => {
const pubkey = pubkeyWithAt.slice(1);
const isUS = isUsAnySogsFromCache(pubkey);
const displayName =
getConversationController().getContactProfileNameOrShortenedPubKey(pubkey);
if (isUS) {
bodyMentionsMappedToNames = bodyMentionsMappedToNames?.replace(
pubkeyWithAt,
`@${window.i18n('you')}`
);
} else if (displayName && displayName.length) {
bodyMentionsMappedToNames = bodyMentionsMappedToNames?.replace(
pubkeyWithAt,
`@${displayName}`
);
}
});
return bodyMentionsMappedToNames;
}
// Note: we want this after the check for a body as we want to display the body if we have one.
if ((this.get('attachments') || []).length) {
return window.i18n.stripped('contentDescriptionMediaMessage');
}
return '';
}
@ -1265,124 +1400,6 @@ export class MessageModel extends Backbone.Model<MessageAttributes> {
return forcedArrayUpdate;
}
private getDescription() {
const groupUpdate = this.getGroupUpdateAsArray();
if (groupUpdate) {
const groupName =
this.getConversation()?.getNicknameOrRealUsernameOrPlaceholder() || window.i18n('unknown');
if (groupUpdate.left) {
// @ts-expect-error -- TODO: Fix by using new i18n builder
const { token, args } = getLeftGroupUpdateChangeStr(groupUpdate.left, groupName);
// TODO: clean up this typing
return window.i18n.stripped(...([token, args] as GetMessageArgs<LocalizerToken>));
}
if (groupUpdate.name) {
return window.i18n.stripped('groupNameNew', { group_name: groupUpdate.name });
}
if (groupUpdate.joined?.length) {
// @ts-expect-error -- TODO: Fix by using new i18n builder
const { token, args } = getJoinedGroupUpdateChangeStr(groupUpdate.joined, groupName);
// TODO: clean up this typing
return window.i18n.stripped(...([token, args] as GetMessageArgs<LocalizerToken>));
}
if (groupUpdate.kicked?.length) {
// @ts-expect-error -- TODO: Fix by using new i18n builder
const { token, args } = getKickedGroupUpdateStr(groupUpdate.kicked, groupName);
// TODO: clean up this typing
return window.i18n.stripped(...([token, args] as GetMessageArgs<LocalizerToken>));
}
window.log.warn('did not build a specific change for getDescription of ', groupUpdate);
return window.i18n.stripped('groupUpdated');
}
if (this.isGroupInvitation()) {
return `😎 ${window.i18n.stripped('communityInvitation')}`;
}
if (this.isDataExtractionNotification()) {
const dataExtraction = this.get(
'dataExtractionNotification'
) as DataExtractionNotificationMsg;
if (dataExtraction.type === SignalService.DataExtractionNotification.Type.SCREENSHOT) {
return window.i18n.stripped('screenshotTaken', {
name: getConversationController().getContactProfileNameOrShortenedPubKey(
dataExtraction.source
),
});
}
return window.i18n.stripped('attachmentsMediaSaved', {
name: getConversationController().getContactProfileNameOrShortenedPubKey(
dataExtraction.source
),
});
}
if (this.isCallNotification()) {
const name = getConversationController().getContactProfileNameOrShortenedPubKey(
this.get('conversationId')
);
const callNotificationType = this.get('callNotificationType');
if (callNotificationType === 'missed-call') {
return window.i18n.stripped('callsMissedCallFrom', { name });
}
if (callNotificationType === 'started-call') {
return window.i18n.stripped('callsYouCalled', { name });
}
if (callNotificationType === 'answered-a-call') {
return window.i18n.stripped('callsInProgress');
}
}
const interactionNotification = this.getInteractionNotification();
if (interactionNotification) {
const { interactionType, interactionStatus } = interactionNotification;
// NOTE For now we only show interaction errors in the message history
if (interactionStatus === ConversationInteractionStatus.Error) {
const convo = getConversationController().get(this.get('conversationId'));
if (convo) {
const isGroup = !convo.isPrivate();
const isCommunity = convo.isPublic();
switch (interactionType) {
case ConversationInteractionType.Hide:
// there is no text for hiding changes
return '';
case ConversationInteractionType.Leave:
return isCommunity
? window.i18n.stripped('communityLeaveError', {
community_name: convo.getNicknameOrRealUsernameOrPlaceholder(),
})
: isGroup
? window.i18n.stripped('groupLeaveErrorFailed', {
group_name: convo.getNicknameOrRealUsernameOrPlaceholder(),
})
: '';
default:
assertUnreachable(
interactionType,
`Message.getDescription: Missing case error "${interactionType}"`
);
}
}
}
}
if (this.get('reaction')) {
const reaction = this.get('reaction');
if (reaction && reaction.emoji && reaction.emoji !== '') {
return window.i18n.stripped('emojiReactsNotification', { emoji: reaction.emoji });
}
}
return this.get('body');
}
// NOTE We want to replace Backbone .get() calls with these getters as we migrate to Redux completely eventually
// #region Start of getters
public getExpirationType() {

Loading…
Cancel
Save