From 2f2eb2ad535788ec144a490ca2a89f5d93db10a1 Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Fri, 13 Nov 2020 17:17:48 +1100 Subject: [PATCH] link back backbone conversation events to redux store --- app/menu.js | 22 +- js/background.js | 62 ++- js/conversation_controller.js | 63 +-- js/models/messages.js | 1 - js/modules/signal.js | 4 +- js/views/app_view.js | 25 +- js/views/inbox_view.js | 38 -- js/views/session_inbox_view.js | 38 +- main.js | 7 - preload.js | 4 - stylesheets/_index.scss | 2 +- stylesheets/_session_conversation.scss | 74 ++-- stylesheets/_session_left_pane.scss | 4 +- test/app/menu_test.js | 1 - ts/components/LeftPane.tsx | 6 +- ts/components/SearchResults.tsx | 17 +- .../session/LeftPaneContactSection.tsx | 8 +- .../session/LeftPaneMessageSection.tsx | 5 +- .../session/LeftPaneSettingSection.tsx | 2 +- ts/components/session/SessionInboxView.tsx | 364 +++++++++--------- .../conversation/SessionConversation.tsx | 1 - ts/session/medium_group/index.ts | 8 +- ts/state/ducks/conversations.ts | 7 - ts/state/ducks/search.ts | 17 - ts/state/selectors/conversations.ts | 3 - ts/window.d.ts | 4 +- 26 files changed, 354 insertions(+), 433 deletions(-) diff --git a/app/menu.js b/app/menu.js index 60aa1f49f..068b93091 100644 --- a/app/menu.js +++ b/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); } diff --git a/js/background.js b/js/background.js index b5c0d05da..147ed7155 100644 --- a/js/background.js +++ b/js/background.js @@ -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; diff --git a/js/conversation_controller.js b/js/conversation_controller.js index 62b6d6650..78c7978d3 100644 --- a/js/conversation_controller.js +++ b/js/conversation_controller.js @@ -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 diff --git a/js/models/messages.js b/js/models/messages.js index 131738e07..ca59df0e9 100644 --- a/js/models/messages.js +++ b/js/models/messages.js @@ -598,7 +598,6 @@ isExpired: this.hasExpired, expirationLength, expirationTimestamp, - multiSelectMode: conversation && conversation.selectedMessages.size > 0, isPublic: !!this.get('isPublic'), isRss: !!this.get('isRss'), isKickedFromGroup: diff --git a/js/modules/signal.js b/js/modules/signal.js index b9156512a..8fd44f40c 100644 --- a/js/modules/signal.js +++ b/js/modules/signal.js @@ -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'); diff --git a/js/views/app_view.js b/js/views/app_view.js index 15312133d..d68e630a3 100644 --- a/js/views/app_view.js +++ b/js/views/app_view.js @@ -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); diff --git a/js/views/inbox_view.js b/js/views/inbox_view.js index fe0d415d9..30afb774f 100644 --- a/js/views/inbox_view.js +++ b/js/views/inbox_view.js @@ -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) { diff --git a/js/views/session_inbox_view.js b/js/views/session_inbox_view.js index 6f2cae8b4..7d17748ce 100644 --- a/js/views/session_inbox_view.js +++ b/js/views/session_inbox_view.js @@ -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(); - }, - }); - })(); \ No newline at end of file + close() { + this.remove(); + }, + }); +})(); diff --git a/main.js b/main.js index 34d787489..166d1a4c0 100644 --- a/main.js +++ b/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); diff --git a/preload.js b/preload.js index 341a34326..4ed3661b9 100644 --- a/preload.js +++ b/preload.js @@ -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); diff --git a/stylesheets/_index.scss b/stylesheets/_index.scss index 5ef186740..f801e8894 100644 --- a/stylesheets/_index.scss +++ b/stylesheets/_index.scss @@ -1,4 +1,4 @@ -.inbox { +.inbox { height: 100%; overflow: hidden; } diff --git a/stylesheets/_session_conversation.scss b/stylesheets/_session_conversation.scss index 5768cf697..3a4b63571 100644 --- a/stylesheets/_session_conversation.scss +++ b/stylesheets/_session_conversation.scss @@ -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; diff --git a/stylesheets/_session_left_pane.scss b/stylesheets/_session_left_pane.scss index 4563402e7..ff47b7153 100644 --- a/stylesheets/_session_left_pane.scss +++ b/stylesheets/_session_left_pane.scss @@ -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'); } diff --git a/test/app/menu_test.js b/test/app/menu_test.js index f6ebf31ce..15f8c57c8 100644 --- a/test/app/menu_test.js +++ b/test/app/menu_test.js @@ -51,7 +51,6 @@ describe('SignalMenu', () => { openSupportPage: null, platform, includeSetup, - setupAsStandalone: null, setupWithImport: null, showAbout: null, showDebugLog: null, diff --git a/ts/components/LeftPane.tsx b/ts/components/LeftPane.tsx index 5b3b12fb5..74baa5ace 100644 --- a/ts/components/LeftPane.tsx +++ b/ts/components/LeftPane.tsx @@ -168,7 +168,11 @@ export class LeftPane extends React.Component { } private renderSettingSection() { - const { isSecondaryDevice, showSessionSettingsCategory, settingsCategory } = this.props; + const { + isSecondaryDevice, + showSessionSettingsCategory, + settingsCategory, + } = this.props; const category = settingsCategory || SessionSettingCategory.Appearance; diff --git a/ts/components/SearchResults.tsx b/ts/components/SearchResults.tsx index 99c52b42e..3f262169c 100644 --- a/ts/components/SearchResults.tsx +++ b/ts/components/SearchResults.tsx @@ -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 { hideMessagesHeader, i18n, messages, - openConversation, + openConversationExternal, searchTerm, } = this.props; @@ -59,14 +59,14 @@ export class SearchResults extends React.Component { ))} ) : 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 { ))} @@ -91,10 +91,9 @@ export class SearchResults extends React.Component { } private renderContacts( header: string, - items: Array, - contacts?: boolean + items: Array ) { - const { i18n, openConversation } = this.props; + const { i18n, openConversationExternal } = this.props; return (
@@ -103,7 +102,7 @@ export class SearchResults extends React.Component { ))} diff --git a/ts/components/session/LeftPaneContactSection.tsx b/ts/components/session/LeftPaneContactSection.tsx index 2ceeba863..e3138614b 100644 --- a/ts/components/session/LeftPaneContactSection.tsx +++ b/ts/components/session/LeftPaneContactSection.tsx @@ -127,7 +127,13 @@ export class LeftPaneContactSection extends React.Component { 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); + }); } } diff --git a/ts/components/session/LeftPaneMessageSection.tsx b/ts/components/session/LeftPaneMessageSection.tsx index 2c0ced3c3..94d0ddb90 100644 --- a/ts/components/session/LeftPaneMessageSection.tsx +++ b/ts/components/session/LeftPaneMessageSection.tsx @@ -144,7 +144,7 @@ export class LeftPaneMessageSection extends React.Component { ); @@ -378,7 +378,7 @@ export class LeftPaneMessageSection extends React.Component { 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 { const error = validateNumber(pubkey); if (!error) { + await window.ConversationController.getOrCreateAndWait(pubkey, 'private'); openConversationExternal(pubkey); } else { ToastUtils.pushToastError('invalidPubKey', error); diff --git a/ts/components/session/LeftPaneSettingSection.tsx b/ts/components/session/LeftPaneSettingSection.tsx index 38e6871f2..3442a3411 100644 --- a/ts/components/session/LeftPaneSettingSection.tsx +++ b/ts/components/session/LeftPaneSettingSection.tsx @@ -58,7 +58,7 @@ export class LeftPaneSettingSection extends React.Component { } public renderRow(item: any): JSX.Element { - const {settingsCategory} = this.props; + const { settingsCategory } = this.props; return (
{ - 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 { // 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 ( - -
-
- {this.renderLeftPane()} -
- {isSettingsView ? this.renderSettings() : this.renderSessionConversation()} - - ); } + const isSettingsView = this.state.settingsCategory !== undefined; + return ( + +
+
+ {this.renderLeftPane()} +
+ {isSettingsView + ? this.renderSettings() + : this.renderSessionConversation()} + + ); + } private renderLeftPane() { return ( @@ -97,14 +107,14 @@ export class SessionInboxView extends React.Component { } 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 ( - + ); } @@ -114,154 +124,134 @@ export class SessionInboxView extends React.Component {
); -} + } - 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 { 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); + // } } diff --git a/ts/components/session/conversation/SessionConversation.tsx b/ts/components/session/conversation/SessionConversation.tsx index d7b25f9bf..f20cc31ad 100644 --- a/ts/components/session/conversation/SessionConversation.tsx +++ b/ts/components/session/conversation/SessionConversation.tsx @@ -151,7 +151,6 @@ export class SessionConversation extends React.Component { // ~~~~~~~~~~~~~~~~ LIFECYCLES ~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - public componentDidUpdate(prevProps: Props, prevState: State) { if (this.props.conversationKey !== prevProps.conversationKey) { void this.loadInitialMessages(); diff --git a/ts/session/medium_group/index.ts b/ts/session/medium_group/index.ts index ea4dcd12f..e276e8ded 100644 --- a/ts/session/medium_group/index.ts +++ b/ts/session/medium_group/index.ts @@ -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) { diff --git a/ts/state/ducks/conversations.ts b/ts/state/ducks/conversations.ts index 0380ab7e1..27d3d3b17 100644 --- a/ts/state/ducks/conversations.ts +++ b/ts/state/ducks/conversations.ts @@ -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; } diff --git a/ts/state/ducks/search.ts b/ts/state/ducks/search.ts index f1a2c657c..657249f1d 100644 --- a/ts/state/ducks/search.ts +++ b/ts/state/ducks/search.ts @@ -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 diff --git a/ts/state/selectors/conversations.ts b/ts/state/selectors/conversations.ts index 168cbe133..2f7a620b3 100644 --- a/ts/state/selectors/conversations.ts +++ b/ts/state/selectors/conversations.ts @@ -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, diff --git a/ts/window.d.ts b/ts/window.d.ts index e06e985ef..7a6808843 100644 --- a/ts/window.d.ts +++ b/ts/window.d.ts @@ -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; } }