From b510916ef5190b5ac3fd238a6d8d3a8c9fb5bfe4 Mon Sep 17 00:00:00 2001 From: Daniel Gasienica Date: Wed, 2 May 2018 16:42:15 -0400 Subject: [PATCH 01/13] Split `global`s into third-party and own --- js/database.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/js/database.js b/js/database.js index 6bade25f8..234821700 100644 --- a/js/database.js +++ b/js/database.js @@ -1,6 +1,7 @@ -/* global Whisper: false */ -/* global Backbone: false */ /* global _: false */ +/* global Backbone: false */ + +/* global Whisper: false */ // eslint-disable-next-line func-names (function() { From 06e3f09732c42a585610b1b46291d84a83211584 Mon Sep 17 00:00:00 2001 From: Daniel Gasienica Date: Wed, 2 May 2018 16:43:32 -0400 Subject: [PATCH 02/13] ESLint: Add `js/notifications` --- .eslintignore | 1 + js/notifications.js | 65 ++++++++++++++++++++++++++++----------------- 2 files changed, 41 insertions(+), 25 deletions(-) diff --git a/.eslintignore b/.eslintignore index fc7b1dc5b..59050f2c0 100644 --- a/.eslintignore +++ b/.eslintignore @@ -36,6 +36,7 @@ ts/**/*.js !js/logging.js !js/models/conversations.js !js/models/messages.js +!js/notifications.js !js/views/attachment_view.js !js/views/backbone_wrapper_view.js !js/views/conversation_search_view.js diff --git a/js/notifications.js b/js/notifications.js index 95029fe50..596a1a64d 100644 --- a/js/notifications.js +++ b/js/notifications.js @@ -1,9 +1,21 @@ +/* global Backbone: false */ +/* global nodeNotifier: false */ + +/* global config: false */ +/* global ConversationController: false */ +/* global i18n: false */ +/* global Signal: false */ +/* global storage: false */ +/* global Whisper: false */ + +// eslint-disable-next-line func-names (function() { 'use strict'; + window.Whisper = window.Whisper || {}; - const { Settings } = window.Signal.Types; + const { Settings } = Signal.Types; - var SETTINGS = { + const SETTINGS = { OFF: 'off', COUNT: 'count', NAME: 'name', @@ -11,16 +23,16 @@ }; Whisper.Notifications = new (Backbone.Collection.extend({ - initialize: function() { + initialize() { this.isEnabled = false; this.on('add', this.update); this.on('remove', this.onRemove); }, - onClick: function(conversationId) { - var conversation = ConversationController.get(conversationId); + onClick(conversationId) { + const conversation = ConversationController.get(conversationId); this.trigger('click', conversation); }, - update: function() { + update() { const { isEnabled } = this; const isFocused = window.isFocused(); const isAudioNotificationEnabled = @@ -51,35 +63,35 @@ return; } - var setting = storage.get('notification-setting') || 'message'; + const setting = this.getSetting(); if (setting === SETTINGS.OFF) { return; } window.drawAttention(); - var title; - var message; - var iconUrl; + let title; + let message; + let iconUrl; // NOTE: i18n has more complex rules for pluralization than just // distinguishing between zero (0) and other (non-zero), // e.g. Russian: // http://docs.translatehouse.org/projects/localization-guide/en/latest/l10n/pluralforms.html - var newMessageCount = [ + const newMessageCount = [ numNotifications, numNotifications === 1 ? i18n('newMessage') : i18n('newMessages'), ].join(' '); - var last = this.last(); - switch (this.getSetting()) { + const last = this.last(); + switch (setting) { case SETTINGS.COUNT: title = 'Signal'; message = newMessageCount; break; case SETTINGS.NAME: title = newMessageCount; - message = 'Most recent from ' + last.get('title'); + message = `Most recent from ${last.get('title')}`; iconUrl = last.get('iconUrl'); break; case SETTINGS.MESSAGE: @@ -91,19 +103,22 @@ message = last.get('message'); iconUrl = last.get('iconUrl'); break; + default: + console.log(`Error: Unknown setting: '${setting}'`); + break; } - if (window.config.polyfillNotifications) { - window.nodeNotifier.notify({ - title: title, - message: message, + if (config.polyfillNotifications) { + nodeNotifier.notify({ + title, + message, sound: false, }); - window.nodeNotifier.on('click', function(notifierObject, options) { + nodeNotifier.on('click', () => { last.get('conversationId'); }); } else { - var notification = new Notification(title, { + const notification = new Notification(title, { body: message, icon: iconUrl, tag: 'signal', @@ -119,24 +134,24 @@ // We don't want to notify the user about these same messages again this.clear(); }, - getSetting: function() { + getSetting() { return storage.get('notification-setting') || SETTINGS.MESSAGE; }, - onRemove: function() { + onRemove() { console.log('remove notification'); }, - clear: function() { + clear() { console.log('remove all notifications'); this.reset([]); }, - enable: function() { + enable() { const needUpdate = !this.isEnabled; this.isEnabled = true; if (needUpdate) { this.update(); } }, - disable: function() { + disable() { this.isEnabled = false; }, }))(); From 0701768fd7c5bd4146a01d7e8e7edb75c283a4cd Mon Sep 17 00:00:00 2001 From: Daniel Gasienica Date: Wed, 2 May 2018 17:58:48 -0400 Subject: [PATCH 03/13] Declare globals for `drawAttention` and `isFocused` --- js/notifications.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/js/notifications.js b/js/notifications.js index 596a1a64d..2ff1e2885 100644 --- a/js/notifications.js +++ b/js/notifications.js @@ -3,7 +3,9 @@ /* global config: false */ /* global ConversationController: false */ +/* global drawAttention: false */ /* global i18n: false */ +/* global isFocused: false */ /* global Signal: false */ /* global storage: false */ /* global Whisper: false */ @@ -34,7 +36,7 @@ }, update() { const { isEnabled } = this; - const isFocused = window.isFocused(); + const isAppFocused = isFocused(); const isAudioNotificationEnabled = storage.get('audio-notification') || false; const isAudioNotificationSupported = Settings.isAudioNotificationSupported(); @@ -42,7 +44,7 @@ isAudioNotificationSupported && isAudioNotificationEnabled; const numNotifications = this.length; console.log('Update notifications:', { - isFocused, + isAppFocused, isEnabled, numNotifications, shouldPlayNotificationSound, @@ -57,7 +59,7 @@ return; } - const isNotificationOmitted = isFocused; + const isNotificationOmitted = isAppFocused; if (isNotificationOmitted) { this.clear(); return; @@ -68,7 +70,7 @@ return; } - window.drawAttention(); + drawAttention(); let title; let message; From 5fe5320760da1beab4d389f655ebb45b8fadef67 Mon Sep 17 00:00:00 2001 From: Daniel Gasienica Date: Wed, 2 May 2018 18:02:49 -0400 Subject: [PATCH 04/13] Rename `SETTINGS` to `SettingNames` --- js/notifications.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/js/notifications.js b/js/notifications.js index 2ff1e2885..489e7ce9a 100644 --- a/js/notifications.js +++ b/js/notifications.js @@ -17,7 +17,7 @@ window.Whisper = window.Whisper || {}; const { Settings } = Signal.Types; - const SETTINGS = { + const SettingNames = { OFF: 'off', COUNT: 'count', NAME: 'name', @@ -66,7 +66,7 @@ } const setting = this.getSetting(); - if (setting === SETTINGS.OFF) { + if (setting === SettingNames.OFF) { return; } @@ -87,16 +87,16 @@ const last = this.last(); switch (setting) { - case SETTINGS.COUNT: + case SettingNames.COUNT: title = 'Signal'; message = newMessageCount; break; - case SETTINGS.NAME: + case SettingNames.NAME: title = newMessageCount; message = `Most recent from ${last.get('title')}`; iconUrl = last.get('iconUrl'); break; - case SETTINGS.MESSAGE: + case SettingNames.MESSAGE: if (numNotifications === 1) { title = last.get('title'); } else { @@ -137,7 +137,7 @@ this.clear(); }, getSetting() { - return storage.get('notification-setting') || SETTINGS.MESSAGE; + return storage.get('notification-setting') || SettingNames.MESSAGE; }, onRemove() { console.log('remove notification'); From d5b391757d818ee4a4530b472d7afd6729d8882d Mon Sep 17 00:00:00 2001 From: Daniel Gasienica Date: Wed, 2 May 2018 18:03:26 -0400 Subject: [PATCH 05/13] Add `Notifications.getStatus` --- preload.js | 1 + ts/notifications/getStatus.ts | 60 +++++++++++++++++++++++++++++++++++ ts/notifications/index.ts | 3 ++ 3 files changed, 64 insertions(+) create mode 100644 ts/notifications/getStatus.ts create mode 100644 ts/notifications/index.ts diff --git a/preload.js b/preload.js index c8cb16df7..30fad8331 100644 --- a/preload.js +++ b/preload.js @@ -200,6 +200,7 @@ window.Signal.Migrations.Migrations0DatabaseWithAttachmentData = require('./js/m window.Signal.Migrations.Migrations1DatabaseWithoutAttachmentData = require('./js/modules/migrations/migrations_1_database_without_attachment_data'); window.Signal.Migrations.upgradeMessageSchema = upgradeMessageSchema; +window.Signal.Notifications = require('./ts/notifications'); window.Signal.OS = require('./js/modules/os'); window.Signal.Settings = require('./js/modules/settings'); window.Signal.Startup = require('./js/modules/startup'); diff --git a/ts/notifications/getStatus.ts b/ts/notifications/getStatus.ts new file mode 100644 index 000000000..f23df1485 --- /dev/null +++ b/ts/notifications/getStatus.ts @@ -0,0 +1,60 @@ +interface Environment { + isAppFocused: boolean; + isAudioNotificationEnabled: boolean; + isAudioNotificationSupported: boolean; + isEnabled: boolean; + numNotifications: number; + userSetting: UserSetting; +} + +interface Status { + shouldClearNotifications: boolean; + shouldPlayNotificationSound: boolean; + shouldShowNotifications: boolean; + type: Type; +} + +type UserSetting = 'off' | 'count' | 'name' | 'message'; + +type Type = + | 'ok' + | 'disabled' + | 'appIsFocused' + | 'noNotifications' + | 'userSetting'; + +export const getStatus = (environment: Environment): Status => { + const type = ((): Type => { + if (!environment.isEnabled) { + return 'disabled'; + } + + const hasNotifications = environment.numNotifications > 0; + if (!hasNotifications) { + return 'noNotifications'; + } + + if (environment.isAppFocused) { + return 'appIsFocused'; + } + + if (environment.userSetting === 'off') { + return 'userSetting'; + } + + return 'ok'; + })(); + + const shouldPlayNotificationSound = + environment.isAudioNotificationSupported && + environment.isAudioNotificationEnabled; + const shouldShowNotifications = type === 'ok'; + const shouldClearNotifications = type === 'appIsFocused'; + + return { + shouldClearNotifications, + shouldPlayNotificationSound, + shouldShowNotifications, + type, + }; +}; diff --git a/ts/notifications/index.ts b/ts/notifications/index.ts new file mode 100644 index 000000000..30cb2f1e9 --- /dev/null +++ b/ts/notifications/index.ts @@ -0,0 +1,3 @@ +import { getStatus } from './getStatus'; + +export { getStatus }; From 1f2a2e1d52badba0f7ca00af7c512e4be6f6d7ce Mon Sep 17 00:00:00 2001 From: Daniel Gasienica Date: Wed, 2 May 2018 18:04:00 -0400 Subject: [PATCH 06/13] Use `Notifications.getStatus` --- js/notifications.js | 48 +++++++++++++++++++-------------------------- 1 file changed, 20 insertions(+), 28 deletions(-) diff --git a/js/notifications.js b/js/notifications.js index 489e7ce9a..ae1a9adde 100644 --- a/js/notifications.js +++ b/js/notifications.js @@ -40,38 +40,28 @@ const isAudioNotificationEnabled = storage.get('audio-notification') || false; const isAudioNotificationSupported = Settings.isAudioNotificationSupported(); - const shouldPlayNotificationSound = - isAudioNotificationSupported && isAudioNotificationEnabled; const numNotifications = this.length; - console.log('Update notifications:', { - isAppFocused, + const userSetting = this.getUserSetting(); + + const status = Signal.Notifications.getStatus({ isEnabled, + isAppFocused, + isAudioNotificationEnabled, + isAudioNotificationSupported, numNotifications, - shouldPlayNotificationSound, + userSetting, }); - if (!isEnabled) { - return; - } - - const hasNotifications = numNotifications > 0; - if (!hasNotifications) { - return; - } + console.log('Update notifications:', status); - const isNotificationOmitted = isAppFocused; - if (isNotificationOmitted) { - this.clear(); - return; - } + if (status.type !== 'ok') { + if (status.shouldClearNotifications) { + this.clear(); + } - const setting = this.getSetting(); - if (setting === SettingNames.OFF) { return; } - drawAttention(); - let title; let message; let iconUrl; @@ -86,7 +76,7 @@ ].join(' '); const last = this.last(); - switch (setting) { + switch (userSetting) { case SettingNames.COUNT: title = 'Signal'; message = newMessageCount; @@ -106,10 +96,12 @@ iconUrl = last.get('iconUrl'); break; default: - console.log(`Error: Unknown setting: '${setting}'`); + console.log(`Error: Unknown user setting: '${userSetting}'`); break; } + drawAttention(); + if (config.polyfillNotifications) { nodeNotifier.notify({ title, @@ -124,7 +116,7 @@ body: message, icon: iconUrl, tag: 'signal', - silent: !shouldPlayNotificationSound, + silent: !status.shouldPlayNotificationSound, }); notification.onclick = this.onClick.bind( @@ -136,14 +128,14 @@ // We don't want to notify the user about these same messages again this.clear(); }, - getSetting() { + getUserSetting() { return storage.get('notification-setting') || SettingNames.MESSAGE; }, onRemove() { - console.log('remove notification'); + console.log('Remove notification'); }, clear() { - console.log('remove all notifications'); + console.log('Remove all notifications'); this.reset([]); }, enable() { From 4e6a03a91cee44bc966a45b5d1c483433c7ea734 Mon Sep 17 00:00:00 2001 From: Daniel Gasienica Date: Wed, 2 May 2018 18:33:58 -0400 Subject: [PATCH 07/13] Log whether OS supports native notifications --- js/notifications.js | 24 +++++++++++++----------- ts/notifications/getStatus.ts | 26 +++++++++++++++++++------- 2 files changed, 32 insertions(+), 18 deletions(-) diff --git a/js/notifications.js b/js/notifications.js index ae1a9adde..e27bb910d 100644 --- a/js/notifications.js +++ b/js/notifications.js @@ -42,12 +42,14 @@ const isAudioNotificationSupported = Settings.isAudioNotificationSupported(); const numNotifications = this.length; const userSetting = this.getUserSetting(); + const hasNotificationSupport = !Boolean(config.polyfillNotifications); const status = Signal.Notifications.getStatus({ - isEnabled, + hasNotificationSupport, isAppFocused, isAudioNotificationEnabled, isAudioNotificationSupported, + isEnabled, numNotifications, userSetting, }); @@ -102,16 +104,7 @@ drawAttention(); - if (config.polyfillNotifications) { - nodeNotifier.notify({ - title, - message, - sound: false, - }); - nodeNotifier.on('click', () => { - last.get('conversationId'); - }); - } else { + if (hasNotificationSupport) { const notification = new Notification(title, { body: message, icon: iconUrl, @@ -123,6 +116,15 @@ this, last.get('conversationId') ); + } else { + nodeNotifier.notify({ + title, + message, + sound: false, + }); + nodeNotifier.on('click', () => { + last.get('conversationId'); + }); } // We don't want to notify the user about these same messages again diff --git a/ts/notifications/getStatus.ts b/ts/notifications/getStatus.ts index f23df1485..9f82eacb2 100644 --- a/ts/notifications/getStatus.ts +++ b/ts/notifications/getStatus.ts @@ -4,6 +4,7 @@ interface Environment { isAudioNotificationSupported: boolean; isEnabled: boolean; numNotifications: number; + hasNotificationSupport: boolean; userSetting: UserSetting; } @@ -11,6 +12,7 @@ interface Status { shouldClearNotifications: boolean; shouldPlayNotificationSound: boolean; shouldShowNotifications: boolean; + hasNotificationSupport: boolean; type: Type; } @@ -23,22 +25,30 @@ type Type = | 'noNotifications' | 'userSetting'; -export const getStatus = (environment: Environment): Status => { +export const getStatus = ({ + hasNotificationSupport, + isAppFocused, + isAudioNotificationEnabled, + isAudioNotificationSupported, + isEnabled, + numNotifications, + userSetting, +}: Environment): Status => { const type = ((): Type => { - if (!environment.isEnabled) { + if (!isEnabled) { return 'disabled'; } - const hasNotifications = environment.numNotifications > 0; + const hasNotifications = numNotifications > 0; if (!hasNotifications) { return 'noNotifications'; } - if (environment.isAppFocused) { + if (isAppFocused) { return 'appIsFocused'; } - if (environment.userSetting === 'off') { + if (userSetting === 'off') { return 'userSetting'; } @@ -46,12 +56,14 @@ export const getStatus = (environment: Environment): Status => { })(); const shouldPlayNotificationSound = - environment.isAudioNotificationSupported && - environment.isAudioNotificationEnabled; + isAudioNotificationSupported && + isAudioNotificationEnabled && + hasNotificationSupport; const shouldShowNotifications = type === 'ok'; const shouldClearNotifications = type === 'appIsFocused'; return { + hasNotificationSupport, shouldClearNotifications, shouldPlayNotificationSound, shouldShowNotifications, From c591c3ca5510adec9ec4701a93fd607a0fa478c7 Mon Sep 17 00:00:00 2001 From: Daniel Gasienica Date: Wed, 2 May 2018 19:06:03 -0400 Subject: [PATCH 08/13] Use native notifications on all platforms --- js/notifications.js | 34 ++++++++-------------------------- main.js | 13 ------------- preload.js | 1 - ts/notifications/getStatus.ts | 8 +------- 4 files changed, 9 insertions(+), 47 deletions(-) diff --git a/js/notifications.js b/js/notifications.js index e27bb910d..91091d39f 100644 --- a/js/notifications.js +++ b/js/notifications.js @@ -1,7 +1,5 @@ /* global Backbone: false */ -/* global nodeNotifier: false */ -/* global config: false */ /* global ConversationController: false */ /* global drawAttention: false */ /* global i18n: false */ @@ -42,10 +40,8 @@ const isAudioNotificationSupported = Settings.isAudioNotificationSupported(); const numNotifications = this.length; const userSetting = this.getUserSetting(); - const hasNotificationSupport = !Boolean(config.polyfillNotifications); const status = Signal.Notifications.getStatus({ - hasNotificationSupport, isAppFocused, isAudioNotificationEnabled, isAudioNotificationSupported, @@ -104,28 +100,14 @@ drawAttention(); - if (hasNotificationSupport) { - const notification = new Notification(title, { - body: message, - icon: iconUrl, - tag: 'signal', - silent: !status.shouldPlayNotificationSound, - }); - - notification.onclick = this.onClick.bind( - this, - last.get('conversationId') - ); - } else { - nodeNotifier.notify({ - title, - message, - sound: false, - }); - nodeNotifier.on('click', () => { - last.get('conversationId'); - }); - } + const notification = new Notification(title, { + body: message, + icon: iconUrl, + tag: 'signal', + silent: !status.shouldPlayNotificationSound, + }); + + notification.onclick = () => this.onClick(last.get('conversationId')); // We don't want to notify the user about these same messages again this.clear(); diff --git a/main.js b/main.js index 51b556aff..93e46cee4 100644 --- a/main.js +++ b/main.js @@ -4,7 +4,6 @@ const os = require('os'); const _ = require('lodash'); const electron = require('electron'); -const semver = require('semver'); const { BrowserWindow, app, Menu, shell, ipcMain: ipc } = electron; @@ -99,17 +98,6 @@ const loadLocale = require('./app/locale').load; let logger; let locale; -const WINDOWS_8 = '8.0.0'; -const osRelease = os.release(); -const polyfillNotifications = - os.platform() === 'win32' && semver.lt(osRelease, WINDOWS_8); -console.log( - 'OS Release:', - osRelease, - '- notifications polyfill?', - polyfillNotifications -); - function prepareURL(pathSegments) { return url.format({ pathname: path.join.apply(null, pathSegments), @@ -127,7 +115,6 @@ function prepareURL(pathSegments) { node_version: process.versions.node, hostname: os.hostname(), appInstance: process.env.NODE_APP_INSTANCE, - polyfillNotifications: polyfillNotifications ? true : undefined, // for stringify() proxyUrl: process.env.HTTPS_PROXY || process.env.https_proxy, importMode: importMode ? true : undefined, // for stringify() }, diff --git a/preload.js b/preload.js index 30fad8331..dc729e5ad 100644 --- a/preload.js +++ b/preload.js @@ -101,7 +101,6 @@ window.loadImage = require('blueimp-load-image'); window.nodeBuffer = Buffer; window.nodeFetch = require('node-fetch'); -window.nodeNotifier = require('node-notifier'); window.ProxyAgent = require('proxy-agent'); // Note: when modifying this file, consider whether our React Components or Backbone Views diff --git a/ts/notifications/getStatus.ts b/ts/notifications/getStatus.ts index 9f82eacb2..7c693435c 100644 --- a/ts/notifications/getStatus.ts +++ b/ts/notifications/getStatus.ts @@ -4,7 +4,6 @@ interface Environment { isAudioNotificationSupported: boolean; isEnabled: boolean; numNotifications: number; - hasNotificationSupport: boolean; userSetting: UserSetting; } @@ -12,7 +11,6 @@ interface Status { shouldClearNotifications: boolean; shouldPlayNotificationSound: boolean; shouldShowNotifications: boolean; - hasNotificationSupport: boolean; type: Type; } @@ -26,7 +24,6 @@ type Type = | 'userSetting'; export const getStatus = ({ - hasNotificationSupport, isAppFocused, isAudioNotificationEnabled, isAudioNotificationSupported, @@ -56,14 +53,11 @@ export const getStatus = ({ })(); const shouldPlayNotificationSound = - isAudioNotificationSupported && - isAudioNotificationEnabled && - hasNotificationSupport; + isAudioNotificationSupported && isAudioNotificationEnabled; const shouldShowNotifications = type === 'ok'; const shouldClearNotifications = type === 'appIsFocused'; return { - hasNotificationSupport, shouldClearNotifications, shouldPlayNotificationSound, shouldShowNotifications, From e3191c901717401854bb08b6b88ceae4b0941022 Mon Sep 17 00:00:00 2001 From: Daniel Gasienica Date: Wed, 2 May 2018 19:06:14 -0400 Subject: [PATCH 09/13] Remove `node-notifier` --- package.json | 1 - yarn.lock | 19 +------------------ 2 files changed, 1 insertion(+), 19 deletions(-) diff --git a/package.json b/package.json index fd447c78f..70f0047ae 100644 --- a/package.json +++ b/package.json @@ -67,7 +67,6 @@ "mkdirp": "^0.5.1", "moment": "^2.21.0", "node-fetch": "https://github.com/scottnonnenberg/node-fetch.git#3e5f51e08c647ee5f20c43b15cf2d352d61c36b4", - "node-notifier": "^5.1.2", "os-locale": "^2.1.0", "pify": "^3.0.0", "proxy-agent": "^2.1.0", diff --git a/yarn.lock b/yarn.lock index af4b0221d..de9214ce5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3789,10 +3789,6 @@ growl@1.10.3: version "1.10.3" resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.3.tgz#1926ba90cf3edfe2adb4927f5880bc22c66c790f" -growly@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081" - grunt-cli@^1.2.0, grunt-cli@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/grunt-cli/-/grunt-cli-1.2.0.tgz#562b119ebb069ddb464ace2845501be97b35b6a8" @@ -5882,15 +5878,6 @@ node-libs-browser@^2.0.0: util "^0.10.3" vm-browserify "0.0.4" -node-notifier@^5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/node-notifier/-/node-notifier-5.1.2.tgz#2fa9e12605fa10009d44549d6fcd8a63dde0e4ff" - dependencies: - growly "^1.3.0" - semver "^5.3.0" - shellwords "^0.1.0" - which "^1.2.12" - node-pre-gyp@^0.6.39: version "0.6.39" resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.6.39.tgz#c00e96860b23c0e1420ac7befc5044e1d78d8649" @@ -7997,10 +7984,6 @@ shelljs@0.3.x: version "0.3.0" resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.3.0.tgz#3596e6307a781544f591f37da618360f31db57b1" -shellwords@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/shellwords/-/shellwords-0.1.1.tgz#d6b9181c1a48d397324c84871efbcfc73fc0654b" - signal-exit@^3.0.0, signal-exit@^3.0.1, signal-exit@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" @@ -9507,7 +9490,7 @@ which@1, which@^1.2.9, which@~1.2.1: dependencies: isexe "^2.0.0" -which@^1.2.10, which@^1.2.12, which@^1.2.14, which@^1.3.0: +which@^1.2.10, which@^1.2.14, which@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/which/-/which-1.3.0.tgz#ff04bdfc010ee547d780bec38e1ac1c2777d253a" dependencies: From 0b4c60c272b93b584e321ea6a155309abf7d8fe2 Mon Sep 17 00:00:00 2001 From: Daniel Gasienica Date: Wed, 2 May 2018 19:57:41 -0400 Subject: [PATCH 10/13] Add `@types/sinon` --- package.json | 1 + yarn.lock | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/package.json b/package.json index 70f0047ae..09c3b39f4 100644 --- a/package.json +++ b/package.json @@ -91,6 +91,7 @@ "@types/qs": "^6.5.1", "@types/react": "^16.3.1", "@types/react-dom": "^16.0.4", + "@types/sinon": "^4.3.1", "arraybuffer-loader": "^1.0.3", "asar": "^0.14.0", "bower": "^1.8.2", diff --git a/yarn.lock b/yarn.lock index de9214ce5..6b509abca 100644 --- a/yarn.lock +++ b/yarn.lock @@ -83,6 +83,10 @@ version "16.3.1" resolved "https://registry.yarnpkg.com/@types/react/-/react-16.3.1.tgz#6f6aaffaf7dba502ff5ca15e4aa18caee9b04995" +"@types/sinon@^4.3.1": + version "4.3.1" + resolved "https://registry.yarnpkg.com/@types/sinon/-/sinon-4.3.1.tgz#32458f9b166cd44c23844eee4937814276f35199" + "@vxna/mini-html-webpack-template@^0.1.6": version "0.1.6" resolved "https://registry.yarnpkg.com/@vxna/mini-html-webpack-template/-/mini-html-webpack-template-0.1.6.tgz#64225d564da5fe610b6445523c245572923c00b8" From 38b23c662787a5df0c45ba001c1a9289cfd19664 Mon Sep 17 00:00:00 2001 From: Daniel Gasienica Date: Wed, 2 May 2018 20:01:49 -0400 Subject: [PATCH 11/13] Add `@types/semver` --- package.json | 1 + yarn.lock | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/package.json b/package.json index 09c3b39f4..e4d07bc3b 100644 --- a/package.json +++ b/package.json @@ -91,6 +91,7 @@ "@types/qs": "^6.5.1", "@types/react": "^16.3.1", "@types/react-dom": "^16.0.4", + "@types/semver": "^5.5.0", "@types/sinon": "^4.3.1", "arraybuffer-loader": "^1.0.3", "asar": "^0.14.0", diff --git a/yarn.lock b/yarn.lock index 6b509abca..47540d5bb 100644 --- a/yarn.lock +++ b/yarn.lock @@ -83,6 +83,10 @@ version "16.3.1" resolved "https://registry.yarnpkg.com/@types/react/-/react-16.3.1.tgz#6f6aaffaf7dba502ff5ca15e4aa18caee9b04995" +"@types/semver@^5.5.0": + version "5.5.0" + resolved "https://registry.yarnpkg.com/@types/semver/-/semver-5.5.0.tgz#146c2a29ee7d3bae4bf2fcb274636e264c813c45" + "@types/sinon@^4.3.1": version "4.3.1" resolved "https://registry.yarnpkg.com/@types/sinon/-/sinon-4.3.1.tgz#32458f9b166cd44c23844eee4937814276f35199" From a102016ed8edf737f849d36fb48f1a82935ecf28 Mon Sep 17 00:00:00 2001 From: Daniel Gasienica Date: Wed, 2 May 2018 19:57:02 -0400 Subject: [PATCH 12/13] Port `Settings` and `OS` to TypeScript --- js/modules/os.js | 7 ----- js/modules/types/settings.js | 3 -- preload.js | 4 +-- ts/OS.ts | 15 ++++++++++ .../test/types/Settings_test.ts | 30 +++++++++++-------- ts/types/Settings.ts | 4 +++ 6 files changed, 38 insertions(+), 25 deletions(-) delete mode 100644 js/modules/os.js delete mode 100644 js/modules/types/settings.js create mode 100644 ts/OS.ts rename test/modules/types/settings_test.js => ts/test/types/Settings_test.ts (61%) create mode 100644 ts/types/Settings.ts diff --git a/js/modules/os.js b/js/modules/os.js deleted file mode 100644 index 245172f68..000000000 --- a/js/modules/os.js +++ /dev/null @@ -1,7 +0,0 @@ -/* eslint-env node */ - -exports.isMacOS = () => process.platform === 'darwin'; - -exports.isLinux = () => process.platform === 'linux'; - -exports.isWindows = () => process.platform === 'win32'; diff --git a/js/modules/types/settings.js b/js/modules/types/settings.js deleted file mode 100644 index 85fbd7add..000000000 --- a/js/modules/types/settings.js +++ /dev/null @@ -1,3 +0,0 @@ -const OS = require('../os'); - -exports.isAudioNotificationSupported = () => !OS.isLinux(); diff --git a/preload.js b/preload.js index dc729e5ad..412456a88 100644 --- a/preload.js +++ b/preload.js @@ -200,7 +200,7 @@ window.Signal.Migrations.Migrations1DatabaseWithoutAttachmentData = require('./j window.Signal.Migrations.upgradeMessageSchema = upgradeMessageSchema; window.Signal.Notifications = require('./ts/notifications'); -window.Signal.OS = require('./js/modules/os'); +window.Signal.OS = require('./ts/OS'); window.Signal.Settings = require('./js/modules/settings'); window.Signal.Startup = require('./js/modules/startup'); @@ -211,7 +211,7 @@ window.Signal.Types.Errors = require('./js/modules/types/errors'); window.Signal.Types.Message = Message; window.Signal.Types.MIME = require('./ts/types/MIME'); -window.Signal.Types.Settings = require('./js/modules/types/settings'); +window.Signal.Types.Settings = require('./ts/types/Settings'); window.Signal.Util = require('./ts/util'); window.Signal.Views = {}; diff --git a/ts/OS.ts b/ts/OS.ts new file mode 100644 index 000000000..efc71bf9e --- /dev/null +++ b/ts/OS.ts @@ -0,0 +1,15 @@ +import is from '@sindresorhus/is'; +import os from 'os'; +import semver from 'semver'; + +export const isMacOS = () => process.platform === 'darwin'; +export const isLinux = () => process.platform === 'linux'; +export const isWindows = (minVersion?: string) => { + const isPlatformValid = process.platform === 'win32'; + const osRelease = os.release(); + const isVersionValid = is.undefined(minVersion) + ? true + : semver.gte(osRelease, minVersion); + + return isPlatformValid && isVersionValid; +}; diff --git a/test/modules/types/settings_test.js b/ts/test/types/Settings_test.ts similarity index 61% rename from test/modules/types/settings_test.js rename to ts/test/types/Settings_test.ts index 59f195348..306e0ef99 100644 --- a/test/modules/types/settings_test.js +++ b/ts/test/types/Settings_test.ts @@ -1,7 +1,8 @@ -const sinon = require('sinon'); -const { assert } = require('chai'); +import os from 'os'; +import sinon from 'sinon'; +import { assert } from 'chai'; -const Settings = require('../../../js/modules/types/settings'); +import * as Settings from '../../../ts/types/Settings'; describe('Settings', () => { const sandbox = sinon.createSandbox(); @@ -22,16 +23,19 @@ describe('Settings', () => { }); context('on Windows', () => { - beforeEach(() => { - sandbox.stub(process, 'platform').value('win32'); - }); - - afterEach(() => { - sandbox.restore(); - }); - - it('should return true', () => { - assert.isTrue(Settings.isAudioNotificationSupported()); + context('version 8+', () => { + beforeEach(() => { + sandbox.stub(process, 'platform').value('win32'); + sandbox.stub(os, 'release').returns('8.0.0'); + }); + + afterEach(() => { + sandbox.restore(); + }); + + it('should return true', () => { + assert.isTrue(Settings.isAudioNotificationSupported()); + }); }); }); diff --git a/ts/types/Settings.ts b/ts/types/Settings.ts new file mode 100644 index 000000000..521106230 --- /dev/null +++ b/ts/types/Settings.ts @@ -0,0 +1,4 @@ +import * as OS from '../OS'; + +export const isAudioNotificationSupported = () => + OS.isWindows() || OS.isMacOS(); From ecf23b6b2edb67466c1f7fdcd3c5890de3a73ba3 Mon Sep 17 00:00:00 2001 From: Daniel Gasienica Date: Wed, 2 May 2018 19:58:23 -0400 Subject: [PATCH 13/13] Disable audio notifications on Windows 7 and lower --- ts/test/types/Settings_test.ts | 15 +++++++++++++++ ts/types/Settings.ts | 4 +++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/ts/test/types/Settings_test.ts b/ts/test/types/Settings_test.ts index 306e0ef99..ebd7fd10d 100644 --- a/ts/test/types/Settings_test.ts +++ b/ts/test/types/Settings_test.ts @@ -23,6 +23,21 @@ describe('Settings', () => { }); context('on Windows', () => { + context('version 7', () => { + beforeEach(() => { + sandbox.stub(process, 'platform').value('win32'); + sandbox.stub(os, 'release').returns('7.0.0'); + }); + + afterEach(() => { + sandbox.restore(); + }); + + it('should return false', () => { + assert.isFalse(Settings.isAudioNotificationSupported()); + }); + }); + context('version 8+', () => { beforeEach(() => { sandbox.stub(process, 'platform').value('win32'); diff --git a/ts/types/Settings.ts b/ts/types/Settings.ts index 521106230..08eea3106 100644 --- a/ts/types/Settings.ts +++ b/ts/types/Settings.ts @@ -1,4 +1,6 @@ import * as OS from '../OS'; +const MIN_WINDOWS_VERSION = '8.0.0'; + export const isAudioNotificationSupported = () => - OS.isWindows() || OS.isMacOS(); + OS.isWindows(MIN_WINDOWS_VERSION) || OS.isMacOS();