fix: tsc does not overwrite workers compiled content

pull/3053/head
Audric Ackermann 2 months ago
parent 261d67d496
commit 53059135ee

@ -1,3 +1,5 @@
var path = require('path');
module.exports = {
root: true,
settings: {
@ -10,6 +12,11 @@ module.exports = {
react: {
version: 'detect',
},
'import/resolver': {
node: {
paths: [path.resolve(__dirname)],
},
},
},
extends: [

3
.gitignore vendored

@ -50,5 +50,6 @@ test-results/
coverage/
stylesheets/dist/
*.worker.js.LICENSE.txt
*.LICENSE.txt
ts/webworker/workers/node/**/*.node

@ -5,7 +5,7 @@ const util = require('util');
const renameAsync = util.promisify(fs.rename);
const unlinkAsync = util.promisify(fs.unlink);
module.exports = async function(context) {
module.exports = async function (context) {
// Replace the app launcher on linux only.
if (process.platform !== 'linux') {
return;

@ -1,6 +1,8 @@
/* eslint-disable @typescript-eslint/no-var-requires */
const path = require('path');
const isProd = process.env.NODE_ENV === 'production';
module.exports = {
entry: './ts/webworker/workers/node/libsession/libsession.worker.ts',
node: {
@ -29,11 +31,11 @@ module.exports = {
},
},
output: {
filename: 'libsession.worker.js',
filename: 'libsession.worker.compiled.js',
path: path.resolve(__dirname, 'ts', 'webworker', 'workers', 'node', 'libsession'),
},
target: 'node',
optimization: {
minimize: true,
minimize: isProd,
},
};

@ -110,15 +110,8 @@ const AvatarImage = (
};
const AvatarInner = (props: Props) => {
const {
base64Data,
size,
pubkey,
forcedAvatarPath,
forcedName,
dataTestId,
onAvatarClick,
} = props;
const { base64Data, size, pubkey, forcedAvatarPath, forcedName, dataTestId, onAvatarClick } =
props;
const [imageBroken, setImageBroken] = useState(false);
const isSelectingMessages = useSelector(isMessageSelectionMode);

@ -82,8 +82,8 @@ const StyledButton = styled.div<{
props.buttonType === SessionButtonType.Solid
? 'background-color: var(--button-solid-disabled-color)'
: props.buttonType === SessionButtonType.Outline
? 'border: 1px solid var(--button-outline-disabled-color)'
: ''};
? 'border: 1px solid var(--button-outline-disabled-color)'
: ''};
color: ${props =>
props.buttonType === SessionButtonType.Solid
? 'var(--button-solid-text-color)'
@ -116,16 +116,8 @@ type Props = {
};
export const SessionButton = (props: Props) => {
const {
buttonType,
buttonShape,
dataTestId,
buttonColor,
text,
disabled,
onClick,
margin,
} = props;
const { buttonType, buttonShape, dataTestId, buttonColor, text, disabled, onClick, margin } =
props;
const clickHandler = (e: any) => {
if (onClick) {

@ -18,8 +18,8 @@ const StyledInput = styled.input<{
props.disabled
? 'var(--disabled-color)'
: props.selectedColor
? props.selectedColor
: 'var(--primary-color)'};
? props.selectedColor
: 'var(--primary-color)'};
}
`;
@ -133,8 +133,8 @@ const StyledLabelOutlineSelected = styled(StyledLabel)<{ selectedColor: string }
props.disabled
? 'var(--disabled-color)'
: props.selectedColor
? props.selectedColor
: 'var(--primary-color)'};
? props.selectedColor
: 'var(--primary-color)'};
outline: 1px solid transparent; /* CSS variables don't work here */
}
`;

@ -16,7 +16,9 @@ const StyledKnob = styled.div<{ active: boolean }>`
? '-2px 1px 3px var(--toggle-switch-ball-shadow-color);'
: '2px 1px 3px var(--toggle-switch-ball-shadow-color);'};
transition: transform var(--default-duration) ease, background-color var(--default-duration) ease;
transition:
transform var(--default-duration) ease,
background-color var(--default-duration) ease;
transform: ${props => (props.active ? 'translateX(25px)' : '')};
`;

@ -42,23 +42,23 @@ const SpacerStyled = styled.div<SpacerProps>`
props.size === 'xl'
? 'var(--margins-xl)'
: props.size === 'lg'
? 'var(--margins-lg)'
: props.size === 'md'
? 'var(--margins-md)'
: props.size === 'sm'
? 'var(--margins-sm)'
: 'var(--margins-xs)'};
? 'var(--margins-lg)'
: props.size === 'md'
? 'var(--margins-md)'
: props.size === 'sm'
? 'var(--margins-sm)'
: 'var(--margins-xs)'};
width: ${props =>
props.size === 'xl'
? 'var(--margins-xl)'
: props.size === 'lg'
? 'var(--margins-lg)'
: props.size === 'md'
? 'var(--margins-md)'
: props.size === 'sm'
? 'var(--margins-sm)'
: 'var(--margins-xs)'};
? 'var(--margins-lg)'
: props.size === 'md'
? 'var(--margins-md)'
: props.size === 'sm'
? 'var(--margins-sm)'
: 'var(--margins-xs)'};
`;
const Spacer = (props: SpacerProps) => {

@ -25,11 +25,13 @@ export const ContactName = (props: Props) => {
const convoName = useNicknameOrProfileNameOrShortenedPubkey(pubkey);
const isPrivate = useIsPrivate(pubkey);
const shouldShowProfile = Boolean(convoName || profileName || name);
const styles = (boldProfileName
? {
fontWeight: 'bold',
}
: {}) as React.CSSProperties;
const styles = (
boldProfileName
? {
fontWeight: 'bold',
}
: {}
) as React.CSSProperties;
const textProfile = profileName || name || convoName || window.i18n('anonymous');
return (

@ -127,10 +127,8 @@ export class SessionConversation extends React.Component<Props, State> {
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
public componentDidUpdate(prevProps: Props, _prevState: State) {
const {
selectedConversationKey: newConversationKey,
selectedConversation: newConversation,
} = this.props;
const { selectedConversationKey: newConversationKey, selectedConversation: newConversation } =
this.props;
const { selectedConversationKey: oldConversationKey } = prevProps;
// if the convo is valid, and it changed, register for drag events

@ -70,14 +70,14 @@ function renderSubtitleText(
return quoteText && quoteText !== ''
? quoteText
: hasAudioAttachment
? window.i18n('audio')
: isGenericFile
? window.i18n('document')
: isVideo
? window.i18n('video')
: isImage
? window.i18n('image')
: null;
? window.i18n('audio')
: isGenericFile
? window.i18n('document')
: isVideo
? window.i18n('video')
: isImage
? window.i18n('image')
: null;
}
export const SessionQuotedMessageComposition = () => {

@ -147,8 +147,8 @@ function useTextToRender(props: PropsForExpirationTimer) {
const mode = isLegacyDisappearingModeEnabled(expirationMode)
? null
: expirationMode === 'deleteAfterRead'
? window.i18n('timerModeRead')
: window.i18n('timerModeSent');
? window.i18n('timerModeRead')
: window.i18n('timerModeSent');
switch (type) {
case 'fromOther':
return disabled
@ -157,12 +157,12 @@ function useTextToRender(props: PropsForExpirationTimer) {
[contact, timespanText]
)
: mode
? window.i18n(ownSideOnly ? 'theySetTheirDisappearingMessages' : 'theyChangedTheTimer', [
contact,
timespanText,
mode,
])
: window.i18n('theyChangedTheTimerLegacy', [contact, timespanText]);
? window.i18n(ownSideOnly ? 'theySetTheirDisappearingMessages' : 'theyChangedTheTimer', [
contact,
timespanText,
mode,
])
: window.i18n('theyChangedTheTimerLegacy', [contact, timespanText]);
case 'fromMe':
case 'fromSync':
return disabled
@ -170,11 +170,11 @@ function useTextToRender(props: PropsForExpirationTimer) {
ownSideOnly ? 'youDisabledYourDisappearingMessages' : 'youDisabledDisappearingMessages'
)
: mode
? window.i18n(ownSideOnly ? 'youSetYourDisappearingMessages' : 'youChangedTheTimer', [
timespanText,
mode,
])
: window.i18n('youChangedTheTimerLegacy', [timespanText]);
? window.i18n(ownSideOnly ? 'youSetYourDisappearingMessages' : 'youChangedTheTimer', [
timespanText,
mode,
])
: window.i18n('youChangedTheTimerLegacy', [timespanText]);
default:
assertUnreachable(type, `TimerNotification: Missing case error "${type}"`);
}

@ -44,10 +44,7 @@ export const Timestamp = (props: Props) => {
// this is a hack to make the date string shorter, looks like moment does not have a localized way of doing this for now.
const dateString = momentFromNow
? momentValue
.fromNow()
.replace('minutes', 'mins')
.replace('minute', 'min')
? momentValue.fromNow().replace('minutes', 'mins').replace('minute', 'min')
: momentValue.format('lll');
const title = moment(timestamp).format('llll');

@ -63,8 +63,8 @@ const StyledTypingDot = styled.div<{ index: number }>`
props.index === 0
? 'typing-animation-first'
: props.index === 1
? 'typing-animation-second'
: 'typing-animation-third'}
? 'typing-animation-second'
: 'typing-animation-third'}
1600ms ease infinite;
`;

@ -51,9 +51,8 @@ export const ConversationHeaderTitle = () => {
abbreviate: true,
});
const [visibleSubtitle, setVisibleSubtitle] = useState<SubtitleStringsType>(
'disappearingMessages'
);
const [visibleSubtitle, setVisibleSubtitle] =
useState<SubtitleStringsType>('disappearingMessages');
const [subtitleStrings, setSubtitleStrings] = useState<SubtitleStrings>({});
const [subtitleArray, setSubtitleArray] = useState<Array<SubtitleStringsType>>([]);

@ -87,55 +87,53 @@ type MediaItemWithYearMonthSection = GenericMediaItemWithSection<YearMonthSectio
};
type MediaItemWithSection = MediaItemWithStaticSection | MediaItemWithYearMonthSection;
const withSection = (referenceDateTime: moment.Moment) => (
mediaItem: MediaItemType
): MediaItemWithSection => {
const today = moment(referenceDateTime).startOf('day');
const yesterday = moment(referenceDateTime)
.subtract(1, 'day')
.startOf('day');
const thisWeek = moment(referenceDateTime).startOf('isoWeek');
const thisMonth = moment(referenceDateTime).startOf('month');
const withSection =
(referenceDateTime: moment.Moment) =>
(mediaItem: MediaItemType): MediaItemWithSection => {
const today = moment(referenceDateTime).startOf('day');
const yesterday = moment(referenceDateTime).subtract(1, 'day').startOf('day');
const thisWeek = moment(referenceDateTime).startOf('isoWeek');
const thisMonth = moment(referenceDateTime).startOf('month');
const { messageTimestamp } = mediaItem;
const mediaItemReceivedDate = moment.utc(messageTimestamp);
if (mediaItemReceivedDate.isAfter(today)) {
return {
order: 0,
type: 'today',
mediaItem,
};
}
if (mediaItemReceivedDate.isAfter(yesterday)) {
return {
order: 1,
type: 'yesterday',
mediaItem,
};
}
if (mediaItemReceivedDate.isAfter(thisWeek)) {
return {
order: 2,
type: 'thisWeek',
mediaItem,
};
}
if (mediaItemReceivedDate.isAfter(thisMonth)) {
return {
order: 3,
type: 'thisMonth',
mediaItem,
};
}
const month: number = mediaItemReceivedDate.month();
const year: number = mediaItemReceivedDate.year();
const { messageTimestamp } = mediaItem;
const mediaItemReceivedDate = moment.utc(messageTimestamp);
if (mediaItemReceivedDate.isAfter(today)) {
return {
order: 0,
type: 'today',
mediaItem,
};
}
if (mediaItemReceivedDate.isAfter(yesterday)) {
return {
order: 1,
type: 'yesterday',
mediaItem,
};
}
if (mediaItemReceivedDate.isAfter(thisWeek)) {
return {
order: 2,
type: 'thisWeek',
mediaItem,
};
}
if (mediaItemReceivedDate.isAfter(thisMonth)) {
return {
order: 3,
type: 'thisMonth',
order: year * 100 + month,
type: 'yearMonth',
month,
year,
mediaItem,
};
}
const month: number = mediaItemReceivedDate.month();
const year: number = mediaItemReceivedDate.year();
return {
order: year * 100 + month,
type: 'yearMonth',
month,
year,
mediaItem,
};
};

@ -146,15 +146,8 @@ export const MessageContent = (props: Props) => {
return null;
}
const {
direction,
text,
timestamp,
serverTimestamp,
previews,
quote,
attachments,
} = contentProps;
const { direction, text, timestamp, serverTimestamp, previews, quote, attachments } =
contentProps;
const hasContentBeforeAttachment = !isEmpty(previews) || !isEmpty(quote) || !isEmpty(text);

@ -21,7 +21,9 @@ type Props = {
const StyledMessageReactBar = styled.div`
background-color: var(--emoji-reaction-bar-background-color);
border-radius: 25px;
box-shadow: 0 2px 16px 0 rgba(0, 0, 0, 0.2), 0 0px 20px 0 rgba(0, 0, 0, 0.19);
box-shadow:
0 2px 16px 0 rgba(0, 0, 0, 0.2),
0 0px 20px 0 rgba(0, 0, 0, 0.19);
padding: 4px 8px;
white-space: nowrap;

@ -32,8 +32,8 @@ export const MessageText = (props: Props) => {
const contents = isDeleted
? window.i18n('messageDeletedPlaceholder')
: direction === 'incoming' && status === 'error'
? window.i18n('incomingError')
: text?.trim();
? window.i18n('incomingError')
: text?.trim();
if (!contents) {
return null;

@ -44,8 +44,8 @@ export const InteractionNotification = (props: PropsForInteractionNotification)
text = isCommunity
? window.i18n('leaveCommunityFailedPleaseTryAgain')
: isGroup
? window.i18n('leaveGroupFailedPleaseTryAgain')
: window.i18n('deleteConversationFailedPleaseTryAgain');
? window.i18n('leaveGroupFailedPleaseTryAgain')
: window.i18n('deleteConversationFailedPleaseTryAgain');
break;
default:
assertUnreachable(

@ -111,8 +111,8 @@ const Contacts = (contacts: Array<string>, count: number) => {
reactors === 1
? 'reactionPopupOne'
: reactors === 2
? 'reactionPopupTwo'
: 'reactionPopupThree',
? 'reactionPopupTwo'
: 'reactionPopupThree',
contacts
)}{' '}
<span>{window.i18n('reactionPopup')}</span>

@ -48,9 +48,7 @@ import { MediaItemType } from '../../../lightbox/LightboxGallery';
import { MediaGallery } from '../../media-gallery/MediaGallery';
import { Header, StyledScrollContainer } from './components';
async function getMediaGalleryProps(
conversationId: string
): Promise<{
async function getMediaGalleryProps(conversationId: string): Promise<{
documents: Array<MediaItemType>;
media: Array<MediaItemType>;
}> {
@ -261,13 +259,13 @@ export const OverlayRightPanelSettings = () => {
const leaveGroupString = isPublic
? window.i18n('leaveCommunity')
: lastMessage?.interactionType === ConversationInteractionType.Leave &&
lastMessage?.interactionStatus === ConversationInteractionStatus.Error
? window.i18n('deleteConversation')
: isKickedFromGroup
? window.i18n('youGotKickedFromGroup')
: left
? window.i18n('youLeftTheGroup')
: window.i18n('leaveGroup');
lastMessage?.interactionStatus === ConversationInteractionStatus.Error
? window.i18n('deleteConversation')
: isKickedFromGroup
? window.i18n('youGotKickedFromGroup')
: left
? window.i18n('youLeftTheGroup')
: window.i18n('leaveGroup');
const showUpdateGroupNameButton = isGroup && weAreAdmin && !commonNoShow; // legacy groups non-admin cannot change groupname anymore
const showAddRemoveModeratorsButton = weAreAdmin && !commonNoShow && isPublic;

@ -42,19 +42,19 @@ export const DisappearingModes = (props: DisappearingModesProps) => {
mode === 'legacy'
? window.i18n('disappearingMessagesModeLegacy')
: mode === 'deleteAfterRead'
? window.i18n('disappearingMessagesModeAfterRead')
: mode === 'deleteAfterSend'
? window.i18n('disappearingMessagesModeAfterSend')
: window.i18n('disappearingMessagesModeOff');
? window.i18n('disappearingMessagesModeAfterRead')
: mode === 'deleteAfterSend'
? window.i18n('disappearingMessagesModeAfterSend')
: window.i18n('disappearingMessagesModeOff');
const subtitleI18n =
mode === 'legacy'
? window.i18n('disappearingMessagesModeLegacySubtitle')
: mode === 'deleteAfterRead'
? window.i18n('disappearingMessagesModeAfterReadSubtitle')
: mode === 'deleteAfterSend'
? window.i18n('disappearingMessagesModeAfterSendSubtitle')
: undefined;
? window.i18n('disappearingMessagesModeAfterReadSubtitle')
: mode === 'deleteAfterSend'
? window.i18n('disappearingMessagesModeAfterSendSubtitle')
: undefined;
return (
<PanelRadioButton

@ -176,8 +176,8 @@ export const OverlayDisappearingMessages = () => {
{singleMode === 'deleteAfterRead'
? window.i18n('disappearingMessagesModeAfterReadSubtitle')
: singleMode === 'deleteAfterSend'
? window.i18n('disappearingMessagesModeAfterSendSubtitle')
: window.i18n('settingAppliesToYourMessages')}
? window.i18n('disappearingMessagesModeAfterSendSubtitle')
: window.i18n('settingAppliesToYourMessages')}
</HeaderSubtitle>
</Header>
<DisappearingModes
@ -198,8 +198,8 @@ export const OverlayDisappearingMessages = () => {
singleMode
? disappearingModeOptions[singleMode]
: modeSelected
? disappearingModeOptions[modeSelected]
: undefined
? disappearingModeOptions[modeSelected]
: undefined
}
/>
</>
@ -223,8 +223,8 @@ export const OverlayDisappearingMessages = () => {
singleMode
? disappearingModeOptions[singleMode]
: modeSelected
? disappearingModeOptions[modeSelected]
: undefined
? disappearingModeOptions[modeSelected]
: undefined
}
dataTestId={'disappear-set-button'}
>

@ -59,9 +59,7 @@ export const ReactClearAllModal = (props: Props): ReactElement => {
}
const { convoId, serverId } = msgProps;
const roomInfos = getConversationController()
.get(convoId)
.toOpenGroupV2();
const roomInfos = getConversationController().get(convoId).toOpenGroupV2();
const handleClose = () => {
dispatch(updateReactClearAllModal(null));

@ -82,10 +82,10 @@ export class SessionPasswordDialog extends React.Component<Props, State> {
passwordAction === 'change'
? 'changePassword'
: passwordAction === 'remove'
? 'removePassword'
: passwordAction === 'enter'
? 'passwordViewTitle'
: 'setPassword';
? 'removePassword'
: passwordAction === 'enter'
? 'passwordViewTitle'
: 'setPassword';
return (
<SessionWrapperModal title={window.i18n(localizedKeyAction)} onClose={this.closeDialog}>
@ -295,11 +295,8 @@ export class SessionPasswordDialog extends React.Component<Props, State> {
private async setPassword() {
const { passwordAction } = this.props;
const {
currentPasswordEntered,
currentPasswordConfirmEntered,
currentPasswordRetypeEntered,
} = this.state;
const { currentPasswordEntered, currentPasswordConfirmEntered, currentPasswordRetypeEntered } =
this.state;
// Trim leading / trailing whitespace for UX
const firstPasswordEntered = (currentPasswordEntered || '').trim();

@ -171,9 +171,11 @@ export const UpdateGroupMembersDialog = (props: Props) => {
const convoProps = useConversationPropsById(conversationId);
const existingMembers = convoProps?.members || [];
const { addTo, removeFrom, uniqueValues: membersToKeepWithUpdate } = useSet<string>(
existingMembers
);
const {
addTo,
removeFrom,
uniqueValues: membersToKeepWithUpdate,
} = useSet<string>(existingMembers);
const dispatch = useDispatch();

@ -18,14 +18,14 @@ const StyledRoundedButton = styled.div<{ isFullScreen: boolean; isMuted: boolean
props.isMuted
? 'var(--call-buttons-background-disabled-color)'
: props.isFullScreen
? 'var(--call-buttons-action-background-color)'
: 'var(--call-buttons-background-color)'};
? 'var(--call-buttons-action-background-color)'
: 'var(--call-buttons-background-color)'};
color: ${props =>
props.isMuted
? 'var(--call-buttons-icon-disabled-color)'
: props.isFullScreen
? 'var(--call-buttons-action-icon-color)'
: 'var(--call-buttons-icon-color)'};
? 'var(--call-buttons-action-icon-color)'
: 'var(--call-buttons-icon-color)'};
${props => props.isFullScreen && 'opacity: 0.4;'}
&:hover {

File diff suppressed because one or more lines are too long

@ -173,12 +173,8 @@ const setupTheme = async () => {
// Do this only if we created a new Session ID, or if we already received the initial configuration message
const triggerSyncIfNeeded = async () => {
const us = UserUtils.getOurPubKeyStrFromCache();
await getConversationController()
.get(us)
.setDidApproveMe(true, true);
await getConversationController()
.get(us)
.setIsApproved(true, true);
await getConversationController().get(us).setDidApproveMe(true, true);
await getConversationController().get(us).setIsApproved(true, true);
const didWeHandleAConfigurationMessageAlready =
(await Data.getItemById(SettingsKey.hasSyncedInitialConfigurationItem))?.value || false;
if (didWeHandleAConfigurationMessageAlready) {

@ -64,15 +64,15 @@ export const InteractionItem = (props: InteractionItemProps) => {
errorText = isCommunity
? window.i18n('leaveCommunityFailed')
: isGroup
? window.i18n('leaveGroupFailed')
: window.i18n('deleteConversationFailed');
? window.i18n('leaveGroupFailed')
: window.i18n('deleteConversationFailed');
text =
interactionStatus === ConversationInteractionStatus.Error
? errorText
: interactionStatus === ConversationInteractionStatus.Start ||
interactionStatus === ConversationInteractionStatus.Loading
? window.i18n('leaving')
: text;
interactionStatus === ConversationInteractionStatus.Loading
? window.i18n('leaving')
: text;
break;
default:
assertUnreachable(

@ -27,8 +27,8 @@ export const UserItem = () => {
const displayName = isMe
? window.i18n('noteToSelf')
: isSearchResultsMode && hasNickname && realName
? `${realName} (${username})`
: username;
? `${realName} (${username})`
: username;
let shouldShowPubkey = false;
if ((!username || username.length === 0) && (!displayName || displayName.length === 0)) {

@ -155,9 +155,9 @@ export const LeaveGroupOrCommunityMenuItem = () => {
{isPublic
? window.i18n('leaveCommunity')
: lastMessage?.interactionType === ConversationInteractionType.Leave &&
lastMessage?.interactionStatus === ConversationInteractionStatus.Error
? window.i18n('deleteConversation')
: window.i18n('leaveGroup')}
lastMessage?.interactionStatus === ConversationInteractionStatus.Error
? window.i18n('deleteConversation')
: window.i18n('leaveGroup')}
</Item>
);
}
@ -546,8 +546,8 @@ export const NotificationForConvoMenuItem = (): JSX.Element | null => {
n === 'all' || !n
? 'notificationForConvo_all'
: n === 'disabled'
? 'notificationForConvo_disabled'
: 'notificationForConvo_mentions_only';
? 'notificationForConvo_disabled'
: 'notificationForConvo_mentions_only';
return { value: n, name: window.i18n(keyToUse) };
});

@ -176,9 +176,8 @@ async function removeConversation(id: string): Promise<void> {
}
async function getAllConversations(): Promise<Array<ConversationModel>> {
const conversationsAttrs = (await channels.getAllConversations()) as Array<
ConversationAttributes
>;
const conversationsAttrs =
(await channels.getAllConversations()) as Array<ConversationAttributes>;
return conversationsAttrs.map(attr => new ConversationModel(attr));
}
@ -547,23 +546,26 @@ async function removeAllMessagesInConversation(conversationId: string): Promise<
await message.cleanup();
}
window.log.info(
`removeAllMessagesInConversation messages.cleanup() ${conversationId} took ${Date.now() -
start}ms`
`removeAllMessagesInConversation messages.cleanup() ${conversationId} took ${
Date.now() - start
}ms`
);
start = Date.now();
// eslint-disable-next-line no-await-in-loop
await channels.removeMessagesByIds(ids);
window.log.info(
`removeAllMessagesInConversation: removeMessagesByIds ${conversationId} took ${Date.now() -
start}ms`
`removeAllMessagesInConversation: removeMessagesByIds ${conversationId} took ${
Date.now() - start
}ms`
);
} while (messages.length);
await channels.removeAllMessagesInConversation(conversationId);
window.log.info(
`removeAllMessagesInConversation: complete time ${conversationId} took ${Date.now() -
startFunction}ms`
`removeAllMessagesInConversation: complete time ${conversationId} took ${
Date.now() - startFunction
}ms`
);
}

@ -274,28 +274,29 @@ export function useIsTyping(conversationId?: string): boolean {
return useConversationPropsById(conversationId)?.isTyping || false;
}
const getMessageExpirationProps = createSelector(getMessagePropsByMessageId, (props):
| PropsForExpiringMessage
| undefined => {
if (!props || isEmpty(props)) {
return undefined;
}
const getMessageExpirationProps = createSelector(
getMessagePropsByMessageId,
(props): PropsForExpiringMessage | undefined => {
if (!props || isEmpty(props)) {
return undefined;
}
const msgProps: PropsForExpiringMessage = {
...pick(props.propsForMessage, [
'convoId',
'direction',
'receivedAt',
'isUnread',
'expirationTimestamp',
'expirationDurationMs',
'isExpired',
]),
messageId: props.propsForMessage.id,
};
return msgProps;
});
const msgProps: PropsForExpiringMessage = {
...pick(props.propsForMessage, [
'convoId',
'direction',
'receivedAt',
'isUnread',
'expirationTimestamp',
'expirationDurationMs',
'isExpired',
]),
messageId: props.propsForMessage.id,
};
return msgProps;
}
);
export function useMessageExpirationPropsById(messageId?: string) {
return useSelector((state: StateType) => {
@ -352,17 +353,18 @@ export function useTimerOptionsByMode(disappearingMessageMode?: string, hasOnlyO
}, [disappearingMessageMode, hasOnlyOneMode]);
}
export function useQuoteAuthorName(
authorId?: string
): { authorName: string | undefined; isMe: boolean } {
export function useQuoteAuthorName(authorId?: string): {
authorName: string | undefined;
isMe: boolean;
} {
const convoProps = useConversationPropsById(authorId);
const isMe = Boolean(authorId && isUsAnySogsFromCache(authorId));
const authorName = isMe
? window.i18n('you')
: convoProps?.nickname || convoProps?.isPrivate
? convoProps?.displayNameInProfile
: undefined;
? convoProps?.displayNameInProfile
: undefined;
return { authorName, isMe };
}
@ -403,12 +405,12 @@ export function useDisappearingMessageSettingText({
expirationMode === 'deleteAfterRead'
? window.i18n('disappearingMessagesModeAfterRead')
: expirationMode === 'deleteAfterSend'
? window.i18n('disappearingMessagesModeAfterSend')
: expirationMode === 'legacy'
? isMe || (isGroup && !isPublic)
? window.i18n('disappearingMessagesModeAfterSend')
: window.i18n('disappearingMessagesModeAfterRead')
: null;
: expirationMode === 'legacy'
? isMe || (isGroup && !isPublic)
? window.i18n('disappearingMessagesModeAfterSend')
: window.i18n('disappearingMessagesModeAfterRead')
: null;
const expireTimerText = isNumber(expireTimer)
? abbreviate

@ -21,9 +21,8 @@ export function useVideoCallEventsListener(uniqueId: string, onSame: boolean) {
const [remoteStream, setRemoteStream] = useState<MediaStream | null>(null);
const [localStreamVideoIsMuted, setLocalStreamVideoIsMuted] = useState(true);
const [ourAudioIsMuted, setOurAudioIsMuted] = useState(false);
const [currentSelectedAudioOutput, setCurrentSelectedAudioOutput] = useState(
DEVICE_DISABLED_DEVICE_ID
);
const [currentSelectedAudioOutput, setCurrentSelectedAudioOutput] =
useState(DEVICE_DISABLED_DEVICE_ID);
const [remoteStreamVideoIsMuted, setRemoteStreamVideoIsMuted] = useState(true);
const mountedStateFunc = useMountedState();
const mountedState = mountedStateFunc();

@ -556,9 +556,8 @@ export async function uploadOurAvatar(newAvatarDecrypted?: ArrayBuffer) {
} else {
// this is a reupload. no need to generate a new profileKey
const ourConvoProfileKey =
getConversationController()
.get(UserUtils.getOurPubKeyStrFromCache())
?.get('profileKey') || null;
getConversationController().get(UserUtils.getOurPubKeyStrFromCache())?.get('profileKey') ||
null;
profileKey = ourConvoProfileKey ? fromHexToArray(ourConvoProfileKey) : null;
if (!profileKey) {

@ -862,10 +862,13 @@ async function requestShutdown() {
// exits the app before we've set everything up in preload() (so the browser isn't
// yet listening for these events), or if there are a whole lot of stacked-up tasks.
// Note: two minutes is also our timeout for SQL tasks in data.ts in the browser.
setTimeout(() => {
console.log('requestShutdown: Response never received; forcing shutdown.');
resolve(undefined);
}, 2 * 60 * 1000);
setTimeout(
() => {
console.log('requestShutdown: Response never received; forcing shutdown.');
resolve(undefined);
},
2 * 60 * 1000
);
});
try {

@ -2104,8 +2104,8 @@ export class ConversationModel extends Backbone.Model<ConversationAttributes> {
const interactionNotification = lastMessageModel.getInteractionNotification();
const lastMessageInteractionType = interactionNotification?.interactionType;
const lastMessageInteractionStatus = lastMessageModel.getInteractionNotification()
?.interactionStatus;
const lastMessageInteractionStatus =
lastMessageModel.getInteractionNotification()?.interactionStatus;
const lastMessageStatus = lastMessageModel.getMessagePropStatus() || undefined;
const lastMessageNotificationText = lastMessageModel.getNotificationText() || undefined;
// we just want to set the `status` to `undefined` if there are no `lastMessageNotificationText`
@ -2473,10 +2473,10 @@ export class ConversationModel extends Backbone.Model<ConversationAttributes> {
mode === 'deleteAfterRead'
? ours === 'deleteAfterRead'
: mode === 'deleteAfterSend'
? ours === 'deleteAfterSend'
: mode === 'off'
? ours === 'off'
: false;
? ours === 'deleteAfterSend'
: mode === 'off'
? ours === 'off'
: false;
return success;
}

@ -39,7 +39,7 @@ export function isDirectConversation(conversationType: ConversationTypeEnum) {
* mentions_only: trigger a notification only on mentions of ourself
*/
export const ConversationNotificationSetting = ['all', 'disabled', 'mentions_only'] as const;
export type ConversationNotificationSettingType = typeof ConversationNotificationSetting[number];
export type ConversationNotificationSettingType = (typeof ConversationNotificationSetting)[number];
/**
* Some fields are retrieved from the database as a select, but should not be saved in a commit()

@ -273,9 +273,8 @@ export class MessageModel extends Backbone.Model<MessageAttributes> {
(pubkeysInDesc || []).forEach((pubkeyWithAt: string) => {
const pubkey = pubkeyWithAt.slice(1);
const isUS = isUsAnySogsFromCache(pubkey);
const displayName = getConversationController().getContactProfileNameOrShortenedPubKey(
pubkey
);
const displayName =
getConversationController().getContactProfileNameOrShortenedPubKey(pubkey);
if (isUS) {
description = description?.replace(pubkeyWithAt, `@${window.i18n('you')}`);
} else if (displayName && displayName.length) {
@ -742,9 +741,8 @@ export class MessageModel extends Backbone.Model<MessageAttributes> {
const quoteWithData = await loadQuoteData(this.get('quote'));
const previewWithData = await loadPreviewData(this.get('preview'));
const { hasAttachments, hasVisualMediaAttachments, hasFileAttachments } = getAttachmentMetadata(
this
);
const { hasAttachments, hasVisualMediaAttachments, hasFileAttachments } =
getAttachmentMetadata(this);
this.set({ hasAttachments, hasVisualMediaAttachments, hasFileAttachments });
await this.commit();
@ -795,8 +793,9 @@ export class MessageModel extends Backbone.Model<MessageAttributes> {
}
window.log.info(
`Upload of message data for message ${this.idForLogging()} is finished in ${Date.now() -
start}ms.`
`Upload of message data for message ${this.idForLogging()} is finished in ${
Date.now() - start
}ms.`
);
return {
body,
@ -1238,18 +1237,18 @@ export class MessageModel extends Backbone.Model<MessageAttributes> {
const left: Array<string> | undefined = Array.isArray(groupUpdate.left)
? groupUpdate.left
: groupUpdate.left
? [groupUpdate.left]
: undefined;
? [groupUpdate.left]
: undefined;
const kicked: Array<string> | undefined = Array.isArray(groupUpdate.kicked)
? groupUpdate.kicked
: groupUpdate.kicked
? [groupUpdate.kicked]
: undefined;
? [groupUpdate.kicked]
: undefined;
const joined: Array<string> | undefined = Array.isArray(groupUpdate.joined)
? groupUpdate.joined
: groupUpdate.joined
? [groupUpdate.joined]
: undefined;
? [groupUpdate.joined]
: undefined;
const forcedArrayUpdate: MessageGroupUpdate = {};
@ -1381,8 +1380,8 @@ export class MessageModel extends Backbone.Model<MessageAttributes> {
return isCommunity
? window.i18n('leaveCommunityFailed')
: isGroup
? window.i18n('leaveGroupFailed')
: window.i18n('deleteConversationFailed');
? window.i18n('leaveGroupFailed')
: window.i18n('deleteConversationFailed');
default:
assertUnreachable(
interactionType,

@ -17,14 +17,8 @@ export const createTemplate = (
throw new TypeError('`options.platform` must be a string');
}
const {
openReleaseNotes,
openSupportPage,
platform,
showAbout,
showDebugLog,
showWindow,
} = options;
const { openReleaseNotes, openSupportPage, platform, showAbout, showDebugLog, showWindow } =
options;
const template = [
{

@ -309,14 +309,8 @@ function insertLegacyGroupIntoWrapper(
) {
checkTargetMigration(version, targetVersion);
const {
priority,
id,
groupAdmins,
members,
displayNameInProfile,
lastJoinedTimestamp,
} = legacyGroup;
const { priority, id, groupAdmins, members, displayNameInProfile, lastJoinedTimestamp } =
legacyGroup;
const latestEncryptionKeyPairHex = sqlNode.getLatestClosedGroupEncryptionKeyPair(
legacyGroup.id,

@ -351,9 +351,7 @@ function getById(table: string, id: string, instance?: BetterSqlite3.Database) {
function removeById(table: string, id: string) {
if (!Array.isArray(id)) {
assertGlobalInstance()
.prepare(`DELETE FROM ${table} WHERE id = $id;`)
.run({ id });
assertGlobalInstance().prepare(`DELETE FROM ${table} WHERE id = $id;`).run({ id });
return;
}
@ -401,9 +399,7 @@ function updateSwarmNodesForPubkey(pubkey: string, snodeEdKeys: Array<string>) {
}
function getConversationCount() {
const row = assertGlobalInstance()
.prepare(`SELECT count(*) from ${CONVERSATIONS_TABLE};`)
.get();
const row = assertGlobalInstance().prepare(`SELECT count(*) from ${CONVERSATIONS_TABLE};`).get();
if (!row) {
throw new Error(`getConversationCount: Unable to get count of ${CONVERSATIONS_TABLE}`);
}
@ -530,11 +526,9 @@ function fetchConvoMemoryDetails(convoId: string): SaveConversationReturn {
function removeConversation(id: string | Array<string>) {
if (!Array.isArray(id)) {
assertGlobalInstance()
.prepare(`DELETE FROM ${CONVERSATIONS_TABLE} WHERE id = $id;`)
.run({
id,
});
assertGlobalInstance().prepare(`DELETE FROM ${CONVERSATIONS_TABLE} WHERE id = $id;`).run({
id,
});
return;
}
@ -778,9 +772,7 @@ function searchMessagesInConversation(query: string, conversationId: string, lim
}
function getMessageCount() {
const row = assertGlobalInstance()
.prepare(`SELECT count(*) from ${MESSAGES_TABLE};`)
.get();
const row = assertGlobalInstance().prepare(`SELECT count(*) from ${MESSAGES_TABLE};`).get();
if (!row) {
throw new Error(`getMessageCount: Unable to get count of ${MESSAGES_TABLE}`);
@ -953,19 +945,15 @@ function saveSeenMessageHash(data: any) {
}
function cleanLastHashes() {
assertGlobalInstance()
.prepare(`DELETE FROM ${LAST_HASHES_TABLE} WHERE expiresAt <= $now;`)
.run({
now: Date.now(),
});
assertGlobalInstance().prepare(`DELETE FROM ${LAST_HASHES_TABLE} WHERE expiresAt <= $now;`).run({
now: Date.now(),
});
}
function cleanSeenMessages() {
assertGlobalInstance()
.prepare('DELETE FROM seenMessages WHERE expiresAt <= $now;')
.run({
now: Date.now(),
});
assertGlobalInstance().prepare('DELETE FROM seenMessages WHERE expiresAt <= $now;').run({
now: Date.now(),
});
}
function saveMessages(arrayOfMessages: Array<MessageAttributes>) {
@ -1738,19 +1726,15 @@ const unprocessed: UnprocessedDataNode = {
},
getUnprocessedById: (id: string) => {
const row = assertGlobalInstance()
.prepare('SELECT * FROM unprocessed WHERE id = $id;')
.get({
id,
});
const row = assertGlobalInstance().prepare('SELECT * FROM unprocessed WHERE id = $id;').get({
id,
});
return row;
},
getUnprocessedCount: () => {
const row = assertGlobalInstance()
.prepare('SELECT count(*) from unprocessed;')
.get();
const row = assertGlobalInstance().prepare('SELECT count(*) from unprocessed;').get();
if (!row) {
throw new Error('getMessageCount: Unable to get count of unprocessed');
@ -1772,15 +1756,11 @@ const unprocessed: UnprocessedDataNode = {
console.error('removeUnprocessed only supports single ids at a time');
throw new Error('removeUnprocessed only supports single ids at a time');
}
assertGlobalInstance()
.prepare('DELETE FROM unprocessed WHERE id = $id;')
.run({ id });
assertGlobalInstance().prepare('DELETE FROM unprocessed WHERE id = $id;').run({ id });
},
removeAllUnprocessed: () => {
assertGlobalInstance()
.prepare('DELETE FROM unprocessed;')
.run();
assertGlobalInstance().prepare('DELETE FROM unprocessed;').run();
},
};
@ -1870,9 +1850,7 @@ function removeAll() {
}
function removeAllConversations() {
assertGlobalInstance()
.prepare(`DELETE FROM ${CONVERSATIONS_TABLE};`)
.run();
assertGlobalInstance().prepare(`DELETE FROM ${CONVERSATIONS_TABLE};`).run();
}
function getMessagesWithVisualMediaAttachments(conversationId: string, limit?: number) {
@ -2220,9 +2198,7 @@ function removeV2OpenGroupRoom(conversationId: string) {
function getEntriesCountInTable(tbl: string) {
try {
const row = assertGlobalInstance()
.prepare(`SELECT count(*) from ${tbl};`)
.get();
const row = assertGlobalInstance().prepare(`SELECT count(*) from ${tbl};`).get();
return row['count(*)'];
} catch (e) {
console.error(e);
@ -2387,8 +2363,9 @@ function cleanUpOldOpengroupsOnStart() {
const messagesInConvoAfter = getMessagesCountByConversation(convoId);
console.info(
`Cleaning ${countToRemove} messages older than 6 months in public convo: ${convoId} took ${Date.now() -
start}ms. Old message count: ${messagesInConvoBefore}, new message count: ${messagesInConvoAfter}`
`Cleaning ${countToRemove} messages older than 6 months in public convo: ${convoId} took ${
Date.now() - start
}ms. Old message count: ${messagesInConvoBefore}, new message count: ${messagesInConvoAfter}`
);
// no need to update the `unreadCount` during the migration anymore.

@ -318,8 +318,8 @@ export async function handleNewClosedGroup(
expireTimer === 0
? 'off'
: ReleasedFeatures.isDisappearMessageV2FeatureReleasedCached()
? 'deleteAfterSend'
: 'legacy',
? 'deleteAfterSend'
: 'legacy',
providedExpireTimer: expireTimer,
providedSource: sender,
receivedAt: GetNetworkTime.getNowWithNetworkOffset(),

@ -549,7 +549,8 @@ export async function innerHandleSwarmContentMessage({
await handleDataExtractionNotification({
envelope,
dataExtractionNotification: content.dataExtractionNotification as SignalService.DataExtractionNotification,
dataExtractionNotification:
content.dataExtractionNotification as SignalService.DataExtractionNotification,
expireUpdate,
messageHash,
});

@ -68,11 +68,7 @@ const handleOpenGroupMessage = async (
return;
}
if (
!getConversationController()
.get(conversationId)
?.isOpenGroupV2()
) {
if (!getConversationController().get(conversationId)?.isOpenGroupV2()) {
window?.log?.error('Received a message for an unknown convo or not an v2. Skipping');
return;
}

@ -153,8 +153,9 @@ function handleLinkPreviews(messageBody: string, messagePreview: any, message: M
);
if (preview.length < incomingPreview.length) {
window?.log?.info(
`${message.idForLogging()}: Eliminated ${preview.length -
incomingPreview.length} previews with invalid urls'`
`${message.idForLogging()}: Eliminated ${
preview.length - incomingPreview.length
} previews with invalid urls'`
);
}
@ -361,12 +362,9 @@ export async function handleMessageJob(
messageHash: string
) {
window?.log?.info(
`Starting handleMessageJob for message ${messageModel.idForLogging()}, ${messageModel.get(
'serverTimestamp'
) ||
messageModel.get(
'timestamp'
)} in conversation ${conversation.idForLogging()}, messageHash:${messageHash}`
`Starting handleMessageJob for message ${messageModel.idForLogging()}, ${
messageModel.get('serverTimestamp') || messageModel.get('timestamp')
} in conversation ${conversation.idForLogging()}, messageHash:${messageHash}`
);
const sendingDeviceConversation = await getConversationController().getOrCreateAndWait(

@ -238,11 +238,7 @@ export function getUsBlindedInThatServer(convo: ConversationModel | string): str
}
const convoId = isString(convo) ? convo : convo.id;
if (
!getConversationController()
.get(convoId)
?.isOpenGroupV2()
) {
if (!getConversationController().get(convoId)?.isOpenGroupV2()) {
return undefined;
}
const room = OpenGroupData.getV2OpenGroupRoom(isString(convo) ? convo : convo.id);

@ -259,9 +259,8 @@ const handleMessagesResponseV4 = async (
subrequestOption.messages.roomId
);
const messagesWithValidSignature = await filterOutMessagesInvalidSignature(
messagesWithoutDeleted
);
const messagesWithValidSignature =
await filterOutMessagesInvalidSignature(messagesWithoutDeleted);
// we do a first check with blinded ids. Looking to filter out messages we already received from that blinded id.
const messagesFilteredBlindedIds = await filterDuplicatesFromDbAndIncomingV4(
messagesWithValidSignature
@ -427,8 +426,8 @@ async function handleInboxOutboxMessages(
unblindedIDOrBlinded,
ConversationTypeEnum.PRIVATE
);
const serverConversationId = OpenGroupData.getV2OpenGroupRoomsByServerUrl(serverUrl)?.[0]
.conversationId;
const serverConversationId =
OpenGroupData.getV2OpenGroupRoomsByServerUrl(serverUrl)?.[0].conversationId;
if (!serverConversationId) {
throw new Error('serverConversationId needs to exist');
}

@ -457,8 +457,9 @@ export async function expireMessagesOnSnode(
} catch (e) {
const snodeStr = snode ? `${snode.ip}:${snode.port}` : 'null';
window?.log?.warn(
`[expireMessageOnSnode] ${e.code || ''}${e.message ||
e} by ${ourPubKey} via snode:${snodeStr}`
`[expireMessageOnSnode] ${e.code || ''}${
e.message || e
} by ${ourPubKey} via snode:${snodeStr}`
);
throw e;
}

@ -191,8 +191,9 @@ export async function getExpiriesFromSnode({ messageHashes }: GetExpiriesFromSno
} catch (e) {
const snodeStr = snode ? `${snode.ip}:${snode.port}` : 'null';
window?.log?.warn(
`[getExpiriesFromSnode] ${e.code ? `${e.code} ` : ''}${e.message ||
e} by ${ourPubKey} for ${messageHashes} via snode:${snodeStr}`
`[getExpiriesFromSnode] ${e.code ? `${e.code} ` : ''}${
e.message || e
} by ${ourPubKey} for ${messageHashes} via snode:${snodeStr}`
);
throw e;
}

@ -86,9 +86,11 @@ async function encryptOnionV4RequestForPubkey(
) {
const plaintext = encodeV4Request(requestInfo);
return callUtilsWorker('encryptForPubkey', pubKeyX25519hex, plaintext) as Promise<
DestinationContext
>;
return callUtilsWorker(
'encryptForPubkey',
pubKeyX25519hex,
plaintext
) as Promise<DestinationContext>;
}
// Returns the actual ciphertext, symmetric key that will be used
// for decryption, and an ephemeral_key to send to the next hop
@ -98,9 +100,11 @@ async function encryptForPubKey(
): Promise<DestinationContext> {
const plaintext = new TextEncoder().encode(JSON.stringify(requestInfo));
return callUtilsWorker('encryptForPubkey', pubKeyX25519hex, plaintext) as Promise<
DestinationContext
>;
return callUtilsWorker(
'encryptForPubkey',
pubKeyX25519hex,
plaintext
) as Promise<DestinationContext>;
}
export type DestinationRelayV2 = {

@ -180,9 +180,7 @@ export class SwarmPolling {
const diff = now - group.lastPolledTimestamp;
const loggingId =
getConversationController()
.get(group.pubkey.key)
?.idForLogging() || group.pubkey.key;
getConversationController().get(group.pubkey.key)?.idForLogging() || group.pubkey.key;
if (diff >= convoPollingTimeout) {
window?.log?.debug(
`Polling for ${loggingId}; timeout: ${convoPollingTimeout}; diff: ${diff} `
@ -355,9 +353,8 @@ export class SwarmPolling {
})
);
const allDecryptedConfigMessages: Array<IncomingMessage<
SignalService.ISharedConfigMessage
>> = [];
const allDecryptedConfigMessages: Array<IncomingMessage<SignalService.ISharedConfigMessage>> =
[];
for (let index = 0; index < extractedUserConfigMessage.length; index++) {
const userConfigMessage = extractedUserConfigMessage[index];

@ -17,10 +17,7 @@ export async function getSodiumRenderer(): Promise<LibSodiumWrappers> {
}
export const sha256 = (s: string) => {
return crypto
.createHash('sha256')
.update(s)
.digest('base64');
return crypto.createHash('sha256').update(s).digest('base64');
};
export const concatUInt8Array = (...args: Array<Uint8Array>): Uint8Array => {

@ -59,9 +59,7 @@ async function destroyMessagesAndUpdateRedux(
// trigger a refresh the last message for all those uniq conversation
conversationWithChanges.forEach(convoIdToUpdate => {
getConversationController()
.get(convoIdToUpdate)
?.updateLastMessage();
getConversationController().get(convoIdToUpdate)?.updateLastMessage();
});
}
@ -91,12 +89,8 @@ async function destroyExpiredMessages() {
window.log.info('destroyExpiredMessages: convosToRefresh:', convosToRefresh);
await Promise.all(
convosToRefresh.map(async c => {
getConversationController()
.get(c)
?.updateLastMessage();
return getConversationController()
.get(c)
?.refreshInMemoryDetails();
getConversationController().get(c)?.updateLastMessage();
return getConversationController().get(c)?.refreshInMemoryDetails();
})
);
} catch (error) {
@ -278,9 +272,10 @@ function changeToDisappearingMessageType(
* This should only be used for DataExtractionNotification and CallMessages (the ones saved to the DB) currently.
* Note: this can only be called for private conversations, excluding ourselves as it throws otherwise (this wouldn't be right)
* */
function forcedDeleteAfterReadMsgSetting(
convo: ConversationModel
): { expirationType: Exclude<DisappearingMessageType, 'deleteAfterSend'>; expireTimer: number } {
function forcedDeleteAfterReadMsgSetting(convo: ConversationModel): {
expirationType: Exclude<DisappearingMessageType, 'deleteAfterSend'>;
expireTimer: number;
} {
if (convo.isMe() || !convo.isPrivate()) {
throw new Error(
'forcedDeleteAfterReadMsgSetting can only be called with a private chat (excluding ourselves)'
@ -304,9 +299,10 @@ function forcedDeleteAfterReadMsgSetting(
* This should only be used for the outgoing CallMessages that we keep locally only (not synced, just the "you started a call" notification)
* Note: this can only be called for private conversations, excluding ourselves as it throws otherwise (this wouldn't be right)
* */
function forcedDeleteAfterSendMsgSetting(
convo: ConversationModel
): { expirationType: Exclude<DisappearingMessageType, 'deleteAfterRead'>; expireTimer: number } {
function forcedDeleteAfterSendMsgSetting(convo: ConversationModel): {
expirationType: Exclude<DisappearingMessageType, 'deleteAfterRead'>;
expireTimer: number;
} {
if (convo.isMe() || !convo.isPrivate()) {
throw new Error(
'forcedDeleteAfterSendMsgSetting can only be called with a private chat (excluding ourselves)'
@ -359,7 +355,8 @@ async function checkForExpireUpdateInContentMessage(
): Promise<DisappearingMessageUpdate | undefined> {
const dataMessage = content.dataMessage as SignalService.DataMessage | undefined;
// We will only support legacy disappearing messages for a short period before disappearing messages v2 is unlocked
const isDisappearingMessagesV2Released = await ReleasedFeatures.checkIsDisappearMessageV2FeatureReleased();
const isDisappearingMessagesV2Released =
await ReleasedFeatures.checkIsDisappearMessageV2FeatureReleased();
const couldBeLegacyContentMessage = couldBeLegacyDisappearingMessageContent(content);
const isLegacyDataMessage =
@ -559,9 +556,9 @@ function getMessageReadyToDisappear(
if (msgExpirationWasAlreadyUpdated) {
const expirationStartTimestamp = messageExpirationFromRetrieve - expireTimer * 1000;
window.log.debug(
`incoming DaR message already read by another device, forcing readAt ${(Date.now() -
expirationStartTimestamp) /
1000}s ago, so with ${(messageExpirationFromRetrieve - Date.now()) / 1000}s left`
`incoming DaR message already read by another device, forcing readAt ${
(Date.now() - expirationStartTimestamp) / 1000
}s ago, so with ${(messageExpirationFromRetrieve - Date.now()) / 1000}s left`
);
messageModel.set({
expirationStartTimestamp,

@ -1,5 +1,5 @@
// NOTE this must match Content.ExpirationType in the protobuf
export type DisappearingMessageType = typeof DisappearingMessageMode[number];
export type DisappearingMessageType = (typeof DisappearingMessageMode)[number];
export const DisappearingMessageMode = ['unknown', 'deleteAfterRead', 'deleteAfterSend'] as const;
export type DisappearAfterSendOnly = Exclude<DisappearingMessageType, 'deleteAfterRead'>;
@ -11,7 +11,8 @@ export const DisappearingMessageConversationModes = [
// TODO legacy messages support will be removed in a future release
'legacy',
] as const;
export type DisappearingMessageConversationModeType = typeof DisappearingMessageConversationModes[number];
export type DisappearingMessageConversationModeType =
(typeof DisappearingMessageConversationModes)[number];
// TODO legacy messages support will be removed in a future release
// expirationType will no longer have an undefined option

@ -30,10 +30,10 @@ export class ExpirableMessage extends ContentMessage {
this.expirationType === 'deleteAfterSend'
? SignalService.Content.ExpirationType.DELETE_AFTER_SEND
: this.expirationType === 'deleteAfterRead'
? SignalService.Content.ExpirationType.DELETE_AFTER_READ
: this.expirationType === 'unknown'
? SignalService.Content.ExpirationType.UNKNOWN
: undefined,
? SignalService.Content.ExpirationType.DELETE_AFTER_READ
: this.expirationType === 'unknown'
? SignalService.Content.ExpirationType.UNKNOWN
: undefined,
expirationTimer: this.expireTimer && this.expireTimer > -1 ? this.expireTimer : undefined,
});
}

@ -54,9 +54,8 @@ export const sendDataExtractionNotification = async (
window.log.warn('Not sending saving attachment notification for', attachmentSender);
return;
}
const { expirationType, expireTimer } = DisappearingMessages.forcedDeleteAfterReadMsgSetting(
convo
);
const { expirationType, expireTimer } =
DisappearingMessages.forcedDeleteAfterReadMsgSetting(convo);
// DataExtractionNotification are expiring with a forced DaR timer if a DaS is set.
// It's because we want the DataExtractionNotification to stay in the swarm as much as possible,
// but also expire on the recipient's side (and synced) once read.

@ -6,9 +6,7 @@ export interface ClosedGroupEncryptionPairMessageParams extends ClosedGroupMessa
}
export class ClosedGroupEncryptionPairMessage extends ClosedGroupMessage {
private readonly encryptedKeyPairs: Array<
SignalService.DataMessage.ClosedGroupControlMessage.KeyPairWrapper
>;
private readonly encryptedKeyPairs: Array<SignalService.DataMessage.ClosedGroupControlMessage.KeyPairWrapper>;
constructor(params: ClosedGroupEncryptionPairMessageParams) {
super(params);

@ -43,7 +43,8 @@ export abstract class ClosedGroupMessage extends ExpirableMessage {
public dataProto(): SignalService.DataMessage {
const dataMessage = super.dataProto();
dataMessage.closedGroupControlMessage = new SignalService.DataMessage.ClosedGroupControlMessage();
dataMessage.closedGroupControlMessage =
new SignalService.DataMessage.ClosedGroupControlMessage();
return dataMessage;
}

@ -54,7 +54,8 @@ export class ClosedGroupNewMessage extends ClosedGroupMessage {
public dataProto(): SignalService.DataMessage {
const dataMessage = new SignalService.DataMessage();
dataMessage.closedGroupControlMessage = new SignalService.DataMessage.ClosedGroupControlMessage();
dataMessage.closedGroupControlMessage =
new SignalService.DataMessage.ClosedGroupControlMessage();
dataMessage.closedGroupControlMessage.type =
SignalService.DataMessage.ClosedGroupControlMessage.Type.NEW;

@ -375,9 +375,9 @@ export async function selectGuardNodes(): Promise<Array<Snode>> {
// Test all three nodes at once, wait for all to resolve or reject
// eslint-disable-next-line no-await-in-loop
const idxOk = (
await Promise.allSettled(candidateNodes.map(OnionPaths.testGuardNode))
).flatMap(p => (p.status === 'fulfilled' ? p.value : null));
const idxOk = (await Promise.allSettled(candidateNodes.map(OnionPaths.testGuardNode))).flatMap(
p => (p.status === 'fulfilled' ? p.value : null)
);
const goodNodes = _.zip(idxOk, candidateNodes)
.filter(x => x[0])

@ -285,11 +285,7 @@ async function sendMessagesDataToSnode(
}
function encryptionBasedOnConversation(destination: PubKey) {
if (
getConversationController()
.get(destination.key)
?.isClosedGroup()
) {
if (getConversationController().get(destination.key)?.isClosedGroup()) {
return SignalService.Envelope.Type.CLOSED_GROUP_MESSAGE;
}
return SignalService.Envelope.Type.SESSION_MESSAGE;
@ -326,10 +322,8 @@ async function encryptMessageAndWrap(
ttl,
} = params;
const {
overRiddenTimestampBuffer,
networkTimestamp,
} = overwriteOutgoingTimestampWithNetworkTimestamp({ plainTextBuffer });
const { overRiddenTimestampBuffer, networkTimestamp } =
overwriteOutgoingTimestampWithNetworkTimestamp({ plainTextBuffer });
const recipient = PubKey.cast(destination);
const { envelopeType, cipherText } = await MessageEncrypter.encrypt(
@ -349,11 +343,9 @@ async function encryptMessageAndWrap(
const overridenNamespace = !isNil(namespace)
? namespace
: getConversationController()
.get(recipient.key)
?.isClosedGroup()
? SnodeNamespaces.ClosedGroupMessage
: SnodeNamespaces.UserMessages;
: getConversationController().get(recipient.key)?.isClosedGroup()
? SnodeNamespaces.ClosedGroupMessage
: SnodeNamespaces.UserMessages;
return {
data64,

@ -216,11 +216,8 @@ async function _runJob(job: any) {
// and tries to update the same message.
found = await Data.getMessageById(messageId);
if (found) {
const {
hasAttachments,
hasVisualMediaAttachments,
hasFileAttachments,
} = getAttachmentMetadata(found);
const { hasAttachments, hasVisualMediaAttachments, hasFileAttachments } =
getAttachmentMetadata(found);
found.set({ hasAttachments, hasVisualMediaAttachments, hasFileAttachments });
}

@ -425,9 +425,8 @@ async function createOfferAndSendIt(recipient: string, msgIdentifier: string | n
);
// Note: we are forcing callMessages to be DaR if DaS, using the same timer
const { expirationType, expireTimer } = DisappearingMessages.forcedDeleteAfterReadMsgSetting(
convo
);
const { expirationType, expireTimer } =
DisappearingMessages.forcedDeleteAfterReadMsgSetting(convo);
const offerMessage = new CallMessage({
identifier: msgIdentifier || undefined,
@ -946,9 +945,8 @@ export async function rejectCallAlreadyAnotherCall(fromSender: string, forcedUUI
rejectedCallUUIDS.add(forcedUUID);
// Note: we are forcing callMessages to be DaR if DaS, using the same timer
const { expirationType, expireTimer } = DisappearingMessages.forcedDeleteAfterReadMsgSetting(
convo
);
const { expirationType, expireTimer } =
DisappearingMessages.forcedDeleteAfterReadMsgSetting(convo);
const rejectCallMessage = new CallMessage({
type: SignalService.CallMessage.Type.END_CALL,
@ -980,9 +978,8 @@ export async function USER_rejectIncomingCallRequest(fromSender: string) {
throw new Error('USER_rejectIncomingCallRequest not existing convo');
}
// Note: we are forcing callMessages to be DaR if DaS, using the same timer
const { expirationType, expireTimer } = DisappearingMessages.forcedDeleteAfterReadMsgSetting(
convo
);
const { expirationType, expireTimer } =
DisappearingMessages.forcedDeleteAfterReadMsgSetting(convo);
const endCallMessage = new CallMessage({
type: SignalService.CallMessage.Type.END_CALL,
@ -1032,9 +1029,8 @@ export async function USER_hangup(fromSender: string) {
throw new Error('USER_hangup not existing convo');
}
// Note: we are forcing callMessages to be DaR if DaS, using the same timer
const { expirationType, expireTimer } = DisappearingMessages.forcedDeleteAfterReadMsgSetting(
convo
);
const { expirationType, expireTimer } =
DisappearingMessages.forcedDeleteAfterReadMsgSetting(convo);
rejectedCallUUIDS.add(currentCallUUID);
const endCallMessage = new CallMessage({
type: SignalService.CallMessage.Type.END_CALL,
@ -1117,9 +1113,8 @@ async function buildAnswerAndSendIt(sender: string, msgIdentifier: string | null
throw new Error('buildAnswerAndSendIt not existing convo');
}
// Note: we are forcing callMessages to be DaR if DaS, using the same timer
const { expirationType, expireTimer } = DisappearingMessages.forcedDeleteAfterReadMsgSetting(
convo
);
const { expirationType, expireTimer } =
DisappearingMessages.forcedDeleteAfterReadMsgSetting(convo);
const answerSdp = answer.sdp;
const callAnswerMessage = new CallMessage({
identifier: msgIdentifier || undefined,
@ -1157,9 +1152,7 @@ function getCachedMessageFromCallMessage(
}
async function isUserApprovedOrWeSentAMessage(user: string) {
const isApproved = getConversationController()
.get(user)
?.isApproved();
const isApproved = getConversationController().get(user)?.isApproved();
if (isApproved) {
return true;
@ -1524,10 +1517,7 @@ function pushCallMessageToCallCache(
callMessage: CachedCallMessageType
) {
createCallCacheForPubkeyAndUUID(sender, uuid);
callCache
.get(sender)
?.get(uuid)
?.push(callMessage);
callCache.get(sender)?.get(uuid)?.push(callMessage);
}
/**

@ -16,13 +16,13 @@ export function persistedJobFromData<T extends TypeOfPersistedData>(
switch (data.jobType) {
case 'ConfigurationSyncJobType':
return (new ConfigurationSync.ConfigurationSyncJob(data) as unknown) as PersistedJob<T>;
return new ConfigurationSync.ConfigurationSyncJob(data) as unknown as PersistedJob<T>;
case 'AvatarDownloadJobType':
return (new AvatarDownload.AvatarDownloadJob(data) as unknown) as PersistedJob<T>;
return new AvatarDownload.AvatarDownloadJob(data) as unknown as PersistedJob<T>;
case 'FakeSleepForJobType':
return (new FakeSleepForJob(data) as unknown) as PersistedJob<T>;
return new FakeSleepForJob(data) as unknown as PersistedJob<T>;
case 'FakeSleepForJobMultiType':
return (new FakeSleepForMultiJob(data) as unknown) as PersistedJob<T>;
return new FakeSleepForMultiJob(data) as unknown as PersistedJob<T>;
default:
window?.log?.error('unknown persisted job type:', (data as any).jobType);
return null;

@ -235,13 +235,16 @@ export class PersistedJobRunner<T extends TypeOfPersistedData> {
global.clearTimeout(this.nextJobStartTimer);
}
// plan a timer to wakeup when that timer is reached.
this.nextJobStartTimer = global.setTimeout(() => {
if (this.nextJobStartTimer) {
global.clearTimeout(this.nextJobStartTimer);
this.nextJobStartTimer = null;
}
void this.runNextJob();
}, Math.max(nextJob.persistedData.nextAttemptTimestamp - Date.now(), 1));
this.nextJobStartTimer = global.setTimeout(
() => {
if (this.nextJobStartTimer) {
global.clearTimeout(this.nextJobStartTimer);
this.nextJobStartTimer = null;
}
void this.runNextJob();
},
Math.max(nextJob.persistedData.nextAttemptTimestamp - Date.now(), 1)
);
return 'job_deferred';
}

@ -101,15 +101,11 @@ async function refreshMappedValue(id: string, duringAppStart = false) {
if (fromWrapper) {
setMappedValue(fromWrapper);
if (!duringAppStart) {
getConversationController()
.get(id)
?.triggerUIRefresh();
getConversationController().get(id)?.triggerUIRefresh();
}
} else if (mappedContactWrapperValues.delete(id)) {
if (!duringAppStart) {
getConversationController()
.get(id)
?.triggerUIRefresh();
getConversationController().get(id)?.triggerUIRefresh();
}
}
}

@ -51,8 +51,8 @@ function getConvoType(convo: ConversationModel): ConvoVolatileType {
SessionUtilUserProfile.isUserProfileToStoreInWrapper(convo.id)
? '1o1'
: SessionUtilUserGroups.isCommunityToStoreInWrapper(convo)
? 'Community'
: 'LegacyGroup';
? 'Community'
: 'LegacyGroup';
return convoType;
}
@ -180,9 +180,8 @@ async function refreshConvoVolatileCached(
refreshed = true;
break;
case 'LegacyGroup':
const fromWrapperLegacyGroup = await ConvoInfoVolatileWrapperActions.getLegacyGroup(
convoId
);
const fromWrapperLegacyGroup =
await ConvoInfoVolatileWrapperActions.getLegacyGroup(convoId);
if (fromWrapperLegacyGroup) {
mappedLegacyGroupWrapperValues.set(convoId, fromWrapperLegacyGroup);
}
@ -201,9 +200,7 @@ async function refreshConvoVolatileCached(
}
if (refreshed && !duringAppStart) {
getConversationController()
.get(convoId)
?.triggerUIRefresh();
getConversationController().get(convoId)?.triggerUIRefresh();
}
} catch (e) {
window.log.info(`refreshMappedValue for volatile convoID: ${convoId}`, e.message);

@ -190,9 +190,9 @@ const getValidClosedGroups = async (convos: Array<ConversationModel>) => {
})
);
const onlyValidClosedGroup = closedGroups.filter(m => m !== null) as Array<
ConfigurationMessageClosedGroup
>;
const onlyValidClosedGroup = closedGroups.filter(
m => m !== null
) as Array<ConfigurationMessageClosedGroup>;
return onlyValidClosedGroup;
};
@ -268,9 +268,8 @@ export const getCurrentConfigurationMessage = async (
}
const ourProfileKeyHex =
getConversationController()
.get(UserUtils.getOurPubKeyStrFromCache())
?.get('profileKey') || null;
getConversationController().get(UserUtils.getOurPubKeyStrFromCache())?.get('profileKey') ||
null;
const profileKey = ourProfileKeyHex ? fromHexToArray(ourProfileKeyHex) : undefined;
const profilePicture = ourConvo?.get('avatarPointer') || undefined;

@ -378,13 +378,11 @@ async function getMessages({
return { messagesProps: [], quotesProps: {} };
}
const {
messages: messagesCollection,
quotes: quotesCollection,
} = await Data.getMessagesByConversation(conversationKey, {
messageId,
returnQuotes: true,
});
const { messages: messagesCollection, quotes: quotesCollection } =
await Data.getMessagesByConversation(conversationKey, {
messageId,
returnQuotes: true,
});
const messagesProps: Array<MessageModelPropsWithoutConvoProps> = messagesCollection.models.map(
m => m.getMessageModelProps()
@ -1174,13 +1172,11 @@ export async function openConversationToSpecificMessage(args: {
const { conversationKey, messageIdToNavigateTo, shouldHighlightMessage } = args;
await unmarkAsForcedUnread(conversationKey);
const {
messagesProps: messagesAroundThisMessage,
quotesProps: quotesAroundThisMessage,
} = await getMessages({
conversationKey,
messageId: messageIdToNavigateTo,
});
const { messagesProps: messagesAroundThisMessage, quotesProps: quotesAroundThisMessage } =
await getMessages({
conversationKey,
messageId: messageIdToNavigateTo,
});
const mostRecentMessageIdOnOpen = await Data.getLastMessageIdInConversation(conversationKey);

@ -52,9 +52,6 @@ const defaultRoomsSlice = createSlice({
});
const { actions, reducer } = defaultRoomsSlice;
export const {
updateDefaultRooms,
updateDefaultBase64RoomData,
updateDefaultRoomsInProgress,
} = actions;
export const { updateDefaultRooms, updateDefaultBase64RoomData, updateDefaultRoomsInProgress } =
actions;
export const defaultRoomReducer = reducer;

@ -159,7 +159,7 @@ export const reducer = (
case FOCUS_SECTION:
// if we change to something else than settings, reset the focused settings section
// eslint-disable-next-line no-case-declarations
const castedPayload = (payload as unknown) as SectionType;
const castedPayload = payload as unknown as SectionType;
if (castedPayload !== SectionType.Settings) {
return {

@ -13,7 +13,7 @@ const SettingsBoolsKeyTrackedInRedux = [
] as const;
export type SettingsState = {
settingsBools: Record<typeof SettingsBoolsKeyTrackedInRedux[number], boolean>;
settingsBools: Record<(typeof SettingsBoolsKeyTrackedInRedux)[number], boolean>;
};
export function getSettingsInitialState() {
@ -28,7 +28,7 @@ export function getSettingsInitialState() {
};
}
function isTrackedBoolean(key: string): key is typeof SettingsBoolsKeyTrackedInRedux[number] {
function isTrackedBoolean(key: string): key is (typeof SettingsBoolsKeyTrackedInRedux)[number] {
return SettingsBoolsKeyTrackedInRedux.indexOf(key as any) !== -1;
}
@ -97,9 +97,6 @@ const settingsSlice = createSlice({
});
const { actions, reducer } = settingsSlice;
export const {
updateSettingsBoolValue,
deleteSettingsBoolValue,
updateAllOnStorageReady,
} = actions;
export const { updateSettingsBoolValue, deleteSettingsBoolValue, updateAllOnStorageReady } =
actions;
export const settingsReducer = reducer;

@ -36,11 +36,8 @@ const userConfigSlice = createSlice({
});
const { actions, reducer } = userConfigSlice;
export const {
toggleAudioAutoplay,
disableRecoveryPhrasePrompt,
hideMessageRequestBanner,
} = actions;
export const { toggleAudioAutoplay, disableRecoveryPhrasePrompt, hideMessageRequestBanner } =
actions;
export const userConfigReducer = reducer;
export function showMessageRequestBannerOutsideRedux() {

@ -724,39 +724,40 @@ export const getMessagePropsByMessageId = createSelector(
}
);
export const getMessageReactsProps = createSelector(getMessagePropsByMessageId, (props):
| MessageReactsSelectorProps
| undefined => {
if (!props || isEmpty(props)) {
return undefined;
}
export const getMessageReactsProps = createSelector(
getMessagePropsByMessageId,
(props): MessageReactsSelectorProps | undefined => {
if (!props || isEmpty(props)) {
return undefined;
}
const msgProps: MessageReactsSelectorProps = pick(props.propsForMessage, [
'convoId',
'conversationType',
'reacts',
'serverId',
]);
if (msgProps.reacts) {
// NOTE we don't want to render reactions that have 'senders' as an object this is a deprecated type used during development 25/08/2022
const oldReactions = Object.values(msgProps.reacts).filter(
reaction => !Array.isArray(reaction.senders)
);
const msgProps: MessageReactsSelectorProps = pick(props.propsForMessage, [
'convoId',
'conversationType',
'reacts',
'serverId',
]);
if (msgProps.reacts) {
// NOTE we don't want to render reactions that have 'senders' as an object this is a deprecated type used during development 25/08/2022
const oldReactions = Object.values(msgProps.reacts).filter(
reaction => !Array.isArray(reaction.senders)
);
if (oldReactions.length > 0) {
msgProps.reacts = undefined;
return msgProps;
}
if (oldReactions.length > 0) {
msgProps.reacts = undefined;
return msgProps;
const sortedReacts = Object.entries(msgProps.reacts).sort((a, b) => {
return a[1].index < b[1].index ? -1 : a[1].index > b[1].index ? 1 : 0;
});
msgProps.sortedReacts = sortedReacts;
}
const sortedReacts = Object.entries(msgProps.reacts).sort((a, b) => {
return a[1].index < b[1].index ? -1 : a[1].index > b[1].index ? 1 : 0;
});
msgProps.sortedReacts = sortedReacts;
return msgProps;
}
return msgProps;
});
);
export const getMessageQuoteProps = createSelector(
getConversationLookup,
@ -840,45 +841,47 @@ export const getMessageQuoteProps = createSelector(
}
);
export const getMessageTextProps = createSelector(getMessagePropsByMessageId, (props):
| MessageTextSelectorProps
| undefined => {
if (!props || isEmpty(props)) {
return undefined;
}
const msgProps: MessageTextSelectorProps = pick(props.propsForMessage, [
'direction',
'status',
'text',
'isDeleted',
'conversationType',
]);
export const getMessageTextProps = createSelector(
getMessagePropsByMessageId,
(props): MessageTextSelectorProps | undefined => {
if (!props || isEmpty(props)) {
return undefined;
}
return msgProps;
});
const msgProps: MessageTextSelectorProps = pick(props.propsForMessage, [
'direction',
'status',
'text',
'isDeleted',
'conversationType',
]);
export const getMessageAttachmentProps = createSelector(getMessagePropsByMessageId, (props):
| MessageAttachmentSelectorProps
| undefined => {
if (!props || isEmpty(props)) {
return undefined;
return msgProps;
}
);
const msgProps: MessageAttachmentSelectorProps = {
attachments: props.propsForMessage.attachments || [],
...pick(props.propsForMessage, [
'direction',
'isTrustedForAttachmentDownload',
'timestamp',
'serverTimestamp',
'sender',
'convoId',
]),
};
export const getMessageAttachmentProps = createSelector(
getMessagePropsByMessageId,
(props): MessageAttachmentSelectorProps | undefined => {
if (!props || isEmpty(props)) {
return undefined;
}
return msgProps;
});
const msgProps: MessageAttachmentSelectorProps = {
attachments: props.propsForMessage.attachments || [],
...pick(props.propsForMessage, [
'direction',
'isTrustedForAttachmentDownload',
'timestamp',
'serverTimestamp',
'sender',
'convoId',
]),
};
return msgProps;
}
);
export const getIsMessageSelected = createSelector(
getMessagePropsByMessageId,
@ -894,27 +897,28 @@ export const getIsMessageSelected = createSelector(
}
);
export const getMessageContentSelectorProps = createSelector(getMessagePropsByMessageId, (props):
| MessageContentSelectorProps
| undefined => {
if (!props || isEmpty(props)) {
return undefined;
}
export const getMessageContentSelectorProps = createSelector(
getMessagePropsByMessageId,
(props): MessageContentSelectorProps | undefined => {
if (!props || isEmpty(props)) {
return undefined;
}
const msgProps: MessageContentSelectorProps = {
...pick(props.propsForMessage, [
'direction',
'serverTimestamp',
'text',
'timestamp',
'previews',
'quote',
'attachments',
]),
};
const msgProps: MessageContentSelectorProps = {
...pick(props.propsForMessage, [
'direction',
'serverTimestamp',
'text',
'timestamp',
'previews',
'quote',
'attachments',
]),
};
return msgProps;
});
return msgProps;
}
);
export const getMessageContentWithStatusesSelectorProps = createSelector(
getMessagePropsByMessageId,

@ -16,73 +16,12 @@ import { SessionKeyPair } from '../../../../receiver/keypairs';
export const TEST_identityKeyPair: SessionKeyPair = {
pubKey: new Uint8Array([
5,
44,
2,
168,
162,
203,
50,
66,
136,
81,
30,
221,
57,
245,
1,
148,
162,
194,
255,
47,
134,
104,
180,
207,
188,
18,
71,
62,
58,
107,
23,
92,
97,
5, 44, 2, 168, 162, 203, 50, 66, 136, 81, 30, 221, 57, 245, 1, 148, 162, 194, 255, 47, 134, 104,
180, 207, 188, 18, 71, 62, 58, 107, 23, 92, 97,
]),
privKey: new Uint8Array([
200,
45,
226,
75,
253,
235,
213,
108,
187,
188,
217,
9,
51,
105,
65,
15,
97,
36,
233,
33,
21,
31,
7,
90,
145,
30,
52,
254,
47,
162,
192,
105,
200, 45, 226, 75, 253, 235, 213, 108, 187, 188, 217, 9, 51, 105, 65, 15, 97, 36, 233, 33, 21,
31, 7, 90, 145, 30, 52, 254, 47, 162, 192, 105,
]),
ed25519KeyPair: {
privateKey: new Uint8Array(),

@ -13,38 +13,8 @@ chai.use(chaiBytes);
describe('OpenGroupAuthentication', () => {
const secondPartPrivKey = new Uint8Array([
186,
198,
231,
30,
253,
125,
250,
74,
131,
201,
142,
210,
79,
37,
74,
178,
194,
103,
249,
204,
219,
23,
42,
82,
128,
160,
68,
74,
210,
78,
137,
204,
186, 198, 231, 30, 253, 125, 250, 74, 131, 201, 142, 210, 79, 37, 74, 178, 194, 103, 249, 204,
219, 23, 42, 82, 128, 160, 68, 74, 210, 78, 137, 204,
]);
const signingKeysA: ByteKeyPair = {
// 881132ee03dbd2da065aa4c94f96081f62142dc8011d1b7a00de83e4aab38ce4
@ -89,104 +59,14 @@ describe('OpenGroupAuthentication', () => {
const signingKeysB: ByteKeyPair = {
privKeyBytes: new Uint8Array([
130,
56,
83,
227,
58,
149,
251,
148,
119,
85,
180,
81,
17,
190,
245,
33,
219,
6,
246,
238,
110,
61,
191,
133,
244,
223,
32,
32,
121,
172,
138,
198,
215,
25,
249,
139,
235,
31,
251,
12,
100,
87,
84,
131,
231,
45,
87,
251,
204,
133,
20,
3,
118,
71,
29,
47,
245,
62,
216,
163,
254,
248,
195,
109,
130, 56, 83, 227, 58, 149, 251, 148, 119, 85, 180, 81, 17, 190, 245, 33, 219, 6, 246, 238,
110, 61, 191, 133, 244, 223, 32, 32, 121, 172, 138, 198, 215, 25, 249, 139, 235, 31, 251, 12,
100, 87, 84, 131, 231, 45, 87, 251, 204, 133, 20, 3, 118, 71, 29, 47, 245, 62, 216, 163, 254,
248, 195, 109,
]),
pubKeyBytes: new Uint8Array([
215,
25,
249,
139,
235,
31,
251,
12,
100,
87,
84,
131,
231,
45,
87,
251,
204,
133,
20,
3,
118,
71,
29,
47,
245,
62,
216,
163,
254,
248,
195,
109,
215, 25, 249, 139, 235, 31, 251, 12, 100, 87, 84, 131, 231, 45, 87, 251, 204, 133, 20, 3, 118,
71, 29, 47, 245, 62, 216, 163, 254, 248, 195, 109,
]),
};
const serverPubKey = new Uint8Array(
@ -395,12 +275,14 @@ const decryptBlindedMessage = async (
aSignKeyBytes: ByteKeyPair,
bSignKeyBytes: ByteKeyPair,
serverPubKey: Uint8Array
): Promise<| {
messageText: string;
senderED25519PubKey: string;
senderSessionId: string;
}
| undefined> => {
): Promise<
| {
messageText: string;
senderED25519PubKey: string;
senderSessionId: string;
}
| undefined
> => {
const sodium = await getSodiumRenderer();
const aBlindingValues = SogsBlinding.getBlindingValues(serverPubKey, aSignKeyBytes, sodium);

@ -305,9 +305,8 @@ describe('DisappearingMessage', () => {
});
it('if the type and expireTimer are undefined then the conversation mode is off', async () => {
const conversation = new ConversationModel({ ...conversationArgs });
const conversationMode = DisappearingMessages.changeToDisappearingConversationMode(
conversation
);
const conversationMode =
DisappearingMessages.changeToDisappearingConversationMode(conversation);
expect(conversationMode, 'returns off').to.be.eq('off');
});

@ -44,9 +44,8 @@ describe('ExpireRequest', () => {
};
it('builds a request with just the messageHash and expireTimer of 1 minute', async () => {
const request: UpdateExpiryOnNodeSubRequest | null = await buildExpireRequestSingleExpiry(
props
);
const request: UpdateExpiryOnNodeSubRequest | null =
await buildExpireRequestSingleExpiry(props);
expect(request, 'should not return null').to.not.be.null;
expect(request, 'should not return undefined').to.not.be.undefined;

@ -67,9 +67,8 @@ describe('libsession_user_profile', () => {
Sinon.stub(getConversationController(), 'get').returns(contact);
Sinon.stub(SessionUtilUserProfile, 'isUserProfileToStoreInWrapper').returns(true);
const wrapperUserProfile = await SessionUtilUserProfile.insertUserProfileIntoWrapper(
ourNumber
);
const wrapperUserProfile =
await SessionUtilUserProfile.insertUserProfileIntoWrapper(ourNumber);
expect(wrapperUserProfile, 'something should be returned from the wrapper').to.not.be.null;
if (!wrapperUserProfile) {
@ -123,9 +122,8 @@ describe('libsession_user_profile', () => {
Sinon.stub(getConversationController(), 'get').returns(contact);
Sinon.stub(SessionUtilUserProfile, 'isUserProfileToStoreInWrapper').returns(true);
const wrapperUserProfile = await SessionUtilUserProfile.insertUserProfileIntoWrapper(
ourNumber
);
const wrapperUserProfile =
await SessionUtilUserProfile.insertUserProfileIntoWrapper(ourNumber);
expect(wrapperUserProfile, 'something should be returned from the wrapper').to.not.be.null;
if (!wrapperUserProfile) {

@ -131,9 +131,7 @@ describe('VisibleMessage', () => {
const plainText = message.plainTextBuffer();
const decoded = SignalService.Content.decode(plainText);
expect(decoded.dataMessage?.preview).to.have.lengthOf(1);
expect(decoded.dataMessage)
.to.have.nested.property('preview[0].url')
.to.be.deep.equal('url');
expect(decoded.dataMessage).to.have.nested.property('preview[0].url').to.be.deep.equal('url');
expect(decoded.dataMessage)
.to.have.nested.property('preview[0].title')
.to.be.deep.equal('title');

@ -41,9 +41,7 @@ describe('ClosedGroupVisibleMessage', () => {
expect(decoded.dataMessage).to.have.deep.property('body', 'body');
// we use the timestamp of the chatMessage as parent timestamp
expect(message)
.to.have.property('timestamp')
.to.be.equal(chatMessage.timestamp);
expect(message).to.have.property('timestamp').to.be.equal(chatMessage.timestamp);
});
it('correct ttl', () => {

@ -94,25 +94,7 @@ describe('Padding', () => {
it('remove padding', () => {
const expectedSize = 10;
const paddedBuffer = new Uint8Array([
0,
1,
2,
3,
4,
5,
6,
7,
8,
9,
128,
0,
0,
0,
0,
0,
0,
0,
0,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 128, 0, 0, 0, 0, 0, 0, 0, 0,
]);
const unpaddedMessage = removeMessagePadding(paddedBuffer);

@ -199,9 +199,8 @@ describe('Message Utils', () => {
it('passing ClosedGroupEncryptionPairMessage returns ClosedGroup', async () => {
const device = TestUtils.generateFakePubKey();
const fakeWrappers = new Array<
SignalService.DataMessage.ClosedGroupControlMessage.KeyPairWrapper
>();
const fakeWrappers =
new Array<SignalService.DataMessage.ClosedGroupControlMessage.KeyPairWrapper>();
fakeWrappers.push(
new SignalService.DataMessage.ClosedGroupControlMessage.KeyPairWrapper({
publicKey: new Uint8Array(8),
@ -221,9 +220,8 @@ describe('Message Utils', () => {
it('passing ClosedGroupEncryptionKeyPairReply returns Fallback', async () => {
const device = TestUtils.generateFakePubKey();
const fakeWrappers = new Array<
SignalService.DataMessage.ClosedGroupControlMessage.KeyPairWrapper
>();
const fakeWrappers =
new Array<SignalService.DataMessage.ClosedGroupControlMessage.KeyPairWrapper>();
fakeWrappers.push(
new SignalService.DataMessage.ClosedGroupControlMessage.KeyPairWrapper({
publicKey: new Uint8Array(8),

@ -21,7 +21,7 @@ describe('Promise Utils', () => {
let pollSpy: sinon.SinonSpy<
[
(done: (arg: any) => void) => Promise<void> | void,
(Partial<PromiseUtils.PollOptions> | undefined)?
(Partial<PromiseUtils.PollOptions> | undefined)?,
],
Promise<void>
>;

@ -83,9 +83,7 @@ describe('String Utils', () => {
it('can encode huge string', () => {
const stringSize = 2 ** 16;
const testString = Array(stringSize)
.fill('0')
.join('');
const testString = Array(stringSize).fill('0').join('');
const allEncodedings = (['base64', 'hex', 'binary', 'utf8'] as Array<Encoding>).map(e =>
StringUtils.encode(testString, e)
@ -145,9 +143,7 @@ describe('String Utils', () => {
it('can decode huge buffer', () => {
const bytes = 2 ** 16;
const bufferString = Array(bytes)
.fill('A')
.join('');
const bufferString = Array(bytes).fill('A').join('');
const buffer = ByteBuffer.fromUTF8(bufferString);
const encodings = ['base64', 'hex', 'binary', 'utf8'] as Array<Encoding>;

@ -52,7 +52,7 @@ export function stubLibSessionWorker(value: any) {
}
export function stubCreateObjectUrl() {
(global as any).URL = function() {};
(global as any).URL = function () {};
(global as any).URL.createObjectURL = () => {
return `${Date.now()}:${Math.floor(Math.random() * 1000)}`;
};

@ -201,23 +201,25 @@ type CaptureDimensionType = { contentType: string; path: string };
export const captureDimensionsAndScreenshot = async (
attachment: CaptureDimensionType
): Promise<CaptureDimensionType & {
width?: number;
height?: number;
thumbnail: {
path: string;
contentType: string;
width: number;
height: number;
} | null;
screenshot: {
path: string;
contentType: string;
width: number;
height: number;
} | null;
}> => {
): Promise<
CaptureDimensionType & {
width?: number;
height?: number;
thumbnail: {
path: string;
contentType: string;
width: number;
height: number;
} | null;
screenshot: {
path: string;
contentType: string;
width: number;
height: number;
} | null;
}
> => {
const { contentType } = attachment;
if (

@ -1,9 +1,10 @@
import { MessageModel } from '../../models/message';
import * as Attachment from '../Attachment';
const hasAttachmentInMessage = (predicate: (value: Attachment.Attachment) => boolean) => (
message: MessageModel
): boolean => Boolean((message.get('attachments') || []).some(predicate));
const hasAttachmentInMessage =
(predicate: (value: Attachment.Attachment) => boolean) =>
(message: MessageModel): boolean =>
Boolean((message.get('attachments') || []).some(predicate));
export const hasFileAttachmentInMessage = hasAttachmentInMessage(Attachment.isFile);
export const hasVisualMediaAttachmentInMessage = hasAttachmentInMessage(Attachment.isVisualMedia);

@ -40,22 +40,28 @@ export async function start(
autoUpdater.logger = logger;
autoUpdater.autoDownload = false;
interval = global.setInterval(async () => {
try {
await checkForUpdates(getMainWindow, messages, logger);
} catch (error) {
logger.error('auto-update: error:', getPrintableError(error));
}
}, 1000 * 60 * 10); // trigger and try to update every 10 minutes to let the file gets downloaded if we are updating
interval = global.setInterval(
async () => {
try {
await checkForUpdates(getMainWindow, messages, logger);
} catch (error) {
logger.error('auto-update: error:', getPrintableError(error));
}
},
1000 * 60 * 10
); // trigger and try to update every 10 minutes to let the file gets downloaded if we are updating
stopped = false;
global.setTimeout(async () => {
try {
await checkForUpdates(getMainWindow, messages, logger);
} catch (error) {
logger.error('auto-update: error:', getPrintableError(error));
}
}, 2 * 60 * 1000); // we do checks from the fileserver every 1 minute.
global.setTimeout(
async () => {
try {
await checkForUpdates(getMainWindow, messages, logger);
} catch (error) {
logger.error('auto-update: error:', getPrintableError(error));
}
},
2 * 60 * 1000
); // we do checks from the fileserver every 1 minute.
}
export function stop() {

@ -299,10 +299,7 @@ const getLinkHrefAttribute = (
): string | null => {
for (let i = 0; i < rels.length; i += 1) {
const rel = rels[i];
const href = document
.querySelector(`link[rel="${rel}"]`)
?.getAttribute('href')
?.trim();
const href = document.querySelector(`link[rel="${rel}"]`)?.getAttribute('href')?.trim();
if (href) {
return href;
}

@ -7,9 +7,11 @@ import { isDevProd } from '../shared/env_vars';
const APP_ROOT_PATH = getAppRootPath();
const SESSION_ID_PATTERN = /\b((05)?[0-9a-f]{64})\b/gi;
const SNODE_PATTERN = /(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)/g;
const SNODE_PATTERN =
/(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)/g;
const GROUP_ID_PATTERN = /(group\()([^)]+)(\))/g;
const SERVER_URL_PATTERN = /https?:\/\/[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_+.~#?&//=]*)/g;
const SERVER_URL_PATTERN =
/https?:\/\/[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_+.~#?&//=]*)/g;
const REDACTION_PLACEHOLDER = '[REDACTED]';
// redactPath :: Path -> String -> String

@ -30,9 +30,7 @@ async function onReadReceipt(receipt: { source: string; timestamp: number; readA
if (
!convoId ||
!getConversationController().get(convoId) ||
!getConversationController()
.get(convoId)
.isPrivate()
!getConversationController().get(convoId).isPrivate()
) {
window.log.info(
'Convo is undefined or not a private chat for read receipt in convo',

@ -1,6 +1,5 @@
/* eslint-disable import/extensions */
/* eslint-disable import/no-unresolved */
import { join } from 'path';
import {
BaseWrapperActionsCalls,
ContactInfoSet,
@ -10,6 +9,7 @@ import {
UserConfigWrapperActionsCalls,
UserGroupsWrapperActionsCalls,
} from 'libsession_util_nodejs';
import { join } from 'path';
import { getAppRootPath } from '../../../node/getRootPath';
import { WorkerInterface } from '../../worker_interface';
@ -30,7 +30,7 @@ const internalCallLibSessionWorker = async ([
'workers',
'node',
'libsession',
'libsession.worker.js'
'libsession.worker.compiled.js'
);
libsessionWorkerInterface = new WorkerInterface(libsessionWorkerPath, 1 * 60 * 1000);

@ -25,7 +25,7 @@ const internalCallUtilsWorker = async (
'workers',
'node',
'util',
'util.worker.js'
'util.worker.compiled.js'
);
utilWorkerInterface = new WorkerInterface(utilWorkerPath, 3 * 60 * 1000);
}

@ -22,7 +22,7 @@ module.exports = {
},
},
output: {
filename: 'util.worker.js',
filename: 'util.worker.compiled.js',
path: path.resolve(__dirname, 'ts', 'webworker', 'workers', 'node', 'util'),
},
target: 'node',

Loading…
Cancel
Save