diff --git a/js/background.js b/js/background.js index 3600881e6..fada3d7e8 100644 --- a/js/background.js +++ b/js/background.js @@ -344,7 +344,9 @@ Whisper.Notifications.on('click', (id, messageId) => { window.showWindow(); if (id) { - window.inboxStore.dispatch(window.actionsCreators.openConversationExternal(id, messageId)); + window.inboxStore.dispatch( + window.actionsCreators.openConversationExternal({ id, messageId }) + ); } else { appView.openInbox({ initialLoadComplete, diff --git a/js/expire.js b/js/expire.js index e4bb6f48b..0f4ecdb8b 100644 --- a/js/expire.js +++ b/js/expire.js @@ -23,7 +23,7 @@ try { latestVersionWithV = await window.Fsv2.getLatestDesktopReleaseFileToFsV2(); if (!latestVersionWithV) { - throw new Error('Invalid latest version. Shceduling retry...'); + throw new Error('Invalid latest version. Scheduling retry...'); } const latestVer = semver.clean(latestVersionWithV); if (semver.valid(latestVer)) { diff --git a/js/read_syncs.js b/js/read_syncs.js index 70aebf1c4..c7337ec07 100644 --- a/js/read_syncs.js +++ b/js/read_syncs.js @@ -59,7 +59,7 @@ // If message is unread, we mark it read. Otherwise, we update the expiration // timer to the time specified by the read sync if it's earlier than // the previous read time. - if (message.isUnread()) { + if (message.isUnread() && window.isFocused()) { await message.markRead(readAt); // onReadMessage may result in messages older than this one being diff --git a/preload.js b/preload.js index 2634faa8d..da0a7108d 100644 --- a/preload.js +++ b/preload.js @@ -56,7 +56,7 @@ window.lokiFeatureFlags = { useFileOnionRequests: true, useFileOnionRequestsV2: true, // more compact encoding of files in response padOutgoingAttachments: true, - enablePinConversations: false, + enablePinConversations: true, }; if (typeof process.env.NODE_ENV === 'string' && process.env.NODE_ENV.includes('test-integration')) { diff --git a/stylesheets/_modules.scss b/stylesheets/_modules.scss index 02ede7a9a..1cd404ab9 100644 --- a/stylesheets/_modules.scss +++ b/stylesheets/_modules.scss @@ -130,26 +130,19 @@ border-radius: $session_message-container-border-radius; overflow: hidden; // no background by default for the attachment container - @include themify($themes) { - background: themed('inboxBackground'); - } } .module-message--outgoing { .module-message__attachment-container--with-content-below, .module-message__attachment-container--with-content-above { - @include themify($themes) { - background: themed('sentMessageBackground'); - } + background: none; } } .module-message--incoming { .module-message__attachment-container--with-content-below, .module-message__attachment-container--with-content-above { - @include themify($themes) { - background: themed('receivedMessageBackground'); - } + background: none; } } @@ -1285,7 +1278,7 @@ .module-image { overflow: hidden; - background-color: $color-white; + background: none; position: relative; display: inline-block; margin: 1px; diff --git a/stylesheets/_session_theme.scss b/stylesheets/_session_theme.scss index cb3597fed..3e66d9c02 100644 --- a/stylesheets/_session_theme.scss +++ b/stylesheets/_session_theme.scss @@ -25,8 +25,14 @@ } &__container--incoming { - @include themify($themes) { - background: themed('receivedMessageBackground'); + &--opaque { + @include themify($themes) { + background: themed('receivedMessageBackground'); + } + } + + &--transparent { + background: none; } .module-message__text { @@ -49,8 +55,14 @@ } &__container--outgoing { - @include themify($themes) { - background: themed('sentMessageBackground'); + &--opaque { + @include themify($themes) { + background: themed('sentMessageBackground'); + } + } + + &--transparent { + background: none; } .module-message__text { diff --git a/stylesheets/_theme_dark.scss b/stylesheets/_theme_dark.scss index 54639d58e..e0e93674c 100644 --- a/stylesheets/_theme_dark.scss +++ b/stylesheets/_theme_dark.scss @@ -401,7 +401,7 @@ // Module: Image .module-image { - background-color: $color-black; + background: none; } .module-image__border-overlay { diff --git a/ts/components/ConversationListItem.tsx b/ts/components/ConversationListItem.tsx index 5a4e7e21c..98be42401 100644 --- a/ts/components/ConversationListItem.tsx +++ b/ts/components/ConversationListItem.tsx @@ -230,6 +230,8 @@ const ConversationListItem = (props: Props) => { type, isPublic, avatarPath, + notificationForConvo, + currentNotificationSetting, } = props; const triggerId = `conversation-item-${conversationId}-ctxmenu`; const key = `conversation-item-${conversationId}`; @@ -292,6 +294,8 @@ const ConversationListItem = (props: Props) => { isPublic={isPublic} left={left} type={type} + notificationForConvo={notificationForConvo} + currentNotificationSetting={currentNotificationSetting} /> diff --git a/ts/components/conversation/ConversationHeader.tsx b/ts/components/conversation/ConversationHeader.tsx index 52c073430..3b44d4728 100644 --- a/ts/components/conversation/ConversationHeader.tsx +++ b/ts/components/conversation/ConversationHeader.tsx @@ -27,17 +27,13 @@ import { openRightPanel, resetSelectedMessageIds, } from '../../state/ducks/conversations'; +import { NotificationForConvoOption } from '../../state/ducks/conversations'; export interface TimerOption { name: string; value: number; } -export interface NotificationForConvoOption { - name: string; - value: ConversationNotificationSettingType; -} - export type ConversationHeaderProps = { id: string; name?: string; diff --git a/ts/components/conversation/Message.tsx b/ts/components/conversation/Message.tsx index f2cb04f80..92c7fa752 100644 --- a/ts/components/conversation/Message.tsx +++ b/ts/components/conversation/Message.tsx @@ -44,6 +44,7 @@ import { showLightBox, toggleSelectedMessageId } from '../../state/ducks/convers import { saveAttachmentToDisk } from '../../util/attachmentsUtil'; import { LightBoxOptions } from '../session/conversation/SessionConversation'; import { MessageContextMenu } from './MessageContextMenu'; +import { ReadableMessage } from './ReadableMessage'; // Same as MIN_WIDTH in ImageGrid.tsx const MINIMUM_LINK_PREVIEW_IMAGE_WIDTH = 200; @@ -595,9 +596,10 @@ class MessageInner extends React.PureComponent { divClasses.push('flash-green-once'); } - const onVisible = async (inView: boolean) => { - if (inView && shouldMarkReadWhenVisible) { + const onVisible = async (inView: boolean | Object) => { + if (inView === true && shouldMarkReadWhenVisible && window.isFocused()) { const found = await getMessageById(id); + // mark the message as read. // this will trigger the expire timer. void found?.markRead(Date.now()); @@ -605,14 +607,10 @@ class MessageInner extends React.PureComponent { }; return ( - {this.renderAvatar()} @@ -630,7 +628,10 @@ class MessageInner extends React.PureComponent {
{ weAreAdmin={this.props.weAreAdmin} />
-
+ ); } diff --git a/ts/components/conversation/ReadableMessage.tsx b/ts/components/conversation/ReadableMessage.tsx new file mode 100644 index 000000000..d56fa2c4e --- /dev/null +++ b/ts/components/conversation/ReadableMessage.tsx @@ -0,0 +1,22 @@ +import React from 'react'; +import { useFocus } from '../../hooks/useFocus'; +import { InView, useInView } from 'react-intersection-observer'; + +type ReadableMessageProps = { + children: React.ReactNode; + id: string; + className: string; + onChange: (inView: boolean) => void; + onContextMenu: (e: any) => void; +}; + +export const ReadableMessage = (props: ReadableMessageProps) => { + const { onChange } = props; + useFocus(onChange); + + return ( + + {props.children} + + ); +}; diff --git a/ts/components/session/conversation/SessionConversation.tsx b/ts/components/session/conversation/SessionConversation.tsx index d44640cec..ddd21e265 100644 --- a/ts/components/session/conversation/SessionConversation.tsx +++ b/ts/components/session/conversation/SessionConversation.tsx @@ -11,7 +11,7 @@ import { ConversationHeaderWithDetails } from '../../conversation/ConversationHe import { SessionRightPanelWithDetails } from './SessionRightPanel'; import { SessionTheme } from '../../../state/ducks/SessionTheme'; import { DefaultTheme } from 'styled-components'; -import { SessionMessageListProps, SessionMessagesList } from './SessionMessagesList'; +import { SessionMessagesList } from './SessionMessagesList'; import { LightboxGallery, MediaItemType } from '../../LightboxGallery'; import { AttachmentType, AttachmentTypeWithPath, save } from '../../../types/Attachment'; @@ -20,11 +20,9 @@ import * as MIME from '../../../types/MIME'; import { SessionFileDropzone } from './SessionFileDropzone'; import { fetchMessagesForConversation, - PropsForMessage, quoteMessage, ReduxConversationType, resetSelectedMessageIds, - showLightBox, SortedMessageModelProps, updateMentionsMembers, } from '../../../state/ducks/conversations'; diff --git a/ts/components/session/conversation/SessionMessagesList.tsx b/ts/components/session/conversation/SessionMessagesList.tsx index c3722936a..53860fc5d 100644 --- a/ts/components/session/conversation/SessionMessagesList.tsx +++ b/ts/components/session/conversation/SessionMessagesList.tsx @@ -374,7 +374,7 @@ class SessionMessagesListInner extends React.Component { return; } - if (this.getScrollOffsetBottomPx() === 0) { + if (this.getScrollOffsetBottomPx() === 0 && window.isFocused()) { void conversation.markRead(messagesProps[0].propsForMessage.receivedAt || 0); } } diff --git a/ts/components/session/menu/ConversationHeaderMenu.tsx b/ts/components/session/menu/ConversationHeaderMenu.tsx index 2a5325d8a..f164c1721 100644 --- a/ts/components/session/menu/ConversationHeaderMenu.tsx +++ b/ts/components/session/menu/ConversationHeaderMenu.tsx @@ -1,4 +1,4 @@ -import React, { useState } from 'react'; +import React from 'react'; import { animation, Menu } from 'react-contexify'; import { getAddModeratorsMenuItem, @@ -13,12 +13,13 @@ import { getLeaveGroupMenuItem, getMarkAllReadMenuItem, getNotificationForConvoMenuItem, + getPinConversationMenuItem, getRemoveModeratorsMenuItem, getUpdateGroupNameMenuItem, } from './Menu'; -import { NotificationForConvoOption } from '../../conversation/ConversationHeader'; -import { ConversationNotificationSettingType } from '../../../models/conversation'; import _ from 'lodash'; +import { ConversationNotificationSettingType } from '../../../models/conversation'; +import { NotificationForConvoOption } from '../../../state/ducks/conversations'; export type PropsConversationHeaderMenu = { conversationId: string; @@ -64,8 +65,8 @@ const ConversationHeaderMenu = (props: PropsConversationHeaderMenu) => { currentNotificationSetting, conversationId )} + {getPinConversationMenuItem(conversationId)} {getBlockMenuItem(isMe, isPrivate, isBlocked, conversationId)} - {getCopyMenuItem(isPublic, isGroup, conversationId)} {getMarkAllReadMenuItem(conversationId)} {getChangeNicknameMenuItem(isMe, isGroup, conversationId)} diff --git a/ts/components/session/menu/ConversationListItemContextMenu.tsx b/ts/components/session/menu/ConversationListItemContextMenu.tsx index 5c26c77e7..f42f557be 100644 --- a/ts/components/session/menu/ConversationListItemContextMenu.tsx +++ b/ts/components/session/menu/ConversationListItemContextMenu.tsx @@ -1,7 +1,11 @@ import React from 'react'; import { animation, Menu } from 'react-contexify'; import _ from 'underscore'; -import { ConversationTypeEnum } from '../../../models/conversation'; +import { + ConversationNotificationSettingType, + ConversationTypeEnum, +} from '../../../models/conversation'; +import { NotificationForConvoOption } from '../../../state/ducks/conversations'; import { getBlockMenuItem, @@ -13,6 +17,7 @@ import { getInviteContactMenuItem, getLeaveGroupMenuItem, getMarkAllReadMenuItem, + getNotificationForConvoMenuItem, getPinConversationMenuItem, } from './Menu'; @@ -26,6 +31,9 @@ export type PropsContextConversationItem = { hasNickname: boolean; isKickedFromGroup: boolean; left: boolean; + theme?: any; + notificationForConvo: Array; + currentNotificationSetting: ConversationNotificationSettingType; }; const ConversationListItemContextMenu = (props: PropsContextConversationItem) => { @@ -39,11 +47,21 @@ const ConversationListItemContextMenu = (props: PropsContextConversationItem) => type, left, isKickedFromGroup, + notificationForConvo, + currentNotificationSetting, } = props; const isGroup = type === 'group'; return ( + {getNotificationForConvoMenuItem( + isKickedFromGroup, + left, + isBlocked, + notificationForConvo, + currentNotificationSetting, + conversationId + )} {getPinConversationMenuItem(conversationId)} {getBlockMenuItem(isMe, type === ConversationTypeEnum.PRIVATE, isBlocked, conversationId)} {getCopyMenuItem(isPublic, isGroup, conversationId)} diff --git a/ts/components/session/menu/Menu.tsx b/ts/components/session/menu/Menu.tsx index 271e95d01..554b2450d 100644 --- a/ts/components/session/menu/Menu.tsx +++ b/ts/components/session/menu/Menu.tsx @@ -2,7 +2,7 @@ import React from 'react'; import { getNumberOfPinnedConversations } from '../../../state/selectors/conversations'; import { getFocusedSection } from '../../../state/selectors/section'; -import { NotificationForConvoOption, TimerOption } from '../../conversation/ConversationHeader'; +import { TimerOption } from '../../conversation/ConversationHeader'; import { Item, Submenu } from 'react-contexify'; import { ConversationNotificationSettingType } from '../../../models/conversation'; import { useDispatch, useSelector } from 'react-redux'; @@ -27,6 +27,7 @@ import { import { SessionButtonColor } from '../SessionButton'; import { getTimerOptions } from '../../../state/selectors/timerOptions'; import { ToastUtils } from '../../../session/utils'; +import { NotificationForConvoOption } from '../../../state/ducks/conversations'; const maxNumberOfPinnedConversations = 5; @@ -131,10 +132,11 @@ export interface PinConversationMenuItemProps { export const getPinConversationMenuItem = (conversationId: string): JSX.Element | null => { const isMessagesSection = useSelector(getFocusedSection) === SectionType.Message; + const nbOfAlreadyPinnedConvos = useSelector(getNumberOfPinnedConversations); + if (isMessagesSection && window.lokiFeatureFlags.enablePinConversations) { const conversation = getConversationController().get(conversationId); const isPinned = conversation.isPinned(); - const nbOfAlreadyPinnedConvos = useSelector(getNumberOfPinnedConversations); const togglePinConversation = async () => { if ((!isPinned && nbOfAlreadyPinnedConvos < maxNumberOfPinnedConversations) || isPinned) { @@ -312,6 +314,8 @@ export function getDisappearingMenuItem( isBlocked: boolean | undefined, conversationId: string ): JSX.Element | null { + const timerOptions = useSelector(getTimerOptions).timerOptions; + if ( showTimerOptions( Boolean(isPublic), @@ -322,8 +326,6 @@ export function getDisappearingMenuItem( ) { const isRtlMode = isRtlBody(); - const timerOptions = useSelector(getTimerOptions).timerOptions; - return ( // Remove the && false to make context menu work with RTL support { window.Whisper.events.on('configurationMessageReceived', (displayName: string) => { diff --git a/ts/hooks/useEncryptedFileFetch.ts b/ts/hooks/useEncryptedFileFetch.ts index f5178f31e..89a54cc8c 100644 --- a/ts/hooks/useEncryptedFileFetch.ts +++ b/ts/hooks/useEncryptedFileFetch.ts @@ -7,15 +7,21 @@ export const useEncryptedFileFetch = (url: string, contentType: string) => { const [urlToLoad, setUrlToLoad] = useState(''); const [loading, setLoading] = useState(true); + let isCancelled = false; + async function fetchUrl() { const decryptedUrl = await getDecryptedMediaUrl(url, contentType); - setUrlToLoad(decryptedUrl); + if (!isCancelled) { + setUrlToLoad(decryptedUrl); - setLoading(false); + setLoading(false); + } } useEffect(() => { void fetchUrl(); + + () => (isCancelled = true); }, [url]); return { urlToLoad, loading }; diff --git a/ts/hooks/useFocus.ts b/ts/hooks/useFocus.ts new file mode 100644 index 000000000..8f62de92e --- /dev/null +++ b/ts/hooks/useFocus.ts @@ -0,0 +1,10 @@ +import { useEffect } from 'react'; + +export const useFocus = (action: (param: any) => void) => { + useEffect(() => { + window.addEventListener('focus', action); + return () => { + window.removeEventListener('focus', action); + }; + }); +}; diff --git a/ts/models/conversation.ts b/ts/models/conversation.ts index eae8f9361..c45ede6bb 100644 --- a/ts/models/conversation.ts +++ b/ts/models/conversation.ts @@ -27,6 +27,7 @@ import { LastMessageStatusType, MessageModelProps, ReduxConversationType, + NotificationForConvoOption, } from '../state/ducks/conversations'; import { ExpirationTimerUpdateMessage } from '../session/messages/outgoing/controlMessage/ExpirationTimerUpdateMessage'; import { TypingMessage } from '../session/messages/outgoing/controlMessage/TypingMessage'; @@ -37,7 +38,6 @@ import { import { GroupInvitationMessage } from '../session/messages/outgoing/visibleMessage/GroupInvitationMessage'; import { ReadReceiptMessage } from '../session/messages/outgoing/controlMessage/receipt/ReadReceiptMessage'; import { OpenGroupUtils } from '../opengroup/utils'; -import { ConversationInteraction } from '../interactions'; import { OpenGroupVisibleMessage } from '../session/messages/outgoing/visibleMessage/OpenGroupVisibleMessage'; import { OpenGroupRequestCommonType } from '../opengroup/opengroupV2/ApiUtil'; import { getOpenGroupV2FromConversationId } from '../opengroup/utils/OpenGroupUtils'; @@ -177,6 +177,7 @@ export class ConversationModel extends Backbone.Model { private typingRefreshTimer?: NodeJS.Timeout | null; private typingPauseTimer?: NodeJS.Timeout | null; private typingTimer?: NodeJS.Timeout | null; + private lastReadTimestamp: number; private pending: any; @@ -198,11 +199,19 @@ export class ConversationModel extends Backbone.Model { }); this.throttledNotify = _.debounce(this.notify, 500, { maxWait: 1000, trailing: true }); //start right away the function is called, and wait 1sec before calling it again - this.markRead = _.debounce(this.markReadBouncy, 1000, { leading: true }); + const markReadDebounced = _.debounce(this.markReadBouncy, 1000, { leading: true }); + this.markRead = async (newestUnreadDate: number) => { + const lastReadTimestamp = this.lastReadTimestamp; + if (newestUnreadDate > lastReadTimestamp) { + this.lastReadTimestamp = newestUnreadDate; + } + void markReadDebounced(newestUnreadDate); + }; // Listening for out-of-band data updates this.typingRefreshTimer = null; this.typingPauseTimer = null; + this.lastReadTimestamp = 0; window.inboxStore?.dispatch(conversationChanged({ id: this.id, data: this.getProps() })); } @@ -390,16 +399,7 @@ export class ConversationModel extends Backbone.Model { public getProps(): ReduxConversationType { const groupAdmins = this.getGroupAdmins(); - const members = this.isGroup() && !this.isPublic() ? this.get('members') : []; - - // exclude mentions_only settings for private chats as this does not make much sense - const notificationForConvo = ConversationNotificationSetting.filter(n => - this.isPrivate() ? n !== 'mentions_only' : true - ).map((n: ConversationNotificationSettingType) => { - // this link to the notificationForConvo_all, notificationForConvo_mentions_only, ... - return { value: n, name: window.i18n(`notificationForConvo_${n}`) }; - }); const ourNumber = UserUtils.getOurPubKeyStrFromCache(); // isSelected is overriden by redux @@ -411,9 +411,7 @@ export class ConversationModel extends Backbone.Model { type: this.isPrivate() ? ConversationTypeEnum.PRIVATE : ConversationTypeEnum.GROUP, weAreAdmin: this.isAdmin(ourNumber), isGroup: !this.isPrivate(), - currentNotificationSetting: this.get('triggerNotificationsFor'), - notificationForConvo, isPrivate: this.isPrivate(), isMe: this.isMe(), isPublic: this.isPublic(), @@ -437,9 +435,21 @@ export class ConversationModel extends Backbone.Model { expireTimer: this.get('expireTimer') || 0, subscriberCount: this.get('subscriberCount') || 0, isPinned: this.isPinned(), + notificationForConvo: this.getConversationNotificationSettingType(), + currentNotificationSetting: this.get('triggerNotificationsFor'), }; } + public getConversationNotificationSettingType(): Array { + // exclude mentions_only settings for private chats as this does not make much sense + return ConversationNotificationSetting.filter(n => + this.isPrivate() ? n !== 'mentions_only' : true + ).map((n: ConversationNotificationSettingType) => { + // this link to the notificationForConvo_all, notificationForConvo_mentions_only, ... + return { value: n, name: window.i18n(`notificationForConvo_${n}`) }; + }); + } + public async updateGroupAdmins(groupAdmins: Array) { const existingAdmins = _.uniq(_.sortBy(this.getGroupAdmins())); const newAdmins = _.uniq(_.sortBy(groupAdmins)); @@ -946,6 +956,11 @@ export class ConversationModel extends Backbone.Model { } public async markReadBouncy(newestUnreadDate: number, providedOptions: any = {}) { + const lastReadTimestamp = this.lastReadTimestamp; + if (newestUnreadDate < lastReadTimestamp) { + return; + } + const options = providedOptions || {}; _.defaults(options, { sendReadReceipts: true }); @@ -994,7 +1009,7 @@ export class ConversationModel extends Backbone.Model { const cachedUnreadCountOnConvo = this.get('unreadCount'); if (cachedUnreadCountOnConvo !== read.length) { // reset the unreadCount on the convo to the real one coming from markRead messages on the db - this.set({ unreadCount: 0 }); + this.set({ unreadCount: realUnreadCount }); await this.commit(); } else { // window?.log?.info('markRead(): nothing newly read.'); diff --git a/ts/models/message.ts b/ts/models/message.ts index 899799302..349ee1f46 100644 --- a/ts/models/message.ts +++ b/ts/models/message.ts @@ -1088,6 +1088,8 @@ export class MessageModel extends Backbone.Model { public async markRead(readAt: number) { this.markReadNoCommit(readAt); + this.getConversation()?.markRead(this.attributes.received_at); + await this.commit(); } diff --git a/ts/state/ducks/conversations.ts b/ts/state/ducks/conversations.ts index a7a35c95d..d6c58c008 100644 --- a/ts/state/ducks/conversations.ts +++ b/ts/state/ducks/conversations.ts @@ -14,7 +14,6 @@ import { MessageRegularProps, PropsForDataExtractionNotification, } from '../../models/messageType'; -import { NotificationForConvoOption } from '../../components/conversation/ConversationHeader'; import { LightBoxOptions } from '../../components/session/conversation/SessionConversation'; import { ReplyingToMessageProps } from '../../components/session/conversation/SessionCompositionBox'; @@ -225,6 +224,11 @@ export interface ReduxConversationType { isPinned: boolean; } +export interface NotificationForConvoOption { + name: string; + value: ConversationNotificationSettingType; +} + export type ConversationLookupType = { [key: string]: ReduxConversationType; }; @@ -347,8 +351,6 @@ const getFirstMessageUnreadIndex = (messages: Array) => message.propsForMessage.direction === 'incoming' && message.propsForMessage.isUnread === true ) { - console.warn('message.propsForMessage', message.propsForMessage); - return index; } } @@ -375,7 +377,6 @@ export const fetchMessagesForConversation = createAsyncThunk( const mapped = messagesProps.map((m, index) => { if (index === firstUnreadIndex) { - console.warn('fullfuled firstUnreadIndex', firstUnreadIndex); return { ...m, firstMessageOfSeries: true, diff --git a/ts/state/selectors/conversations.ts b/ts/state/selectors/conversations.ts index e428c2b6e..c17e32983 100644 --- a/ts/state/selectors/conversations.ts +++ b/ts/state/selectors/conversations.ts @@ -145,14 +145,6 @@ export const _getLeftPaneLists = ( continue; } - // Show loading icon while fetching messages - if (conversation.isPublic && !conversation.activeAt) { - conversation.lastMessage = { - status: 'sending', - text: '', - }; - } - // Remove all invalid conversations and conversatons of devices associated // with cancelled attempted links if (!conversation.isPublic && !conversation.activeAt) { diff --git a/ts/test/session/unit/selectors/conversations_test.ts b/ts/test/session/unit/selectors/conversations_test.ts index bd24f567d..8db933f21 100644 --- a/ts/test/session/unit/selectors/conversations_test.ts +++ b/ts/test/session/unit/selectors/conversations_test.ts @@ -1,5 +1,8 @@ import { assert } from 'chai'; -import { ConversationTypeEnum } from '../../../../models/conversation'; +import { + ConversationNotificationSetting, + ConversationTypeEnum, +} from '../../../../models/conversation'; import { ConversationLookupType } from '../../../../state/ducks/conversations'; import { @@ -80,7 +83,6 @@ describe('state/selectors/conversations', () => { activeAt: 20, name: 'C', phoneNumber: 'notused', - type: ConversationTypeEnum.PRIVATE, isMe: false, unreadCount: 1, diff --git a/ts/util/accountManager.ts b/ts/util/accountManager.ts index 7661bda9c..1c7da7ee0 100644 --- a/ts/util/accountManager.ts +++ b/ts/util/accountManager.ts @@ -84,6 +84,7 @@ export async function signInByLinkingDevice(mnemonic: string, mnemonicLanguage: // await for the first configuration message to come in. await registrationDone(pubKeyString, ''); + return pubKeyString; } /** * This is a signup. User has no recovery and does not try to link a device diff --git a/ts/window.d.ts b/ts/window.d.ts index 2fdc03466..72029c1bd 100644 --- a/ts/window.d.ts +++ b/ts/window.d.ts @@ -41,6 +41,7 @@ declare global { getFriendsFromContacts: any; getSettingValue: any; i18n: LocalizerType; + isFocused: () => boolean; libsignal: LibsignalProtocol; log: any; lokiFeatureFlags: {