diff --git a/background.html b/background.html
index dd6ae604e..c0da6a528 100644
--- a/background.html
+++ b/background.html
@@ -449,7 +449,6 @@
-
diff --git a/js/background.js b/js/background.js
index 6eda29047..3e52cd598 100644
--- a/js/background.js
+++ b/js/background.js
@@ -40,6 +40,43 @@
false
);
+ // Idle timer - you're active for ACTIVE_TIMEOUT after one of these events
+ const ACTIVE_TIMEOUT = 15 * 1000;
+ const ACTIVE_EVENTS = [
+ 'click',
+ 'keypress',
+ 'mousedown',
+ 'mousemove',
+ // 'scroll', // this is triggered by Timeline re-renders, can't use
+ 'touchstart',
+ 'wheel',
+ ];
+
+ const LISTENER_DEBOUNCE = 5 * 1000;
+ let activeHandlers = [];
+ let activeTimestamp = Date.now();
+
+ window.resetActiveTimer = _.throttle(() => {
+ const previouslyActive = window.isActive();
+ activeTimestamp = Date.now();
+ if (!previouslyActive) {
+ activeHandlers.forEach(handler => handler());
+ }
+ }, LISTENER_DEBOUNCE);
+
+ ACTIVE_EVENTS.forEach(name => {
+ document.addEventListener(name, window.resetActiveTimer, true);
+ });
+
+ window.isActive = () => {
+ const now = Date.now();
+ return now <= activeTimestamp + ACTIVE_TIMEOUT;
+ };
+ window.registerForActive = handler => activeHandlers.push(handler);
+ window.unregisterForActive = handler => {
+ activeHandlers = activeHandlers.filter(item => item !== handler);
+ };
+
// Load these images now to ensure that they don't flicker on first use
window.Signal.EmojiLib.preloadImages();
const images = [];
@@ -712,7 +749,7 @@
}
});
- window.addEventListener('focus', () => Whisper.Notifications.clear());
+ window.registerForActive(() => Whisper.Notifications.clear());
window.addEventListener('unload', () => Whisper.Notifications.fastClear());
Whisper.events.on('showConversation', (id, messageId) => {
diff --git a/js/focus_listener.js b/js/focus_listener.js
deleted file mode 100644
index c9a728233..000000000
--- a/js/focus_listener.js
+++ /dev/null
@@ -1,14 +0,0 @@
-// eslint-disable-next-line func-names
-(function() {
- 'use strict';
-
- let windowFocused = false;
- window.addEventListener('blur', () => {
- windowFocused = false;
- });
- window.addEventListener('focus', () => {
- windowFocused = true;
- });
-
- window.isFocused = () => windowFocused;
-})();
diff --git a/js/models/conversations.js b/js/models/conversations.js
index edaa94ac1..e9bc61d42 100644
--- a/js/models/conversations.js
+++ b/js/models/conversations.js
@@ -334,7 +334,7 @@
this.id,
[model.getReduxData()],
isNewMessage,
- document.hasFocus()
+ window.isActive()
);
}
diff --git a/js/notifications.js b/js/notifications.js
index 7c0fb39ae..8df33aa42 100644
--- a/js/notifications.js
+++ b/js/notifications.js
@@ -3,7 +3,6 @@
/* global drawAttention: false */
/* global i18n: false */
-/* global isFocused: false */
/* global Signal: false */
/* global storage: false */
/* global Whisper: false */
@@ -54,7 +53,7 @@
}
const { isEnabled } = this;
- const isAppFocused = isFocused();
+ const isAppFocused = window.isActive();
const isAudioNotificationEnabled =
storage.get('audio-notification') || false;
const isAudioNotificationSupported = Settings.isAudioNotificationSupported();
diff --git a/js/views/app_view.js b/js/views/app_view.js
index 162f0b69f..9321cfd3a 100644
--- a/js/views/app_view.js
+++ b/js/views/app_view.js
@@ -166,7 +166,7 @@
if (!$.contains(this.el, this.inboxView.el)) {
this.openView(this.inboxView);
}
- window.focus(); // FIXME
+
return Promise.resolve();
},
onEmpty() {
diff --git a/js/views/conversation_view.js b/js/views/conversation_view.js
index d30dd663b..bd8115c77 100644
--- a/js/views/conversation_view.js
+++ b/js/views/conversation_view.js
@@ -442,7 +442,7 @@
id,
models.map(model => model.getReduxData()),
isNewMessage,
- document.hasFocus()
+ window.isActive()
);
} catch (error) {
setMessagesLoading(conversationId, true);
@@ -493,7 +493,7 @@
id,
models.map(model => model.getReduxData()),
isNewMessage,
- document.hasFocus()
+ window.isActive()
);
} catch (error) {
setMessagesLoading(conversationId, false);
@@ -502,10 +502,8 @@
finish();
}
};
- const markMessageRead = async (messageId, forceFocus) => {
- // We need a forceFocus parameter because the BrowserWindow focus event fires
- // before the document realizes that it has focus.
- if (!document.hasFocus() && !forceFocus) {
+ const markMessageRead = async messageId => {
+ if (!window.isActive()) {
return;
}
diff --git a/preload.js b/preload.js
index 369fb10ca..8e350791b 100644
--- a/preload.js
+++ b/preload.js
@@ -10,14 +10,6 @@ const { remote } = electron;
const { app } = remote;
const { systemPreferences } = remote.require('electron');
-const browserWindow = remote.getCurrentWindow();
-let focusHandlers = [];
-browserWindow.on('focus', () => focusHandlers.forEach(handler => handler()));
-window.registerForFocus = handler => focusHandlers.push(handler);
-window.unregisterForFocus = handler => {
- focusHandlers = focusHandlers.filter(item => item !== handler);
-};
-
// Waiting for clients to implement changes on receive side
window.ENABLE_STICKER_SEND = true;
window.TIMESTAMP_VALIDATION = false;
diff --git a/test/index.html b/test/index.html
index e51e22adc..9c013d1a6 100644
--- a/test/index.html
+++ b/test/index.html
@@ -476,7 +476,6 @@
-
diff --git a/ts/components/conversation/Timeline.tsx b/ts/components/conversation/Timeline.tsx
index 697a68fd2..5220dd487 100644
--- a/ts/components/conversation/Timeline.tsx
+++ b/ts/components/conversation/Timeline.tsx
@@ -61,7 +61,7 @@ type PropsActionsType = {
loadOlderMessages: (messageId: string) => unknown;
loadNewerMessages: (messageId: string) => unknown;
loadNewestMessages: (messageId: string) => unknown;
- markMessageRead: (messageId: string, forceFocus?: boolean) => unknown;
+ markMessageRead: (messageId: string) => unknown;
} & MessageActionsType &
SafetyNumberActionsType;
@@ -402,7 +402,7 @@ export class Timeline extends React.PureComponent {
// tslint:disable-next-line member-ordering cyclomatic-complexity
public updateWithVisibleRows = debounce(
- (forceFocus?: boolean) => {
+ () => {
const {
unreadCount,
haveNewest,
@@ -426,7 +426,7 @@ export class Timeline extends React.PureComponent {
return;
}
- markMessageRead(newest.id, forceFocus);
+ markMessageRead(newest.id);
const rowCount = this.getRowCount();
@@ -710,19 +710,14 @@ export class Timeline extends React.PureComponent {
public componentDidMount() {
this.updateWithVisibleRows();
// @ts-ignore
- window.registerForFocus(this.forceFocusVisibleRowUpdate);
+ window.registerForActive(this.updateWithVisibleRows);
}
public componentWillUnmount() {
// @ts-ignore
- window.unregisterForFocus(this.forceFocusVisibleRowUpdate);
+ window.unregisterForActive(this.updateWithVisibleRows);
}
- public forceFocusVisibleRowUpdate = () => {
- const forceFocus = true;
- this.updateWithVisibleRows(forceFocus);
- };
-
// tslint:disable-next-line cyclomatic-complexity max-func-body-length
public componentDidUpdate(prevProps: Props) {
const {
diff --git a/ts/state/ducks/conversations.ts b/ts/state/ducks/conversations.ts
index a39eb86b4..264777c72 100644
--- a/ts/state/ducks/conversations.ts
+++ b/ts/state/ducks/conversations.ts
@@ -160,7 +160,7 @@ export type MessagesAddedActionType = {
conversationId: string;
messages: Array;
isNewMessage: boolean;
- isFocused: boolean;
+ isActive: boolean;
};
};
export type MessagesResetActionType = {
@@ -357,7 +357,7 @@ function messagesAdded(
conversationId: string,
messages: Array,
isNewMessage: boolean,
- isFocused: boolean
+ isActive: boolean
): MessagesAddedActionType {
return {
type: 'MESSAGES_ADDED',
@@ -365,7 +365,7 @@ function messagesAdded(
conversationId,
messages,
isNewMessage,
- isFocused,
+ isActive,
},
};
}
@@ -870,12 +870,7 @@ export function reducer(
};
}
if (action.type === 'MESSAGES_ADDED') {
- const {
- conversationId,
- isFocused,
- isNewMessage,
- messages,
- } = action.payload;
+ const { conversationId, isActive, isNewMessage, messages } = action.payload;
const { messagesByConversation, messagesLookup } = state;
const existingConversation = messagesByConversation[conversationId];
@@ -937,7 +932,7 @@ export function reducer(
const newMessageIds = difference(newIds, existingConversation.messageIds);
const { isNearBottom } = existingConversation;
- if ((!isNearBottom || !isFocused) && !oldestUnread) {
+ if ((!isNearBottom || !isActive) && !oldestUnread) {
const oldestId = newMessageIds.find(messageId => {
const message = lookup[messageId];