From c9cd6a974f16a8f0e499062b2f9cc45d0ee60afb Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Fri, 25 Oct 2024 20:30:10 +1100 Subject: [PATCH] fix: centralised localized string for disappearing messages strings --- protos/SignalService.proto | 1 - ts/components/NoticeBanner.tsx | 21 ++-- ts/components/SessionInboxView.tsx | 2 +- .../conversation/SessionConversation.tsx | 6 +- .../conversation/TimerNotification.tsx | 99 +++-------------- ts/models/message.ts | 48 +++------ ts/models/timerNotifications.ts | 100 ++++++++++++++++++ 7 files changed, 147 insertions(+), 130 deletions(-) create mode 100644 ts/models/timerNotifications.ts diff --git a/protos/SignalService.proto b/protos/SignalService.proto index 5242d158e..853cef89b 100644 --- a/protos/SignalService.proto +++ b/protos/SignalService.proto @@ -146,7 +146,6 @@ message GroupUpdateMessage { optional GroupUpdateInviteResponseMessage inviteResponse = 6; optional GroupUpdateDeleteMemberContentMessage deleteMemberContent = 7; optional GroupUpdateMemberLeftNotificationMessage memberLeftNotificationMessage = 8; - } diff --git a/ts/components/NoticeBanner.tsx b/ts/components/NoticeBanner.tsx index 8bd13b690..659870166 100644 --- a/ts/components/NoticeBanner.tsx +++ b/ts/components/NoticeBanner.tsx @@ -12,9 +12,12 @@ const StyledNoticeBanner = styled(Flex)` padding: var(--margins-xs) var(--margins-sm); text-align: center; flex-shrink: 0; + cursor: pointer; + .session-icon-button { position: absolute; right: var(--margins-sm); + pointer-events: none; } `; @@ -25,12 +28,12 @@ const StyledText = styled.span` type NoticeBannerProps = { text: string; icon: SessionIconType; - onButtonClick: () => void; + onBannerClick: () => void; dataTestId: SessionDataTestId; }; export const NoticeBanner = (props: NoticeBannerProps) => { - const { text, onButtonClick, icon, dataTestId } = props; + const { text, onBannerClick, icon, dataTestId } = props; return ( { justifyContent={'center'} alignItems={'center'} data-testid={dataTestId} + onClick={event => { + event?.preventDefault(); + onBannerClick(); + }} > {text} - { - event?.preventDefault(); - onButtonClick(); - }} - /> + ); }; diff --git a/ts/components/SessionInboxView.tsx b/ts/components/SessionInboxView.tsx index e17a25d17..bff9301b2 100644 --- a/ts/components/SessionInboxView.tsx +++ b/ts/components/SessionInboxView.tsx @@ -128,7 +128,7 @@ const SomeDeviceOutdatedSyncingNotice = () => { return ( diff --git a/ts/components/conversation/SessionConversation.tsx b/ts/components/conversation/SessionConversation.tsx index a5066e39a..8a28b137d 100644 --- a/ts/components/conversation/SessionConversation.tsx +++ b/ts/components/conversation/SessionConversation.tsx @@ -638,7 +638,7 @@ function OutdatedClientBanner(props: { return selectedConversation.hasOutdatedClient?.length ? ( { + onBannerClick={() => { const conversation = ConvoHub.use().get(selectedConversation.id); conversation.set({ hasOutdatedClient: undefined }); void conversation.commit(); @@ -662,8 +662,8 @@ function OutdatedLegacyGroupBanner(props: { return isLegacyGroup ? ( { + text={window.i18n('groupLegacyBanner', { date: 'FIXME AUDRIC' })} // Remove after QA + onBannerClick={() => { showLinkVisitWarningDialog('', dispatch); throw new Error('TODO'); // fixme audric }} diff --git a/ts/components/conversation/TimerNotification.tsx b/ts/components/conversation/TimerNotification.tsx index 0f0bdf232..c768245db 100644 --- a/ts/components/conversation/TimerNotification.tsx +++ b/ts/components/conversation/TimerNotification.tsx @@ -1,8 +1,8 @@ import { useDispatch } from 'react-redux'; import styled from 'styled-components'; +import { PubkeyType } from 'libsession_util_nodejs'; import { PropsForExpirationTimer } from '../../state/ducks/conversations'; -import { isLegacyDisappearingModeEnabled } from '../../session/disappearing_messages/legacy'; import { UserUtils } from '../../session/utils'; import { useSelectedConversationDisappearingMode, @@ -10,7 +10,6 @@ import { useSelectedExpireTimer, useSelectedIsGroupOrCommunity, useSelectedIsGroupV2, - useSelectedIsLegacyGroup, useSelectedIsPrivateFriend, useSelectedIsPublic, } from '../../state/selectors/selectedConversation'; @@ -26,6 +25,7 @@ import type { LocalizerComponentProps, LocalizerToken } from '../../types/locali import { Localizer } from '../basic/Localizer'; import { SessionButtonColor } from '../basic/SessionButton'; import { SessionIcon } from '../icon'; +import { getTimerNotificationStr } from '../../models/timerNotifications'; const FollowSettingButton = styled.button` color: var(--primary-color); @@ -142,90 +142,25 @@ const FollowSettingsButton = (props: PropsForExpirationTimer) => { ); }; -function useTextToRenderI18nProps( - props: PropsForExpirationTimer -): LocalizerComponentProps { - const { pubkey: authorPk, profileName, expirationMode, timespanText: time, disabled } = props; - - const isLegacyGroup = useSelectedIsLegacyGroup(); - - const authorIsUs = authorPk === UserUtils.getOurPubKeyStrFromCache(); - - const name = profileName ?? authorPk; - - // TODO: legacy messages support will be removed in a future release - if (isLegacyDisappearingModeEnabled(expirationMode)) { - return { - token: 'deleteAfterLegacyDisappearingMessagesTheyChangedTimer', - args: { - name: authorIsUs ? window.i18n('you') : name, - time, - }, - }; - } - - const disappearing_messages_type = - expirationMode === 'deleteAfterRead' - ? window.i18n('disappearingMessagesTypeRead') - : window.i18n('disappearingMessagesTypeSent'); - - if (isLegacyGroup) { - if (disabled) { - return authorIsUs - ? { - token: 'disappearingMessagesTurnedOffYouGroup', - } - : { - token: 'disappearingMessagesTurnedOffGroup', - args: { - name, - }, - }; - } - } - - if (disabled) { - return authorIsUs - ? { - token: isLegacyGroup - ? 'disappearingMessagesTurnedOffYouGroup' - : 'disappearingMessagesTurnedOffYou', - } - : { - token: isLegacyGroup - ? 'disappearingMessagesTurnedOffGroup' - : 'disappearingMessagesTurnedOff', - args: { - name, - }, - }; - } - - return authorIsUs - ? { - token: 'disappearingMessagesSetYou', - args: { - time, - disappearing_messages_type, - }, - } - : { - token: 'disappearingMessagesSet', - args: { - time, - disappearing_messages_type, - name, - }, - }; -} - export const TimerNotification = (props: PropsForExpirationTimer) => { - const { messageId } = props; - - const i18nProps = useTextToRenderI18nProps(props); + const { messageId, expirationMode, pubkey, timespanSeconds } = props; + const convoId = useSelectedConversationKey(); const isGroupOrCommunity = useSelectedIsGroupOrCommunity(); const isGroupV2 = useSelectedIsGroupV2(); const isPublic = useSelectedIsPublic(); + + if (!convoId) { + return null; + } + + const i18nProps = getTimerNotificationStr({ + convoId, + author: pubkey as PubkeyType, + expirationMode, + isGroup: isGroupOrCommunity, + timespanSeconds, + }); + // 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) const renderOffIcon = props.disabled || (isGroupOrCommunity && isPublic && !isGroupV2); diff --git a/ts/models/message.ts b/ts/models/message.ts index 5791d1629..f196042c5 100644 --- a/ts/models/message.ts +++ b/ts/models/message.ts @@ -99,6 +99,8 @@ import { } from './groupUpdate'; import { NetworkTime } from '../util/NetworkTime'; import { MessageQueue } from '../session/sending'; +import { getTimerNotificationStr } from './timerNotifications'; +import { ExpirationTimerUpdate } from '../session/disappearing_messages/types'; // tslint:disable: cyclomatic-complexity @@ -408,8 +410,8 @@ export class MessageModel extends Backbone.Model { } } if (this.isExpirationTimerUpdate()) { - const expireTimerUpdate = this.getExpirationTimerUpdate(); - const expireTimer = expireTimerUpdate?.expireTimer; + const expireTimerUpdate = this.getExpirationTimerUpdate() as ExpirationTimerUpdate; // the isExpirationTimerUpdate above enforces this + const expireTimer = expireTimerUpdate.expireTimer; const convo = this.getConversation(); if (!convo) { return ''; @@ -422,39 +424,21 @@ export class MessageModel extends Backbone.Model { ); const source = expireTimerUpdate?.source; - const isUs = UserUtils.isUsFromCache(source); - - const authorName = - ConvoHub.use() - .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, - }); - } - - const localizedMode = - expirationMode === 'deleteAfterRead' - ? window.i18n.stripped('disappearingMessagesTypeRead') - : window.i18n.stripped('disappearingMessagesTypeSent'); + const i18nProps = getTimerNotificationStr({ + convoId: convo.id, + author: source as PubkeyType, + expirationMode, + isGroup: convo.isGroup(), + timespanSeconds: expireTimer, + }); - if (isUs) { - return window.i18n.stripped('disappearingMessagesSetYou', { - time: TimerOptions.getAbbreviated(expireTimerUpdate.expireTimer || 0), - disappearing_messages_type: localizedMode, - }); + if ('args' in i18nProps) { + return window.i18n.stripped( + ...([i18nProps.token, i18nProps.args] as GetMessageArgs) + ); } + return window.i18n.stripped(...([i18nProps.token] as GetMessageArgs)); - return window.i18n.stripped('disappearingMessagesSet', { - time: TimerOptions.getAbbreviated(expireTimerUpdate.expireTimer || 0), - name: authorName, - disappearing_messages_type: localizedMode, - }); } const body = this.get('body'); if (body) { diff --git a/ts/models/timerNotifications.ts b/ts/models/timerNotifications.ts new file mode 100644 index 000000000..ae529f7cd --- /dev/null +++ b/ts/models/timerNotifications.ts @@ -0,0 +1,100 @@ +import { PubkeyType } from 'libsession_util_nodejs'; +import { ConvoHub } from '../session/conversations'; +import { PropsForExpirationTimer } from '../state/ducks/conversations'; +import { PubKey } from '../session/types'; +import { UserUtils } from '../session/utils'; +import { TimerOptions } from '../session/disappearing_messages/timerOptions'; +import { isLegacyDisappearingModeEnabled } from '../session/disappearing_messages/legacy'; +import { LocalizerComponentPropsObject } from '../types/localizer'; + +export function getTimerNotificationStr({ + expirationMode, + timespanSeconds, + convoId, + author, + isGroup, +}: Pick & { + author: PubkeyType; + convoId: string; + isGroup: boolean; +}): LocalizerComponentPropsObject { + const is03group = PubKey.is03Pubkey(convoId); + const authorIsUs = author === UserUtils.getOurPubKeyStrFromCache(); + const isLegacyGroup = isGroup && !is03group; + const timespanText = TimerOptions.getName(timespanSeconds || 0); + const disabled = !timespanSeconds || timespanSeconds <= 0; + + const authorName = ConvoHub.use().getContactProfileNameOrShortenedPubKey(author); + + // TODO: legacy messages support will be removed in a future release + if (isLegacyDisappearingModeEnabled(expirationMode)) { + return { + token: 'deleteAfterLegacyDisappearingMessagesTheyChangedTimer', + args: { + name: authorIsUs ? window.i18n('you') : authorName, + time: timespanText, + }, + } as const; + } + + const disappearing_messages_type = + expirationMode === 'deleteAfterRead' + ? window.i18n('disappearingMessagesTypeRead') + : window.i18n('disappearingMessagesTypeSent'); + + if (isLegacyGroup || isGroup) { + if (disabled) { + return authorIsUs + ? { + token: 'disappearingMessagesTurnedOffYouGroup', + } + : { + token: 'disappearingMessagesTurnedOffGroup', + args: { + name: authorName, + }, + }; + } + return authorIsUs + ? { + token: 'disappearingMessagesSetYou', + args: { time: timespanText, disappearing_messages_type }, + } + : { + token: 'disappearingMessagesSet', + args: { name: authorName, time: timespanText, disappearing_messages_type }, + }; + } + + // legacy groups and groups are handled above. + // This can only be a private chat or Note to Self. + if (disabled) { + return authorIsUs + ? { + token: 'disappearingMessagesTurnedOffYou', + } + : { + token: 'disappearingMessagesTurnedOff', + args: { + name: authorName, + }, + }; + } + + return authorIsUs + ? { + token: 'disappearingMessagesSetYou', + args: { + time: timespanText, + disappearing_messages_type, + }, + } + : { + token: 'disappearingMessagesSet', + args: { + time: timespanText, + disappearing_messages_type, + name: authorName, + }, + }; +}