link back backbone conversation events to redux store
This commit is contained in:
parent
918eeae275
commit
2f2eb2ad53
22
app/menu.js
22
app/menu.js
|
@ -11,7 +11,6 @@ exports.createTemplate = (options, messages) => {
|
|||
openReleaseNotes,
|
||||
openSupportPage,
|
||||
platform,
|
||||
setupAsStandalone,
|
||||
setupWithImport,
|
||||
showAbout,
|
||||
showDebugLog,
|
||||
|
@ -153,12 +152,6 @@ exports.createTemplate = (options, messages) => {
|
|||
const fileMenu = template[0];
|
||||
|
||||
// These are in reverse order, since we're prepending them one at a time
|
||||
if (options.development) {
|
||||
fileMenu.submenu.unshift({
|
||||
label: messages.menuSetupAsStandalone.message,
|
||||
click: setupAsStandalone,
|
||||
});
|
||||
}
|
||||
|
||||
fileMenu.submenu.unshift({
|
||||
type: 'separator',
|
||||
|
@ -177,13 +170,7 @@ exports.createTemplate = (options, messages) => {
|
|||
};
|
||||
|
||||
function updateForMac(template, messages, options) {
|
||||
const {
|
||||
includeSetup,
|
||||
setupAsStandalone,
|
||||
setupWithImport,
|
||||
showAbout,
|
||||
showWindow,
|
||||
} = options;
|
||||
const { includeSetup, setupWithImport, showAbout, showWindow } = options;
|
||||
|
||||
// Remove About item and separator from Help menu, since it's on the first menu
|
||||
template[4].submenu.pop();
|
||||
|
@ -205,13 +192,6 @@ function updateForMac(template, messages, options) {
|
|||
],
|
||||
};
|
||||
|
||||
if (options.development) {
|
||||
fileMenu.submenu.push({
|
||||
label: messages.menuSetupAsStandalone.message,
|
||||
click: setupAsStandalone,
|
||||
});
|
||||
}
|
||||
|
||||
template.unshift(fileMenu);
|
||||
}
|
||||
|
||||
|
|
|
@ -165,7 +165,6 @@
|
|||
let initialLoadComplete = false;
|
||||
let newVersion = false;
|
||||
|
||||
window.owsDesktopApp = {};
|
||||
window.document.title = window.getTitle();
|
||||
|
||||
// start a background worker for ecc
|
||||
|
@ -477,13 +476,6 @@
|
|||
}
|
||||
);
|
||||
|
||||
Whisper.events.on('setupAsStandalone', () => {
|
||||
const { appView } = window.owsDesktopApp;
|
||||
if (appView) {
|
||||
appView.openStandalone();
|
||||
}
|
||||
});
|
||||
|
||||
function manageExpiringData() {
|
||||
window.Signal.Data.cleanSeenMessages();
|
||||
window.Signal.Data.cleanLastHashes();
|
||||
|
@ -570,7 +562,6 @@
|
|||
const appView = new Whisper.AppView({
|
||||
el: $('body'),
|
||||
});
|
||||
window.owsDesktopApp.appView = appView;
|
||||
|
||||
Whisper.WallClockListener.init(Whisper.events);
|
||||
Whisper.ExpiringMessagesListener.init(Whisper.events);
|
||||
|
@ -608,12 +599,6 @@
|
|||
window.addEventListener('focus', () => Whisper.Notifications.clear());
|
||||
window.addEventListener('unload', () => Whisper.Notifications.fastClear());
|
||||
|
||||
Whisper.events.on('showConversation', (id, messageId) => {
|
||||
if (appView) {
|
||||
appView.openConversation(id, messageId);
|
||||
}
|
||||
});
|
||||
|
||||
window.confirmationDialog = params => {
|
||||
const confirmDialog = new Whisper.SessionConfirmView({
|
||||
el: $('body'),
|
||||
|
@ -634,9 +619,6 @@
|
|||
confirmDialog.render();
|
||||
};
|
||||
|
||||
window.showSeedDialog = window.owsDesktopApp.appView.showSeedDialog;
|
||||
window.showPasswordDialog = window.owsDesktopApp.appView.showPasswordDialog;
|
||||
|
||||
window.showEditProfileDialog = async callback => {
|
||||
const ourNumber = window.storage.get('primaryDevicePubKey');
|
||||
const conversation = await ConversationController.getOrCreateAndWait(
|
||||
|
@ -930,7 +912,9 @@
|
|||
window.log.warn(`Could not connect to ${serverAddress}`);
|
||||
return;
|
||||
}
|
||||
appView.openConversation(conversationId, {});
|
||||
window.inboxStore.dispatch(
|
||||
window.actionsCreators.openConversationExternal(conversationId)
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -943,7 +927,9 @@
|
|||
Whisper.Notifications.on('click', (id, messageId) => {
|
||||
window.showWindow();
|
||||
if (id) {
|
||||
appView.openConversation(id, messageId);
|
||||
window.inboxStore.dispatch(
|
||||
window.actionsCreators.openConversationExternal(id, messageId)
|
||||
);
|
||||
} else {
|
||||
appView.openInbox({
|
||||
initialLoadComplete,
|
||||
|
@ -981,7 +967,9 @@
|
|||
avatarPath,
|
||||
isRss: conversation.isRss(),
|
||||
onStartConversation: () => {
|
||||
Whisper.events.trigger('showConversation', userPubKey);
|
||||
window.inboxStore.dispatch(
|
||||
window.actionsCreators.openConversationExternal(conversation.id)
|
||||
);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
@ -1308,24 +1296,24 @@
|
|||
}
|
||||
|
||||
function onChangeTheme() {
|
||||
const view = window.owsDesktopApp.appView;
|
||||
if (view) {
|
||||
view.applyTheme();
|
||||
}
|
||||
// const view = window.owsDesktopApp.appView;
|
||||
// if (view) {
|
||||
// view.applyTheme();
|
||||
// }
|
||||
}
|
||||
function onEmpty() {
|
||||
initialLoadComplete = true;
|
||||
|
||||
window.readyForUpdates();
|
||||
|
||||
let interval = setInterval(() => {
|
||||
const view = window.owsDesktopApp.appView;
|
||||
if (view) {
|
||||
clearInterval(interval);
|
||||
interval = null;
|
||||
view.onEmpty();
|
||||
}
|
||||
}, 500);
|
||||
// let interval = setInterval(() => {
|
||||
// const view = window.owsDesktopApp.appView;
|
||||
// if (view) {
|
||||
// clearInterval(interval);
|
||||
// interval = null;
|
||||
// view.onEmpty();
|
||||
// }
|
||||
// }, 500);
|
||||
|
||||
Whisper.Notifications.enable();
|
||||
}
|
||||
|
@ -1345,10 +1333,10 @@
|
|||
const { count } = ev;
|
||||
window.log.info(`onProgress: Message count is ${count}`);
|
||||
|
||||
const view = window.owsDesktopApp.appView;
|
||||
if (view) {
|
||||
view.onProgress(count);
|
||||
}
|
||||
// const view = window.owsDesktopApp.appView;
|
||||
// if (view) {
|
||||
// view.onProgress(count);
|
||||
// }
|
||||
}
|
||||
function onConfiguration(ev) {
|
||||
const { configuration } = ev;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* global Whisper, Backbone, textsecure, libsignal, log */
|
||||
/* global Whisper, textsecure, libsignal, log */
|
||||
|
||||
/* eslint-disable more/no-then */
|
||||
|
||||
|
@ -9,33 +9,7 @@
|
|||
window.Whisper = window.Whisper || {};
|
||||
|
||||
const conversations = new Whisper.ConversationCollection();
|
||||
const inboxCollection = new (Backbone.Collection.extend({
|
||||
initialize() {
|
||||
this.listenTo(conversations, 'add change:active_at', this.addActive);
|
||||
this.listenTo(conversations, 'reset', () => this.reset([]));
|
||||
this.listenTo(conversations, 'remove', this.remove);
|
||||
|
||||
this.startPruning();
|
||||
},
|
||||
addActive(model) {
|
||||
if (model.get('active_at')) {
|
||||
this.add(model);
|
||||
model.updateLastMessage();
|
||||
} else {
|
||||
this.remove(model);
|
||||
}
|
||||
},
|
||||
startPruning() {
|
||||
const halfHour = 30 * 60 * 1000;
|
||||
this.interval = setInterval(() => {
|
||||
this.forEach(conversation => {
|
||||
conversation.trigger('prune');
|
||||
});
|
||||
}, halfHour);
|
||||
},
|
||||
}))();
|
||||
|
||||
window.getInboxCollection = () => inboxCollection;
|
||||
window.getConversations = () => conversations;
|
||||
|
||||
window.getMessagesByKey = async key => {
|
||||
|
@ -154,6 +128,15 @@
|
|||
window.SnodePool.getSnodesFor(id),
|
||||
]);
|
||||
}
|
||||
if (window.inboxStore) {
|
||||
conversation.on('change', this.updateReduxConvoChanged);
|
||||
window.inboxStore.dispatch(
|
||||
window.actionsCreators.conversationAdded(
|
||||
conversation.id,
|
||||
conversation.getProps()
|
||||
)
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
return conversation;
|
||||
|
@ -203,7 +186,13 @@
|
|||
await window.Signal.Data.removeConversation(id, {
|
||||
Conversation: Whisper.Conversation,
|
||||
});
|
||||
conversation.off('change', this.updateReduxConvoChanged);
|
||||
conversations.remove(conversation);
|
||||
if (window.inboxStore) {
|
||||
window.inboxStore.dispatch(
|
||||
window.actionsCreators.conversationRemoved(conversation.id)
|
||||
);
|
||||
}
|
||||
},
|
||||
getOrCreateAndWait(id, type) {
|
||||
return this._initialPromise.then(() => {
|
||||
|
@ -237,6 +226,22 @@
|
|||
this._initialPromise = Promise.resolve();
|
||||
this._initialFetchComplete = false;
|
||||
conversations.reset([]);
|
||||
if (window.inboxStore) {
|
||||
conversations.forEach(convo =>
|
||||
convo.off('change', this.updateReduxConvoChanged)
|
||||
);
|
||||
|
||||
window.inboxStore.dispatch(
|
||||
window.actionsCreators.removeAllConversations()
|
||||
);
|
||||
}
|
||||
},
|
||||
updateReduxConvoChanged(convo) {
|
||||
if (window.inboxStore) {
|
||||
window.inboxStore.dispatch(
|
||||
window.actionsCreators.conversationChanged(convo.id, convo.getProps())
|
||||
);
|
||||
}
|
||||
},
|
||||
async load() {
|
||||
window.log.info('ConversationController: starting initial fetch');
|
||||
|
@ -265,6 +270,10 @@
|
|||
conversation.updateProfileAvatar(),
|
||||
]);
|
||||
});
|
||||
conversations.forEach(conversation => {
|
||||
// register for change event on each conversation, and forward to redux
|
||||
conversation.on('change', this.updateReduxConvoChanged);
|
||||
});
|
||||
await Promise.all(promises);
|
||||
|
||||
// Remove any unused images
|
||||
|
|
|
@ -598,7 +598,6 @@
|
|||
isExpired: this.hasExpired,
|
||||
expirationLength,
|
||||
expirationTimestamp,
|
||||
multiSelectMode: conversation && conversation.selectedMessages.size > 0,
|
||||
isPublic: !!this.get('isPublic'),
|
||||
isRss: !!this.get('isRss'),
|
||||
isKickedFromGroup:
|
||||
|
|
|
@ -49,7 +49,9 @@ const { SessionModal } = require('../../ts/components/session/SessionModal');
|
|||
const {
|
||||
SessionSeedModal,
|
||||
} = require('../../ts/components/session/SessionSeedModal');
|
||||
const { SessionInboxView} = require('../../ts/components/session/SessionInboxView')
|
||||
const {
|
||||
SessionInboxView,
|
||||
} = require('../../ts/components/session/SessionInboxView');
|
||||
const {
|
||||
SessionPasswordModal,
|
||||
} = require('../../ts/components/session/SessionPasswordModal');
|
||||
|
|
|
@ -123,25 +123,18 @@
|
|||
return Promise.resolve();
|
||||
},
|
||||
onEmpty() {
|
||||
const view = this.inboxView;
|
||||
// const view = this.inboxView;
|
||||
|
||||
this.initialLoadComplete = true;
|
||||
if (view) {
|
||||
view.onEmpty();
|
||||
}
|
||||
// this.initialLoadComplete = true;
|
||||
// if (view) {
|
||||
// view.onEmpty();
|
||||
// }
|
||||
},
|
||||
onProgress(count) {
|
||||
const view = this.inboxView;
|
||||
if (view) {
|
||||
view.onProgress(count);
|
||||
}
|
||||
},
|
||||
openConversation(id, messageId) {
|
||||
if (id) {
|
||||
this.openInbox().then(() => {
|
||||
this.inboxView.openConversation(id, messageId);
|
||||
});
|
||||
}
|
||||
// const view = this.inboxView;
|
||||
// if (view) {
|
||||
// view.onProgress(count);
|
||||
// }
|
||||
},
|
||||
showEditProfileDialog(options) {
|
||||
const dialog = new Whisper.EditProfileDialogView(options);
|
||||
|
|
|
@ -1,15 +1,11 @@
|
|||
/*
|
||||
global
|
||||
$
|
||||
ConversationController,
|
||||
extension,
|
||||
ConversationController
|
||||
getConversations,
|
||||
getInboxCollection,
|
||||
i18n,
|
||||
Whisper,
|
||||
textsecure,
|
||||
Signal,
|
||||
*/
|
||||
|
||||
// eslint-disable-next-line func-names
|
||||
|
@ -18,11 +14,6 @@
|
|||
|
||||
window.Whisper = window.Whisper || {};
|
||||
|
||||
Whisper.AppLoadingScreen = Whisper.View.extend({
|
||||
templateName: 'app-loading-screen',
|
||||
className: 'app-loading-screen',
|
||||
});
|
||||
|
||||
Whisper.InboxViewWhisper = Whisper.View.extend({
|
||||
templateName: 'two-column',
|
||||
className: 'inbox index',
|
||||
|
@ -67,35 +58,6 @@
|
|||
this.setupLeftPane();
|
||||
},
|
||||
|
||||
|
||||
|
||||
|
||||
startConnectionListener() {
|
||||
this.interval = setInterval(() => {
|
||||
const status = window.getSocketStatus();
|
||||
switch (status) {
|
||||
case WebSocket.CONNECTING:
|
||||
break;
|
||||
case WebSocket.OPEN:
|
||||
clearInterval(this.interval);
|
||||
// Default to connected, but lokinet is slow so we pretend empty event
|
||||
this.onEmpty();
|
||||
this.interval = null;
|
||||
break;
|
||||
case WebSocket.CLOSING:
|
||||
case WebSocket.CLOSED:
|
||||
clearInterval(this.interval);
|
||||
this.interval = null;
|
||||
// if we failed to connect, we pretend we got an empty event
|
||||
this.onEmpty();
|
||||
break;
|
||||
default:
|
||||
// We also replicate empty here
|
||||
this.onEmpty();
|
||||
break;
|
||||
}
|
||||
}, 1000);
|
||||
},
|
||||
onEmpty() {
|
||||
const view = this.appLoadingScreen;
|
||||
if (view) {
|
||||
|
|
|
@ -2,27 +2,27 @@
|
|||
|
||||
// eslint-disable-next-line func-names
|
||||
(function() {
|
||||
'use strict';
|
||||
'use strict';
|
||||
|
||||
window.Whisper = window.Whisper || {};
|
||||
window.Whisper = window.Whisper || {};
|
||||
|
||||
Whisper.InboxView = Whisper.View.extend({
|
||||
initialize() {
|
||||
this.render();
|
||||
},
|
||||
Whisper.InboxView = Whisper.View.extend({
|
||||
initialize() {
|
||||
this.render();
|
||||
},
|
||||
|
||||
render() {
|
||||
this.dialogView = new Whisper.ReactWrapperView({
|
||||
className: 'inbox index',
|
||||
Component: window.Signal.Components.SessionInboxView,
|
||||
});
|
||||
render() {
|
||||
this.dialogView = new Whisper.ReactWrapperView({
|
||||
className: 'inbox index',
|
||||
Component: window.Signal.Components.SessionInboxView,
|
||||
});
|
||||
|
||||
this.$el.append(this.dialogView.el);
|
||||
return this;
|
||||
},
|
||||
this.$el.append(this.dialogView.el);
|
||||
return this;
|
||||
},
|
||||
|
||||
close() {
|
||||
this.remove();
|
||||
},
|
||||
});
|
||||
})();
|
||||
close() {
|
||||
this.remove();
|
||||
},
|
||||
});
|
||||
})();
|
||||
|
|
7
main.js
7
main.js
|
@ -513,12 +513,6 @@ function setupWithImport() {
|
|||
}
|
||||
}
|
||||
|
||||
function setupAsStandalone() {
|
||||
if (mainWindow) {
|
||||
mainWindow.webContents.send('set-up-as-standalone');
|
||||
}
|
||||
}
|
||||
|
||||
let passwordWindow;
|
||||
function showPasswordWindow() {
|
||||
if (passwordWindow) {
|
||||
|
@ -868,7 +862,6 @@ function setupMenu(options) {
|
|||
openSupportPage,
|
||||
platform,
|
||||
setupWithImport,
|
||||
setupAsStandalone,
|
||||
});
|
||||
const template = createTemplate(menuOptions, locale.messages);
|
||||
const menu = Menu.buildFromTemplate(template);
|
||||
|
|
|
@ -240,10 +240,6 @@ ipc.on('set-up-with-import', () => {
|
|||
Whisper.events.trigger('setupWithImport');
|
||||
});
|
||||
|
||||
ipc.on('set-up-as-standalone', () => {
|
||||
Whisper.events.trigger('setupAsStandalone');
|
||||
});
|
||||
|
||||
ipc.on('get-theme-setting', () => {
|
||||
const theme = window.Events.getThemeSetting();
|
||||
ipc.send('get-success-theme-setting', theme);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
.inbox {
|
||||
.inbox {
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
|
|
@ -27,49 +27,20 @@
|
|||
}
|
||||
}
|
||||
|
||||
.conversation-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-grow: 1;
|
||||
.conversation-item__options-pane {
|
||||
position: absolute;
|
||||
height: 100%;
|
||||
outline: none;
|
||||
right: 0vw;
|
||||
|
||||
.selection-mode {
|
||||
.messages-container > *:not(.message-selected) {
|
||||
animation: toShadow $session-transition-duration;
|
||||
opacity: 0.25;
|
||||
}
|
||||
transition: transform 1.5 * $session-transition-duration ease-in-out;
|
||||
transform: translateX(100%);
|
||||
will-change: transform;
|
||||
width: 25vw;
|
||||
|
||||
.conversation-header {
|
||||
.conversation-header {
|
||||
&--items-wrapper {
|
||||
.session-icon {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
user-select: none;
|
||||
pointer-events: none;
|
||||
opacity: 0.25;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&__options-pane {
|
||||
position: absolute;
|
||||
height: 100%;
|
||||
right: 0vw;
|
||||
|
||||
transition: transform 1.5 * $session-transition-duration ease-in-out;
|
||||
transform: translateX(100%);
|
||||
will-change: transform;
|
||||
width: 25vw;
|
||||
|
||||
&.show {
|
||||
transform: none;
|
||||
transition: transform $session-transition-duration ease-in-out;
|
||||
z-index: 2;
|
||||
}
|
||||
&.show {
|
||||
transform: none;
|
||||
transition: transform $session-transition-duration ease-in-out;
|
||||
z-index: 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -116,6 +87,28 @@
|
|||
flex-grow: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
max-width: calc(100vw - 380px);
|
||||
|
||||
.selection-mode {
|
||||
.messages-container > *:not(.message-selected) {
|
||||
animation: toShadow $session-transition-duration;
|
||||
opacity: 0.25;
|
||||
}
|
||||
|
||||
.conversation-header {
|
||||
.conversation-header {
|
||||
&--items-wrapper {
|
||||
.session-icon {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
user-select: none;
|
||||
pointer-events: none;
|
||||
opacity: 0.25;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.conversation-content {
|
||||
|
@ -173,7 +166,6 @@
|
|||
flex-grow: 1;
|
||||
flex-direction: column-reverse;
|
||||
position: relative;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
min-width: 370px;
|
||||
scrollbar-width: 4px;
|
||||
|
|
|
@ -108,9 +108,11 @@ $session-compose-margin: 20px;
|
|||
&__sections-container {
|
||||
height: 100vh;
|
||||
flex-shrink: 0;
|
||||
width: 80px;
|
||||
overflow-x: hidden;
|
||||
display: inline-flex;
|
||||
flex-direction: column;
|
||||
overflow: auto;
|
||||
|
||||
@include themify($themes) {
|
||||
border-right: themed('sessionBorder');
|
||||
}
|
||||
|
|
|
@ -51,7 +51,6 @@ describe('SignalMenu', () => {
|
|||
openSupportPage: null,
|
||||
platform,
|
||||
includeSetup,
|
||||
setupAsStandalone: null,
|
||||
setupWithImport: null,
|
||||
showAbout: null,
|
||||
showDebugLog: null,
|
||||
|
|
|
@ -168,7 +168,11 @@ export class LeftPane extends React.Component<Props> {
|
|||
}
|
||||
|
||||
private renderSettingSection() {
|
||||
const { isSecondaryDevice, showSessionSettingsCategory, settingsCategory } = this.props;
|
||||
const {
|
||||
isSecondaryDevice,
|
||||
showSessionSettingsCategory,
|
||||
settingsCategory,
|
||||
} = this.props;
|
||||
|
||||
const category = settingsCategory || SessionSettingCategory.Appearance;
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ export type PropsData = {
|
|||
|
||||
type PropsHousekeeping = {
|
||||
i18n: LocalizerType;
|
||||
openConversation: (id: string, messageId?: string) => void;
|
||||
openConversationExternal: (id: string, messageId?: string) => void;
|
||||
};
|
||||
|
||||
type Props = PropsData & PropsHousekeeping;
|
||||
|
@ -34,7 +34,7 @@ export class SearchResults extends React.Component<Props> {
|
|||
hideMessagesHeader,
|
||||
i18n,
|
||||
messages,
|
||||
openConversation,
|
||||
openConversationExternal,
|
||||
searchTerm,
|
||||
} = this.props;
|
||||
|
||||
|
@ -59,14 +59,14 @@ export class SearchResults extends React.Component<Props> {
|
|||
<ConversationListItemWithDetails
|
||||
key={conversation.phoneNumber}
|
||||
{...conversation}
|
||||
onClick={openConversation}
|
||||
onClick={openConversationExternal}
|
||||
i18n={i18n}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
) : null}
|
||||
{haveContacts
|
||||
? this.renderContacts(i18n('contactsHeader'), contacts, true)
|
||||
? this.renderContacts(i18n('contactsHeader'), contacts)
|
||||
: null}
|
||||
|
||||
{haveMessages ? (
|
||||
|
@ -80,7 +80,7 @@ export class SearchResults extends React.Component<Props> {
|
|||
<MessageSearchResult
|
||||
key={message.id}
|
||||
{...message}
|
||||
onClick={openConversation}
|
||||
onClick={openConversationExternal}
|
||||
i18n={i18n}
|
||||
/>
|
||||
))}
|
||||
|
@ -91,10 +91,9 @@ export class SearchResults extends React.Component<Props> {
|
|||
}
|
||||
private renderContacts(
|
||||
header: string,
|
||||
items: Array<ConversationListItemPropsType>,
|
||||
contacts?: boolean
|
||||
items: Array<ConversationListItemPropsType>
|
||||
) {
|
||||
const { i18n, openConversation } = this.props;
|
||||
const { i18n, openConversationExternal } = this.props;
|
||||
|
||||
return (
|
||||
<div className="module-search-results__contacts">
|
||||
|
@ -103,7 +102,7 @@ export class SearchResults extends React.Component<Props> {
|
|||
<ConversationListItemWithDetails
|
||||
key={contact.phoneNumber}
|
||||
{...contact}
|
||||
onClick={openConversation}
|
||||
onClick={openConversationExternal}
|
||||
i18n={i18n}
|
||||
/>
|
||||
))}
|
||||
|
|
|
@ -127,7 +127,13 @@ export class LeftPaneContactSection extends React.Component<Props, State> {
|
|||
if (error) {
|
||||
ToastUtils.pushToastError('addContact', error);
|
||||
} else {
|
||||
window.Whisper.events.trigger('showConversation', sessionID);
|
||||
// tslint:disable-next-line: no-floating-promises
|
||||
window.ConversationController.getOrCreateAndWait(
|
||||
sessionID,
|
||||
'private'
|
||||
).then(() => {
|
||||
this.props.openConversationExternal(sessionID);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -144,7 +144,7 @@ export class LeftPaneMessageSection extends React.Component<Props, State> {
|
|||
<SearchResults
|
||||
{...searchResults}
|
||||
contacts={contacts}
|
||||
openConversation={openConversationExternal}
|
||||
openConversationExternal={openConversationExternal}
|
||||
i18n={window.i18n}
|
||||
/>
|
||||
);
|
||||
|
@ -378,7 +378,7 @@ export class LeftPaneMessageSection extends React.Component<Props, State> {
|
|||
this.setState({ valuePasted: value });
|
||||
}
|
||||
|
||||
private handleMessageButtonClick() {
|
||||
private async handleMessageButtonClick() {
|
||||
const { openConversationExternal } = this.props;
|
||||
|
||||
if (!this.state.valuePasted && !this.props.searchTerm) {
|
||||
|
@ -394,6 +394,7 @@ export class LeftPaneMessageSection extends React.Component<Props, State> {
|
|||
|
||||
const error = validateNumber(pubkey);
|
||||
if (!error) {
|
||||
await window.ConversationController.getOrCreateAndWait(pubkey, 'private');
|
||||
openConversationExternal(pubkey);
|
||||
} else {
|
||||
ToastUtils.pushToastError('invalidPubKey', error);
|
||||
|
|
|
@ -58,7 +58,7 @@ export class LeftPaneSettingSection extends React.Component<Props, State> {
|
|||
}
|
||||
|
||||
public renderRow(item: any): JSX.Element {
|
||||
const {settingsCategory} = this.props;
|
||||
const { settingsCategory } = this.props;
|
||||
return (
|
||||
<div
|
||||
key={item.id}
|
||||
|
|
|
@ -6,14 +6,16 @@ import { createStore } from '../../state/createStore';
|
|||
import { StateType } from '../../state/reducer';
|
||||
import { SmartLeftPane } from '../../state/smart/LeftPane';
|
||||
import { SmartSessionConversation } from '../../state/smart/SessionConversation';
|
||||
import { SessionSettingCategory, SettingsView } from './settings/SessionSettings';
|
||||
import {
|
||||
SessionSettingCategory,
|
||||
SettingsView,
|
||||
} from './settings/SessionSettings';
|
||||
|
||||
// Workaround: A react component's required properties are filtering up through connect()
|
||||
// https://github.com/DefinitelyTyped/DefinitelyTyped/issues/31363
|
||||
const FilteredLeftPane = SmartLeftPane as any;
|
||||
const FilteredSessionConversation = SmartSessionConversation as any;
|
||||
|
||||
|
||||
type Props = {
|
||||
focusedSection: number;
|
||||
};
|
||||
|
@ -21,38 +23,44 @@ type Props = {
|
|||
type State = {
|
||||
isInitialLoadComplete: boolean;
|
||||
settingsCategory?: SessionSettingCategory;
|
||||
networkError: boolean;
|
||||
};
|
||||
|
||||
// tslint:disable: react-a11y-img-has-alt
|
||||
|
||||
|
||||
export class SessionInboxView extends React.Component<Props, State> {
|
||||
private store: any;
|
||||
private store: any;
|
||||
private interval: NodeJS.Timeout | null = null;
|
||||
|
||||
constructor(props: any) {
|
||||
super(props);
|
||||
this.state = {
|
||||
isInitialLoadComplete: false,
|
||||
settingsCategory: undefined,
|
||||
};
|
||||
constructor(props: any) {
|
||||
super(props);
|
||||
this.state = {
|
||||
isInitialLoadComplete: false,
|
||||
settingsCategory: undefined,
|
||||
networkError: false,
|
||||
};
|
||||
|
||||
// Inbox
|
||||
const inboxCollection = window.getInboxCollection();
|
||||
this.fetchHandleMessageSentData = this.fetchHandleMessageSentData.bind(
|
||||
this
|
||||
);
|
||||
this.handleMessageSentFailure = this.handleMessageSentFailure.bind(this);
|
||||
this.handleMessageSentSuccess = this.handleMessageSentSuccess.bind(this);
|
||||
this.showSessionSettingsCategory = this.showSessionSettingsCategory.bind(this);
|
||||
this.showSessionViewConversation = this.showSessionViewConversation.bind(this);
|
||||
const conversationModels = window.getConversations();
|
||||
this.fetchHandleMessageSentData = this.fetchHandleMessageSentData.bind(
|
||||
this
|
||||
);
|
||||
this.handleMessageSentFailure = this.handleMessageSentFailure.bind(this);
|
||||
this.handleMessageSentSuccess = this.handleMessageSentSuccess.bind(this);
|
||||
this.showSessionSettingsCategory = this.showSessionSettingsCategory.bind(
|
||||
this
|
||||
);
|
||||
this.showSessionViewConversation = this.showSessionViewConversation.bind(
|
||||
this
|
||||
);
|
||||
|
||||
void this.setupLeftPane();
|
||||
void this.setupLeftPane();
|
||||
|
||||
// ConversationCollection
|
||||
// ConversationCollection
|
||||
conversationModels;
|
||||
// this.listenTo(inboxCollection, 'messageError', () => {
|
||||
// if (this.networkStatusView) {
|
||||
// this.networkStatusView.render();
|
||||
// }
|
||||
// if (this.networkStatusView) {
|
||||
// this.networkStatusView.render();
|
||||
// }
|
||||
// });
|
||||
|
||||
// this.networkStatusView = new Whisper.NetworkStatusView();
|
||||
|
@ -67,24 +75,26 @@ export class SessionInboxView extends React.Component<Props, State> {
|
|||
// this.$el.addClass('expired');
|
||||
// }
|
||||
// });
|
||||
}
|
||||
|
||||
public render() {
|
||||
if (!this.state.isInitialLoadComplete) {
|
||||
return <></>;
|
||||
}
|
||||
|
||||
|
||||
public render() {
|
||||
if (!this.state.isInitialLoadComplete) {
|
||||
return <></>;
|
||||
}
|
||||
|
||||
const isSettingsView = this.state.settingsCategory !== undefined;
|
||||
return (
|
||||
<Provider store={this.store}>
|
||||
<div className="gutter">
|
||||
<div className="network-status-container"/>
|
||||
{this.renderLeftPane()}
|
||||
</div>
|
||||
{isSettingsView ? this.renderSettings() : this.renderSessionConversation()}
|
||||
</Provider>
|
||||
); }
|
||||
const isSettingsView = this.state.settingsCategory !== undefined;
|
||||
return (
|
||||
<Provider store={this.store}>
|
||||
<div className="gutter">
|
||||
<div className="network-status-container" />
|
||||
{this.renderLeftPane()}
|
||||
</div>
|
||||
{isSettingsView
|
||||
? this.renderSettings()
|
||||
: this.renderSessionConversation()}
|
||||
</Provider>
|
||||
);
|
||||
}
|
||||
|
||||
private renderLeftPane() {
|
||||
return (
|
||||
|
@ -97,14 +107,14 @@ export class SessionInboxView extends React.Component<Props, State> {
|
|||
}
|
||||
|
||||
private renderSettings() {
|
||||
const isSecondaryDevice = !!window.textsecure.storage.get('isSecondaryDevice');
|
||||
const category = this.state.settingsCategory || SessionSettingCategory.Appearance;
|
||||
const isSecondaryDevice = !!window.textsecure.storage.get(
|
||||
'isSecondaryDevice'
|
||||
);
|
||||
const category =
|
||||
this.state.settingsCategory || SessionSettingCategory.Appearance;
|
||||
|
||||
return (
|
||||
<SettingsView
|
||||
isSecondaryDevice={isSecondaryDevice}
|
||||
category={category}
|
||||
/>
|
||||
<SettingsView isSecondaryDevice={isSecondaryDevice} category={category} />
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -114,154 +124,134 @@ export class SessionInboxView extends React.Component<Props, State> {
|
|||
<FilteredSessionConversation />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private async fetchHandleMessageSentData(m: any) {
|
||||
// nobody is listening to this freshly fetched message .trigger calls
|
||||
const tmpMsg = await window.Signal.Data.getMessageById(m.identifier, {
|
||||
Message: window.Whisper.Message,
|
||||
});
|
||||
private async fetchHandleMessageSentData(m: any) {
|
||||
// nobody is listening to this freshly fetched message .trigger calls
|
||||
const tmpMsg = await window.Signal.Data.getMessageById(m.identifier, {
|
||||
Message: window.Whisper.Message,
|
||||
});
|
||||
|
||||
if (!tmpMsg) {
|
||||
return null;
|
||||
}
|
||||
if (!tmpMsg) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// find the corresponding conversation of this message
|
||||
const conv = window.ConversationController.get(
|
||||
tmpMsg.get('conversationId')
|
||||
);
|
||||
// find the corresponding conversation of this message
|
||||
const conv = window.ConversationController.get(
|
||||
tmpMsg.get('conversationId')
|
||||
);
|
||||
|
||||
if (!conv) {
|
||||
return null;
|
||||
}
|
||||
if (!conv) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// then, find in this conversation the very same message
|
||||
// const msg = conv.messageCollection.models.find(
|
||||
// convMsg => convMsg.id === tmpMsg.id
|
||||
// );
|
||||
const msg = window.MessageController._get()[m.identifier];
|
||||
// then, find in this conversation the very same message
|
||||
// const msg = conv.messageCollection.models.find(
|
||||
// convMsg => convMsg.id === tmpMsg.id
|
||||
// );
|
||||
const msg = window.MessageController._get()[m.identifier];
|
||||
|
||||
if (!msg || !msg.message) {
|
||||
return null;
|
||||
}
|
||||
if (!msg || !msg.message) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return { msg: msg.message };
|
||||
}
|
||||
return { msg: msg.message };
|
||||
}
|
||||
|
||||
private async handleMessageSentSuccess(sentMessage: any, wrappedEnvelope: any) {
|
||||
const fetchedData = await this.fetchHandleMessageSentData(sentMessage);
|
||||
if (!fetchedData) {
|
||||
return;
|
||||
}
|
||||
const { msg } = fetchedData;
|
||||
private async handleMessageSentSuccess(
|
||||
sentMessage: any,
|
||||
wrappedEnvelope: any
|
||||
) {
|
||||
const fetchedData = await this.fetchHandleMessageSentData(sentMessage);
|
||||
if (!fetchedData) {
|
||||
return;
|
||||
}
|
||||
const { msg } = fetchedData;
|
||||
|
||||
msg.handleMessageSentSuccess(sentMessage, wrappedEnvelope);
|
||||
}
|
||||
msg.handleMessageSentSuccess(sentMessage, wrappedEnvelope);
|
||||
}
|
||||
|
||||
private async handleMessageSentFailure(sentMessage: any, error: any) {
|
||||
const fetchedData = await this.fetchHandleMessageSentData(sentMessage);
|
||||
if (!fetchedData) {
|
||||
return;
|
||||
}
|
||||
const { msg } = fetchedData;
|
||||
private async handleMessageSentFailure(sentMessage: any, error: any) {
|
||||
const fetchedData = await this.fetchHandleMessageSentData(sentMessage);
|
||||
if (!fetchedData) {
|
||||
return;
|
||||
}
|
||||
const { msg } = fetchedData;
|
||||
|
||||
await msg.handleMessageSentFailure(sentMessage, error);
|
||||
}
|
||||
await msg.handleMessageSentFailure(sentMessage, error);
|
||||
}
|
||||
|
||||
private async setupLeftPane() {
|
||||
// Here we set up a full redux store with initial state for our LeftPane Root
|
||||
const convoCollection = window.getConversations();
|
||||
const conversations = convoCollection.map(
|
||||
(conversation: any) => conversation.cachedProps
|
||||
);
|
||||
private async setupLeftPane() {
|
||||
// Here we set up a full redux store with initial state for our LeftPane Root
|
||||
const convoCollection = window.getConversations();
|
||||
const conversations = convoCollection.map(
|
||||
(conversation: any) => conversation.cachedProps
|
||||
);
|
||||
|
||||
const filledConversations = conversations.map(async (conv: any) => {
|
||||
const messages = await window.getMessagesByKey(conv.id);
|
||||
return { ...conv, messages };
|
||||
});
|
||||
const filledConversations = conversations.map(async (conv: any) => {
|
||||
const messages = await window.getMessagesByKey(conv.id);
|
||||
return { ...conv, messages };
|
||||
});
|
||||
|
||||
const fullFilledConversations = await Promise.all(filledConversations);
|
||||
const fullFilledConversations = await Promise.all(filledConversations);
|
||||
|
||||
const initialState = {
|
||||
conversations: {
|
||||
conversationLookup: window.Signal.Util.makeLookup(
|
||||
fullFilledConversations,
|
||||
'id'
|
||||
),
|
||||
},
|
||||
user: {
|
||||
regionCode: window.storage.get('regionCode'),
|
||||
ourNumber:
|
||||
window.storage.get('primaryDevicePubKey') ||
|
||||
window.textsecure.storage.user.getNumber(),
|
||||
isSecondaryDevice: !!window.storage.get('isSecondaryDevice'),
|
||||
i18n: window.i18n,
|
||||
},
|
||||
section: {
|
||||
focusedSection: 1,
|
||||
},
|
||||
};
|
||||
const initialState = {
|
||||
conversations: {
|
||||
conversationLookup: window.Signal.Util.makeLookup(
|
||||
fullFilledConversations,
|
||||
'id'
|
||||
),
|
||||
},
|
||||
user: {
|
||||
regionCode: window.storage.get('regionCode'),
|
||||
ourNumber:
|
||||
window.storage.get('primaryDevicePubKey') ||
|
||||
window.textsecure.storage.user.getNumber(),
|
||||
isSecondaryDevice: !!window.storage.get('isSecondaryDevice'),
|
||||
i18n: window.i18n,
|
||||
},
|
||||
section: {
|
||||
focusedSection: 1,
|
||||
},
|
||||
};
|
||||
|
||||
this.store = createStore(initialState);
|
||||
window.inboxStore = this.store;
|
||||
this.store = createStore(initialState);
|
||||
window.inboxStore = this.store;
|
||||
|
||||
// Enables our redux store to be updated by backbone events in the outside world
|
||||
const {
|
||||
conversationAdded,
|
||||
conversationChanged,
|
||||
conversationRemoved,
|
||||
removeAllConversations,
|
||||
messageExpired,
|
||||
openConversationExternal,
|
||||
} = bindActionCreators(
|
||||
window.Signal.State.Ducks.conversations.actions,
|
||||
this.store.dispatch
|
||||
);
|
||||
const { userChanged } = bindActionCreators(
|
||||
window.Signal.State.Ducks.user.actions,
|
||||
this.store.dispatch
|
||||
);
|
||||
const { messageChanged } = bindActionCreators(
|
||||
window.Signal.State.Ducks.messages.actions,
|
||||
this.store.dispatch
|
||||
);
|
||||
// Enables our redux store to be updated by backbone events in the outside world
|
||||
const { messageExpired } = bindActionCreators(
|
||||
window.Signal.State.Ducks.conversations.actions,
|
||||
this.store.dispatch
|
||||
);
|
||||
window.actionsCreators = window.Signal.State.Ducks.conversations.actions;
|
||||
const { userChanged } = bindActionCreators(
|
||||
window.Signal.State.Ducks.user.actions,
|
||||
this.store.dispatch
|
||||
);
|
||||
const { messageChanged } = bindActionCreators(
|
||||
window.Signal.State.Ducks.messages.actions,
|
||||
this.store.dispatch
|
||||
);
|
||||
|
||||
// this.openConversationAction = openConversationExternal;
|
||||
this.fetchHandleMessageSentData = this.fetchHandleMessageSentData.bind(
|
||||
this
|
||||
);
|
||||
this.handleMessageSentFailure = this.handleMessageSentFailure.bind(this);
|
||||
this.handleMessageSentSuccess = this.handleMessageSentSuccess.bind(this);
|
||||
|
||||
this.fetchHandleMessageSentData = this.fetchHandleMessageSentData.bind(
|
||||
this
|
||||
);
|
||||
this.handleMessageSentFailure = this.handleMessageSentFailure.bind(this);
|
||||
this.handleMessageSentSuccess = this.handleMessageSentSuccess.bind(this);
|
||||
getMessageQueue().events.addListener(
|
||||
'success',
|
||||
this.handleMessageSentSuccess
|
||||
);
|
||||
|
||||
// this.listenTo(convoCollection, 'remove', conversation => {
|
||||
// const { id } = conversation || {};
|
||||
// conversationRemoved(id);
|
||||
// });
|
||||
// this.listenTo(convoCollection, 'add', conversation => {
|
||||
// const { id, cachedProps } = conversation || {};
|
||||
// conversationAdded(id, cachedProps);
|
||||
// });
|
||||
// this.listenTo(convoCollection, 'change', conversation => {
|
||||
// const { id, cachedProps } = conversation || {};
|
||||
// conversationChanged(id, cachedProps);
|
||||
// });
|
||||
// this.listenTo(convoCollection, 'reset', removeAllConversations);
|
||||
getMessageQueue().events.addListener('fail', this.handleMessageSentFailure);
|
||||
|
||||
getMessageQueue()
|
||||
.events.addListener('success', this.handleMessageSentSuccess);
|
||||
window.Whisper.events.on('messageExpired', messageExpired);
|
||||
window.Whisper.events.on('messageChanged', messageChanged);
|
||||
window.Whisper.events.on('userChanged', userChanged);
|
||||
|
||||
getMessageQueue()
|
||||
.events.addListener('fail', this.handleMessageSentFailure);
|
||||
|
||||
window.Whisper.events.on('messageExpired', messageExpired);
|
||||
window.Whisper.events.on('messageChanged', messageChanged);
|
||||
window.Whisper.events.on('userChanged', userChanged);
|
||||
|
||||
// Finally, add it to the DOM
|
||||
// this.$('.left-pane-placeholder').append(this.leftPaneView.el);
|
||||
this.setState({ isInitialLoadComplete: true });
|
||||
}
|
||||
this.setState({ isInitialLoadComplete: true });
|
||||
}
|
||||
|
||||
private showSessionSettingsCategory(category: SessionSettingCategory) {
|
||||
this.setState({ settingsCategory: category });
|
||||
|
@ -270,4 +260,34 @@ export class SessionInboxView extends React.Component<Props, State> {
|
|||
private showSessionViewConversation() {
|
||||
this.setState({ settingsCategory: undefined });
|
||||
}
|
||||
|
||||
// private startConnectionListener() {
|
||||
// this.interval = global.setInterval(() => {
|
||||
// const status = window.getSocketStatus();
|
||||
// switch (status) {
|
||||
// case WebSocket.CONNECTING:
|
||||
// break;
|
||||
// case WebSocket.OPEN:
|
||||
// if (this.interval) {
|
||||
// clearInterval(this.interval);
|
||||
// }
|
||||
// // Default to connected, but lokinet is slow so we pretend empty event
|
||||
// // this.onEmpty();
|
||||
// this.interval = null;
|
||||
// break;
|
||||
// case WebSocket.CLOSING:
|
||||
// case WebSocket.CLOSED:
|
||||
// if (this.interval) {
|
||||
// clearInterval(this.interval);
|
||||
// }
|
||||
// this.interval = null;
|
||||
// // if we failed to connect, we pretend we got an empty event
|
||||
// // this.onEmpty();
|
||||
// break;
|
||||
// default:
|
||||
// // We also replicate empty here
|
||||
// // this.onEmpty();
|
||||
// }
|
||||
// }, 1000);
|
||||
// }
|
||||
}
|
||||
|
|
|
@ -151,7 +151,6 @@ export class SessionConversation extends React.Component<Props, State> {
|
|||
// ~~~~~~~~~~~~~~~~ LIFECYCLES ~~~~~~~~~~~~~~~~
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
||||
public componentDidUpdate(prevProps: Props, prevState: State) {
|
||||
if (this.props.conversationKey !== prevProps.conversationKey) {
|
||||
void this.loadInitialMessages();
|
||||
|
|
|
@ -128,7 +128,9 @@ export async function createMediumGroup(
|
|||
|
||||
convo.updateGroupAdmins(admins);
|
||||
|
||||
window.owsDesktopApp.appView.openConversation(groupId, {});
|
||||
window.inboxStore.dispatch(
|
||||
window.actionsCreators.openConversationExternal(groupId)
|
||||
);
|
||||
|
||||
// Subscribe to this group id
|
||||
window.SwarmPolling.addGroupId(new PubKey(groupId));
|
||||
|
@ -177,7 +179,9 @@ export async function createLegacyGroup(
|
|||
await sendGroupUpdate(convo, diff, groupDetails, dbMessage.id);
|
||||
|
||||
window.textsecure.messaging.sendGroupSyncMessage([convo]);
|
||||
window.owsDesktopApp.appView.openConversation(groupId, {});
|
||||
window.inboxStore.dispatch(
|
||||
window.actionsCreators.openConversationExternal(groupId)
|
||||
);
|
||||
}
|
||||
|
||||
export async function leaveMediumGroup(groupId: string) {
|
||||
|
|
|
@ -241,7 +241,6 @@ export function reducer(
|
|||
selectedConversation = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
...state,
|
||||
selectedConversation,
|
||||
|
@ -255,7 +254,6 @@ export function reducer(
|
|||
const { payload } = action;
|
||||
const { id } = payload;
|
||||
const { conversationLookup } = state;
|
||||
|
||||
return {
|
||||
...state,
|
||||
conversationLookup: omit(conversationLookup, [id]),
|
||||
|
@ -270,15 +268,10 @@ export function reducer(
|
|||
if (action.type === 'SELECTED_CONVERSATION_CHANGED') {
|
||||
const { payload } = action;
|
||||
const { id } = payload;
|
||||
if (state.selectedConversation !== id) {
|
||||
window.owsDesktopApp.appView.openConversation(id, {});
|
||||
}
|
||||
|
||||
return {
|
||||
...state,
|
||||
selectedConversation: id,
|
||||
};
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
|
|
@ -75,7 +75,6 @@ export const actions = {
|
|||
search,
|
||||
clearSearch,
|
||||
updateSearchTerm,
|
||||
startNewConversation,
|
||||
};
|
||||
|
||||
function search(
|
||||
|
@ -143,22 +142,6 @@ function updateSearchTerm(query: string): UpdateSearchTermActionType {
|
|||
},
|
||||
};
|
||||
}
|
||||
function startNewConversation(
|
||||
query: string,
|
||||
options: { regionCode: string }
|
||||
): ClearSearchActionType {
|
||||
const { regionCode } = options;
|
||||
const normalized = normalize(query, { regionCode });
|
||||
if (!normalized) {
|
||||
throw new Error('Attempted to start new conversation with invalid number');
|
||||
}
|
||||
trigger('showConversation', normalized);
|
||||
|
||||
return {
|
||||
type: 'SEARCH_CLEAR',
|
||||
payload: null,
|
||||
};
|
||||
}
|
||||
|
||||
// Helper functions for search
|
||||
|
||||
|
|
|
@ -40,10 +40,8 @@ function getConversationTitle(
|
|||
|
||||
if (conversation.type === 'group') {
|
||||
const { i18n } = options;
|
||||
|
||||
return i18n('unknown');
|
||||
}
|
||||
|
||||
return format(conversation.phoneNumber, options);
|
||||
}
|
||||
|
||||
|
@ -65,7 +63,6 @@ export const _getConversationComparator = (
|
|||
if (leftTimestamp && rightTimestamp && leftTimestamp !== rightTimestamp) {
|
||||
return rightTimestamp - leftTimestamp;
|
||||
}
|
||||
|
||||
const leftTitle = getConversationTitle(left, {
|
||||
i18n,
|
||||
ourRegionCode,
|
||||
|
|
|
@ -102,7 +102,6 @@ declare global {
|
|||
GroupBuffer: any;
|
||||
SwarmPolling: SwarmPolling;
|
||||
MediaRecorder: any;
|
||||
owsDesktopApp: any;
|
||||
loadImage: any;
|
||||
dataURLToBlobSync: any;
|
||||
autoOrientImage: any;
|
||||
|
@ -112,8 +111,9 @@ declare global {
|
|||
) => Promise<{ pubKey: ArrayBufferLike; privKey: ArrayBufferLike }>;
|
||||
setClockParams: any;
|
||||
clientClockSynced: number | undefined;
|
||||
getInboxCollection: any;
|
||||
getMessagesByKey: any;
|
||||
inboxStore: Store;
|
||||
getSocketStatus: any;
|
||||
actionsCreators: any;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue