diff --git a/.github/workflows/build-binaries.yml b/.github/workflows/build-binaries.yml index 19760fd1a..01b436bed 100644 --- a/.github/workflows/build-binaries.yml +++ b/.github/workflows/build-binaries.yml @@ -46,6 +46,7 @@ jobs: run: yarn generate - name: Lint Files + if: runner.os != 'Windows' run: yarn lint-full - name: Build windows production binaries diff --git a/.github/workflows/pull-request.yml b/.github/workflows/pull-request.yml index 9cab74b71..7e74cb96d 100644 --- a/.github/workflows/pull-request.yml +++ b/.github/workflows/pull-request.yml @@ -47,8 +47,9 @@ jobs: run: yarn generate - name: Lint Files + if: runner.os != 'Windows' run: | - yarn format-full --list-different + yarn format-full yarn eslint yarn tslint diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 4f56cc97b..7fe998f3f 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -43,6 +43,7 @@ jobs: run: yarn generate - name: Lint Files + if: runner.os != 'Windows' run: yarn lint-full - name: Build windows production binaries diff --git a/integration_test/add_friends_test.js b/integration_test/add_friends_test.js index 6b1d73670..90dbcf230 100644 --- a/integration_test/add_friends_test.js +++ b/integration_test/add_friends_test.js @@ -39,7 +39,7 @@ describe('Add friends', function() { await common.stopStubSnodeServer(); }); - it('can add a friend by sessionID', async () => { + it('addFriends: can add a friend by sessionID', async () => { const textMessage = common.generateSendMessageText(); await app.client.element(ConversationPage.contactsButtonSection).click(); @@ -47,13 +47,16 @@ describe('Add friends', function() { await app.client.isExisting(ConversationPage.leftPaneOverlay).should .eventually.be.true; - await app.client - .element(ConversationPage.sessionIDInput) - .setValue(common.TEST_PUBKEY2); + await common.setValueWrapper( + app, + ConversationPage.sessionIDInput, + common.TEST_PUBKEY2 + ); await app.client .element(ConversationPage.sessionIDInput) .getValue() .should.eventually.equal(common.TEST_PUBKEY2); + await app.client.element(ConversationPage.nextButton).click(); await app.client.waitForExist( ConversationPage.sendFriendRequestTextarea, @@ -69,6 +72,7 @@ describe('Add friends', function() { ConversationPage.existingFriendRequestText(textMessage), 1000 ); + // assure friend request message has been sent await common.timeout(3000); await app.client.isExisting(ConversationPage.retrySendButton).should diff --git a/integration_test/closed_group_test.js b/integration_test/closed_group_test.js index fec80c64a..12345b3e5 100644 --- a/integration_test/closed_group_test.js +++ b/integration_test/closed_group_test.js @@ -24,7 +24,7 @@ describe('Closed groups', function() { await common.stopStubSnodeServer(); }); - it('can create a closed group with a friend and send/receive a message', async () => { + it('closedGroup: can create a closed group with a friend and send/receive a message', async () => { await app.client.element(ConversationPage.globeButtonSection).click(); await app.client.element(ConversationPage.createClosedGroupButton).click(); diff --git a/integration_test/common.js b/integration_test/common.js index 5bf1c579e..ddf4c1788 100644 --- a/integration_test/common.js +++ b/integration_test/common.js @@ -58,6 +58,45 @@ module.exports = { return new Promise(resolve => setTimeout(resolve, ms)); }, + // a wrapper to work around electron/spectron bug + async setValueWrapper(app, selector, value) { + await app.client.element(selector).click(); + // keys, setValue and addValue hang on certain platforms + // could put a branch here to use one of those + // if we know what platforms are good and which ones are broken + + if (process.platform === 'darwin'){ + await app.client.execute( + (slctr, val) => { + // eslint-disable-next-line no-undef + const iter = document.evaluate( + slctr, + // eslint-disable-next-line no-undef + document, + null, + // eslint-disable-next-line no-undef + XPathResult.UNORDERED_NODE_ITERATOR_TYPE, + null + ); + const elem = iter.iterateNext(); + if (elem) { + elem.value = val; + } else { + console.error('Cant find', slctr, elem, iter); + } + }, + selector, + value + ); + // let session js detect the text change + await app.client.element(selector).click(); + } else { + // Linux & Windows don't require wrapper + await app.client.element(selector).setValue(value); + } + + }, + async startApp(environment = 'test-integration-session') { const env = environment.startsWith('test-integration') ? 'test-integration' @@ -100,16 +139,16 @@ module.exports = { async stopApp(app1) { if (app1 && app1.isRunning()) { await app1.stop(); - return Promise.resolve(); } - return Promise.resolve(); }, async killallElectron() { + // rtharp - my 2nd client on MacOs needs: pkill -f "node_modules/.bin/electron" + // node_modules/electron/dist/electron is node_modules/electron/dist/Electron.app on MacOS const killStr = process.platform === 'win32' ? 'taskkill /im electron.exe /t /f' - : 'pkill -f "node_modules/electron/dist/electron"'; + : 'pkill -f "node_modules/electron/dist/electron" | pkill -f "node_modules/.bin/electron"'; return new Promise(resolve => { exec(killStr, (_err, stdout, stderr) => { resolve({ stdout, stderr }); @@ -149,23 +188,24 @@ module.exports = { stubOpenGroups = false, env = 'test-integration-session', }) { - const app1 = await this.startAndAssureCleanedApp(env); + const app = await this.startAndAssureCleanedApp(env); if (stubSnode) { await this.startStubSnodeServer(); - this.stubSnodeCalls(app1); + this.stubSnodeCalls(app); } if (stubOpenGroups) { - this.stubOpenGroupsCalls(app1); + this.stubOpenGroupsCalls(app); } if (mnemonic && displayName) { - await this.restoreFromMnemonic(app1, mnemonic, displayName); + await this.restoreFromMnemonic(app, mnemonic, displayName); + // not sure we need this - rtharp. await this.timeout(2000); } - return app1; + return app; }, async startAndStubN(props, n) { @@ -178,18 +218,25 @@ module.exports = { return appN; }, - async restoreFromMnemonic(app1, mnemonic, displayName) { - await app1.client.element(RegistrationPage.registrationTabSignIn).click(); - await app1.client.element(RegistrationPage.restoreFromSeedMode).click(); - await app1.client - .element(RegistrationPage.recoveryPhraseInput) - .setValue(mnemonic); - await app1.client - .element(RegistrationPage.displayNameInput) - .setValue(displayName); - - await app1.client.element(RegistrationPage.continueSessionButton).click(); - await app1.client.waitForExist( + async restoreFromMnemonic(app, mnemonic, displayName) { + await app.client.element(RegistrationPage.registrationTabSignIn).click(); + await app.client.element(RegistrationPage.restoreFromSeedMode).click(); + await this.setValueWrapper( + app, + RegistrationPage.recoveryPhraseInput, + mnemonic + ); + + await this.setValueWrapper( + app, + RegistrationPage.displayNameInput, + displayName + ); + + // await app.client.element(RegistrationPage.continueSessionButton).click(); + await app.client.keys('Enter'); + + await app.client.waitForExist( RegistrationPage.conversationListContainer, 4000 ); @@ -219,9 +266,11 @@ module.exports = { await app1.client.element(ConversationPage.contactsButtonSection).click(); await app1.client.element(ConversationPage.addContactButton).click(); - await app1.client - .element(ConversationPage.sessionIDInput) - .setValue(this.TEST_PUBKEY2); + await this.setValueWrapper( + app1, + ConversationPage.sessionIDInput, + this.TEST_PUBKEY2 + ); await app1.client.element(ConversationPage.nextButton).click(); await app1.client.waitForExist( ConversationPage.sendFriendRequestTextarea, @@ -229,9 +278,11 @@ module.exports = { ); // send a text message to that user (will be a friend request) - await app1.client - .element(ConversationPage.sendFriendRequestTextarea) - .setValue(textMessage); + await this.setValueWrapper( + app1, + ConversationPage.sendFriendRequestTextarea, + textMessage + ); await app1.client.keys('Enter'); await app1.client.waitForExist( ConversationPage.existingFriendRequestText(textMessage), @@ -364,9 +415,12 @@ module.exports = { // next trigger the link request from the app2 with the app1 pubkey await app2.client.element(RegistrationPage.registrationTabSignIn).click(); await app2.client.element(RegistrationPage.linkDeviceMode).click(); - await app2.client - .element(RegistrationPage.textareaLinkDevicePubkey) - .setValue(this.TEST_PUBKEY1); + + await this.setValueWrapper( + app2, + RegistrationPage.textareaLinkDevicePubkey, + this.TEST_PUBKEY1 + ); await app2.client.element(RegistrationPage.linkDeviceTriggerButton).click(); await app1.client.waitForExist(RegistrationPage.toastWrapper, 7000); let secretWordsapp1 = await app1.client diff --git a/integration_test/link_device_test.js b/integration_test/link_device_test.js index 9cc8ca74a..63239e58a 100644 --- a/integration_test/link_device_test.js +++ b/integration_test/link_device_test.js @@ -36,11 +36,11 @@ describe('Link Device', function() { await common.stopStubSnodeServer(); }); - it('link two desktop devices', async () => { + it('linkDevice: link two desktop devices', async () => { await common.linkApp2ToApp(app, app2); }); - it('unlink two devices', async () => { + it('linkDevice: unlink two devices', async () => { await common.linkApp2ToApp(app, app2); await common.timeout(1000); await common.triggerUnlinkApp2FromApp(app, app2); diff --git a/integration_test/open_group_test.js b/integration_test/open_group_test.js index 9f3d21fd9..e61f6047a 100644 --- a/integration_test/open_group_test.js +++ b/integration_test/open_group_test.js @@ -24,25 +24,25 @@ describe('Open groups', function() { await common.killallElectron(); }); - it('works with valid group url', async () => { + // reduce code duplication to get the initial join + async function joinOpenGroup(url, name) { await app.client.element(ConversationPage.globeButtonSection).click(); await app.client.element(ConversationPage.joinOpenGroupButton).click(); - await app.client - .element(ConversationPage.openGroupInputUrl) - .setValue(common.VALID_GROUP_URL); + await common.setValueWrapper(app, ConversationPage.openGroupInputUrl, url); await app.client .element(ConversationPage.openGroupInputUrl) .getValue() - .should.eventually.equal(common.VALID_GROUP_URL); + .should.eventually.equal(url); await app.client.element(ConversationPage.joinOpenGroupButton).click(); // validate session loader is shown await app.client.isExisting(ConversationPage.sessionLoader).should .eventually.be.true; + // account for slow home internet connection delays... await app.client.waitForExist( ConversationPage.sessionToastJoinOpenGroupSuccess, - 9000 + 60 * 1000 ); // validate overlay is closed @@ -51,35 +51,27 @@ describe('Open groups', function() { // validate open chat has been added await app.client.waitForExist( - ConversationPage.rowOpenGroupConversationName(common.VALID_GROUP_NAME), + ConversationPage.rowOpenGroupConversationName(name), 4000 ); + } - await common.timeout(1000); + it('openGroup: works with valid open group url', async () => { + await joinOpenGroup(common.VALID_GROUP_URL, common.VALID_GROUP_NAME); }); - it('cannot join two times the same open group', async () => { - await app.client.element(ConversationPage.globeButtonSection).click(); - await app.client.element(ConversationPage.joinOpenGroupButton).click(); - - await app.client - .element(ConversationPage.openGroupInputUrl) - .setValue(common.VALID_GROUP_URL2); - await app.client.element(ConversationPage.joinOpenGroupButton).click(); - // first add is a success - await common.timeout(2000); - await app.client.waitForExist( - ConversationPage.rowOpenGroupConversationName(common.VALID_GROUP_NAME2), - 8000 - ); + it('openGroup: cannot join two times the same open group', async () => { + await joinOpenGroup(common.VALID_GROUP_URL2, common.VALID_GROUP_NAME2); // adding a second time the same open group await app.client.element(ConversationPage.globeButtonSection).click(); await app.client.element(ConversationPage.joinOpenGroupButton).click(); - await app.client - .element(ConversationPage.openGroupInputUrl) - .setValue(common.VALID_GROUP_URL2); + await common.setValueWrapper( + app, + ConversationPage.openGroupInputUrl, + common.VALID_GROUP_URL2 + ); await app.client.element(ConversationPage.joinOpenGroupButton).click(); // validate session loader is not shown await app.client.isExisting(ConversationPage.sessionLoader).should @@ -87,7 +79,7 @@ describe('Open groups', function() { await app.client.waitForExist( ConversationPage.sessionToastJoinOpenGroupAlreadyExist, - 1000 + 1 * 1000 ); // validate overlay is still opened @@ -95,20 +87,28 @@ describe('Open groups', function() { .eventually.be.true; }); - it('can send message to open group', async () => { + it('openGroup: can send message to open group', async () => { // join dev-chat group await app.client.element(ConversationPage.globeButtonSection).click(); await app.client.element(ConversationPage.joinOpenGroupButton).click(); - await app.client - .element(ConversationPage.openGroupInputUrl) - .setValue(common.VALID_GROUP_URL2); + await common.setValueWrapper( + app, + ConversationPage.openGroupInputUrl, + common.VALID_GROUP_URL2 + ); await app.client.element(ConversationPage.joinOpenGroupButton).click(); - // first add is a success - await common.timeout(2000); + + // wait for toast to appear + await app.client.waitForExist( + ConversationPage.sessionToastJoinOpenGroupSuccess, + 30 * 1000 + ); + await common.timeout(5 * 1000); // wait for toast to clear + await app.client.waitForExist( ConversationPage.rowOpenGroupConversationName(common.VALID_GROUP_NAME2), - 8000 + 10 * 1000 ); // generate a message containing the current timestamp so we can find it in the list of messages const textMessage = common.generateSendMessageText(); @@ -119,14 +119,18 @@ describe('Open groups', function() { await app.client.isExisting( ConversationPage.rowOpenGroupConversationName(common.VALID_GROUP_NAME2) ); + await app.client .element( ConversationPage.rowOpenGroupConversationName(common.VALID_GROUP_NAME2) ) .click(); - await app.client - .element(ConversationPage.sendMessageTextarea) - .setValue(textMessage); + + await common.setValueWrapper( + app, + ConversationPage.sendMessageTextarea, + textMessage + ); await app.client .element(ConversationPage.sendMessageTextarea) .getValue() @@ -140,7 +144,7 @@ describe('Open groups', function() { // validate that the message has been added to the message list view await app.client.waitForExist( ConversationPage.existingSendMessageText(textMessage), - 3000 + 3 * 1000 ); // we should validate that the message has been added effectively sent // (checking the check icon on the metadata part of the message?) diff --git a/integration_test/page-objects/common.page.js b/integration_test/page-objects/common.page.js index 9a3a77573..e5374f6d6 100644 --- a/integration_test/page-objects/common.page.js +++ b/integration_test/page-objects/common.page.js @@ -13,6 +13,7 @@ module.exports = { `//input[contains(@placeholder, "${placeholder}")]`, textAreaWithPlaceholder: placeholder => `//textarea[contains(@placeholder, "${placeholder}")]`, + byId: id => `//*[@id="${id}"]`, divWithClass: classname => `//div[contains(@class, "${classname}")]`, divWithClassAndText: (classname, text) => module.exports.objWithClassAndText('div', classname, text), diff --git a/integration_test/page-objects/conversation.page.js b/integration_test/page-objects/conversation.page.js index c8b358634..1720274bb 100644 --- a/integration_test/page-objects/conversation.page.js +++ b/integration_test/page-objects/conversation.page.js @@ -31,7 +31,9 @@ module.exports = { attachmentInput: '//*[contains(@class, "choose-file")]/input[@type="file"]', attachmentButton: '//*[contains(@class, "choose-file")]/button', - messageCtxMenu: message => `//div[contains(@class, "message-wrapper") and .//span[contains(@class, "text-selectable")][contains(string(), ${message})]]//div[contains(@class, 'module-message__buttons__menu')]`, + messageCtxMenu: message => `//div[contains(@class, "message-wrapper")]//span[contains(@class, "text-selectable")][contains(string(), '${message}')]/ancestor::div//div[contains(@class, 'module-message__buttons__menu')]`, + //div[contains(@class, "message-wrapper")]//span[contains(@class, "text-selectable")][contains(string(), 'delete_me')]/ancestor::div//div[contains(@class, 'module-message__buttons__menu')] + deleteMessageCtxButton: '//*[contains(@class, "react-contextmenu--visible")]/div[contains(string(), "Delete Message")]', deleteMessageModalButton: '//*[contains(@class, "session-modal")]//div[contains(string(), "Delete") and contains(@class, "session-button")]', diff --git a/integration_test/registration_test.js b/integration_test/registration_test.js index 595ead8e8..69bf4b27f 100644 --- a/integration_test/registration_test.js +++ b/integration_test/registration_test.js @@ -22,12 +22,12 @@ describe('Window Test and Login', function() { await common.killallElectron(); }); - it('opens one window', async () => { + it('registration: opens one window', async () => { app = await common.startAndAssureCleanedApp(); app.client.getWindowCount().should.eventually.be.equal(1); }); - it('window title is correct', async () => { + it('registration: window title is correct', async () => { app = await common.startAndAssureCleanedApp(); app.client @@ -35,7 +35,7 @@ describe('Window Test and Login', function() { .should.eventually.be.equal('Session - test-integration-session'); }); - it('can restore from seed', async () => { + it('registration: can restore from seed', async () => { app = await common.startAndAssureCleanedApp(); await app.client.element(RegistrationPage.registrationTabSignIn).click(); @@ -71,7 +71,7 @@ describe('Window Test and Login', function() { .should.eventually.be.equal(common.TEST_PUBKEY1); }); - it('can create new account', async () => { + it('registration: can create new account', async () => { app = await common.startAndAssureCleanedApp(); await app.client.element(RegistrationPage.createSessionIDButton).click(); // wait for the animation of generated pubkey to finish @@ -99,7 +99,7 @@ describe('Window Test and Login', function() { .should.eventually.be.equal(pubkeyGenerated); }); - it('can delete account when logged in', async () => { + it('registration: can delete account when logged in', async () => { // login as user1 const login = { mnemonic: common.TEST_MNEMONIC1, diff --git a/js/modules/loki_file_server_api.js b/js/modules/loki_file_server_api.js index 47adf81eb..b6050a6be 100644 --- a/js/modules/loki_file_server_api.js +++ b/js/modules/loki_file_server_api.js @@ -4,7 +4,6 @@ /* global log: false */ const LokiAppDotNetAPI = require('./loki_app_dot_net_api'); -const StubAppDotNetAPI = require('../../integration_test/stubs/stub_app_dot_net_api.js'); const DEVICE_MAPPING_USER_ANNOTATION_TYPE = 'network.loki.messenger.devicemapping'; @@ -60,6 +59,8 @@ class LokiFileServerInstance { async establishConnection(serverUrl, options) { // why don't we extend this? if (process.env.USE_STUBBED_NETWORK) { + // eslint-disable-next-line global-require + const StubAppDotNetAPI = require('../../integration_test/stubs/stub_app_dot_net_api.js'); this._server = new StubAppDotNetAPI(this.ourKey, serverUrl); } else { this._server = new LokiAppDotNetAPI(this.ourKey, serverUrl); diff --git a/js/modules/loki_public_chat_api.js b/js/modules/loki_public_chat_api.js index 20aa2338d..aa89828a4 100644 --- a/js/modules/loki_public_chat_api.js +++ b/js/modules/loki_public_chat_api.js @@ -2,7 +2,6 @@ const EventEmitter = require('events'); const nodeFetch = require('node-fetch'); const LokiAppDotNetAPI = require('./loki_app_dot_net_api'); -const StubAppDotNetAPI = require('../../integration_test/stubs/stub_app_dot_net_api.js'); class LokiPublicChatFactoryAPI extends EventEmitter { constructor(ourKey) { @@ -61,6 +60,8 @@ class LokiPublicChatFactoryAPI extends EventEmitter { // after verification then we can start up all the pollers if (process.env.USE_STUBBED_NETWORK) { + // eslint-disable-next-line global-require + const StubAppDotNetAPI = require('../../integration_test/stubs/stub_app_dot_net_api.js'); thisServer = new StubAppDotNetAPI(this.ourKey, serverUrl); } else { thisServer = new LokiAppDotNetAPI(this.ourKey, serverUrl); diff --git a/main.js b/main.js index d092ab1af..8be3fe80e 100644 --- a/main.js +++ b/main.js @@ -206,9 +206,11 @@ function captureClicks(window) { } const DEFAULT_WIDTH = 880; -const DEFAULT_HEIGHT = 720; +// add contact button needs to be visible (on HiDpi screens?) +// otherwise integration test fail +const DEFAULT_HEIGHT = 820; const MIN_WIDTH = 880; -const MIN_HEIGHT = 720; +const MIN_HEIGHT = 820; const BOUNDS_BUFFER = 100; function isVisible(window, bounds) { @@ -353,6 +355,10 @@ async function createWindow() { mainWindow.on('focus', () => { mainWindow.flashFrame(false); + if (passwordWindow) { + passwordWindow.close(); + passwordWindow = null; + } }); if (config.environment === 'test') { @@ -1025,11 +1031,6 @@ ipc.on('password-window-login', async (event, passPhrase) => { const passwordAttempt = true; await showMainWindow(passPhrase, passwordAttempt); sendResponse(); - - if (passwordWindow) { - passwordWindow.close(); - passwordWindow = null; - } } catch (e) { const localisedError = locale.messages.invalidPassword.message; sendResponse(localisedError || 'Invalid password'); diff --git a/package.json b/package.json index b6bd7d4ba..d05625c77 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "session-messenger-desktop", "productName": "Session", "description": "Private messaging from your desktop", - "version": "1.0.5", + "version": "1.0.6", "license": "GPL-3.0", "author": { "name": "Loki Project", @@ -35,7 +35,8 @@ "test-lib-view": "NODE_ENV=test-lib yarn run start", "test-loki-view": "NODE_ENV=test-loki yarn run start", "test-electron": "yarn grunt test", - "test-integration": "ELECTRON_DISABLE_SANDBOX=1 mocha --exit --timeout 5000 integration_test/integration_test.js", + "test-integration": "ELECTRON_DISABLE_SANDBOX=1 mocha --exit --timeout 10000 integration_test/integration_test.js", + "test-integration-parts": "ELECTRON_DISABLE_SANDBOX=1 mocha --exit --timeout 10000 integration_test/integration_test.js --grep 'registration' && ELECTRON_DISABLE_SANDBOX=1 mocha --exit --timeout 10000 integration_test/integration_test.js --grep 'openGroup' && ELECTRON_DISABLE_SANDBOX=1 mocha --exit --timeout 10000 integration_test/integration_test.js --grep 'addFriends' && ELECTRON_DISABLE_SANDBOX=1 mocha --exit --timeout 10000 integration_test/integration_test.js --grep 'linkDevice' && ELECTRON_DISABLE_SANDBOX=1 mocha --exit --timeout 10000 integration_test/integration_test.js --grep 'closedGroup'", "test-node": "mocha --recursive --exit test/app test/modules ts/test libloki/test/node", "eslint": "eslint --cache .", "eslint-fix": "eslint --fix .", @@ -47,8 +48,8 @@ "lint-files-full": "yarn eslint-full && yarn tslint", "lint-deps": "node ts/util/lint/linter.js", "tslint": "tslint --format stylish --project .", - "format": "prettier --list-different --write `git ls-files --modified *.{css,js,json,md,scss,ts,tsx}` `git ls-files --modified ./**/*.{css,js,json,md,scss,ts,tsx}`", - "format-full": "prettier --list-different --write \"*.{css,js,json,md,scss,ts,tsx}\" \"./**/*.{css,js,json,md,scss,ts,tsx}\"", + "format": "prettier --list-different --write `git ls-files --modified *.{css,js,json,scss,ts,tsx}` `git ls-files --modified ./**/*.{css,js,json,scss,ts,tsx}`", + "format-full": "prettier --list-different --write \"*.{css,js,json,scss,ts,tsx}\" \"./**/*.{css,js,json,scss,ts,tsx}\"", "transpile": "tsc", "clean-transpile": "rimraf ts/**/*.js && rimraf ts/*.js", "pow-metrics": "node metrics_app.js localhost 9000", diff --git a/ts/components/conversation/ConversationHeader.tsx b/ts/components/conversation/ConversationHeader.tsx index f0d4e021b..198d06fbd 100644 --- a/ts/components/conversation/ConversationHeader.tsx +++ b/ts/components/conversation/ConversationHeader.tsx @@ -419,6 +419,7 @@ export class ConversationHeader extends React.Component { $('.session-search-input input').focus(); } + // tslint:disable-next-line: cyclomatic-complexity private renderPublicMenuItems() { const { i18n, @@ -438,9 +439,10 @@ export class ConversationHeader extends React.Component { timerOptions, onBlockUser, onUnblockUser, - hasNickname, - onClearNickname, - onChangeNickname, + // hasNickname, + // onClearNickname, + // onChangeNickname, + isFriend, } = this.props; if (isPublic || isRss) { @@ -452,7 +454,7 @@ export class ConversationHeader extends React.Component { const blockTitle = isBlocked ? i18n('unblockUser') : i18n('blockUser'); const blockHandler = isBlocked ? onUnblockUser : onBlockUser; - const disappearingMessagesMenuItem = ( + const disappearingMessagesMenuItem = isFriend && ( {(timerOptions || []).map(item => ( { {i18n('showSafetyNumber')} ); - const resetSessionMenuItem = !isGroup && ( - {i18n('resetSession')} - ); - const blockHandlerMenuItem = !isMe && - !isGroup && - !isRss && {blockTitle}; - const changeNicknameMenuItem = !isMe && + const resetSessionMenuItem = isFriend && !isGroup && ( - {i18n('changeNickname')} + {i18n('resetSession')} ); - const clearNicknameMenuItem = !isMe && + const blockHandlerMenuItem = !isMe && !isGroup && - hasNickname && ( - {i18n('clearNickname')} - ); + !isRss && {blockTitle}; + // const changeNicknameMenuItem = !isMe && + // !isGroup && ( + // {i18n('changeNickname')} + // ); + // const clearNicknameMenuItem = !isMe && + // !isGroup && + // hasNickname && ( + // {i18n('clearNickname')} + // ); const archiveConversationMenuItem = isArchived ? ( {i18n('moveConversationToInbox')} @@ -506,8 +509,8 @@ export class ConversationHeader extends React.Component { {showSafetyNumberMenuItem} {resetSessionMenuItem} {blockHandlerMenuItem} - {changeNicknameMenuItem} - {clearNicknameMenuItem} + {/* {changeNicknameMenuItem} + {clearNicknameMenuItem} */} {archiveConversationMenuItem} ); diff --git a/ts/components/session/SessionIdEditable.tsx b/ts/components/session/SessionIdEditable.tsx index dc4bab8bc..6fca9f63e 100644 --- a/ts/components/session/SessionIdEditable.tsx +++ b/ts/components/session/SessionIdEditable.tsx @@ -45,6 +45,7 @@ export class SessionIdEditable extends React.PureComponent { spellCheck={false} onKeyDown={this.handleKeyDown} onChange={this.handleChange} + onBlur={this.handleChange} value={value || text} maxLength={maxLength} /> diff --git a/ts/components/session/SessionInput.tsx b/ts/components/session/SessionInput.tsx index 11432e80a..edd8c64ed 100644 --- a/ts/components/session/SessionInput.tsx +++ b/ts/components/session/SessionInput.tsx @@ -61,6 +61,10 @@ export class SessionInput extends React.PureComponent { className={classNames( enableShowHide ? 'session-input-floating-label-show-hide' : '' )} + // just incase onChange isn't triggered + onBlur={e => { + this.updateInputValue(e); + }} onKeyPress={event => { event.persist(); if (event.key === 'Enter' && this.props.onEnterPressed) {