Remove ts/services/timers.ts
This commit is contained in:
parent
26eabf16a8
commit
a537204fc0
10 changed files with 38 additions and 144 deletions
|
@ -147,7 +147,6 @@ const {
|
||||||
initializeUpdateListener,
|
initializeUpdateListener,
|
||||||
} = require('../../ts/services/updateListener');
|
} = require('../../ts/services/updateListener');
|
||||||
const { calling } = require('../../ts/services/calling');
|
const { calling } = require('../../ts/services/calling');
|
||||||
const { onTimeout, removeTimeout } = require('../../ts/services/timers');
|
|
||||||
const {
|
const {
|
||||||
enableStorageService,
|
enableStorageService,
|
||||||
eraseAllStorageServiceState,
|
eraseAllStorageServiceState,
|
||||||
|
@ -388,8 +387,6 @@ exports.setup = (options = {}) => {
|
||||||
initializeGroupCredentialFetcher,
|
initializeGroupCredentialFetcher,
|
||||||
initializeNetworkObserver,
|
initializeNetworkObserver,
|
||||||
initializeUpdateListener,
|
initializeUpdateListener,
|
||||||
onTimeout,
|
|
||||||
removeTimeout,
|
|
||||||
runStorageServiceSyncJob,
|
runStorageServiceSyncJob,
|
||||||
storageServiceUploadJob,
|
storageServiceUploadJob,
|
||||||
};
|
};
|
||||||
|
|
|
@ -383,11 +383,6 @@ try {
|
||||||
version: config.version,
|
version: config.version,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Linux seems to periodically let the event loop stop, so this is a global workaround
|
|
||||||
setInterval(() => {
|
|
||||||
window.nodeSetImmediate(() => {});
|
|
||||||
}, 1000);
|
|
||||||
|
|
||||||
const { imageToBlurHash } = require('./ts/util/imageToBlurHash');
|
const { imageToBlurHash } = require('./ts/util/imageToBlurHash');
|
||||||
const { isValidGuid } = require('./ts/util/isValidGuid');
|
const { isValidGuid } = require('./ts/util/isValidGuid');
|
||||||
const { ActiveWindowService } = require('./ts/services/ActiveWindowService');
|
const { ActiveWindowService } = require('./ts/services/ActiveWindowService');
|
||||||
|
|
|
@ -54,7 +54,10 @@ export function start(): void {
|
||||||
this.on('add remove change:unreadCount', debouncedUpdateUnreadCount);
|
this.on('add remove change:unreadCount', debouncedUpdateUnreadCount);
|
||||||
window.Whisper.events.on('updateUnreadCount', debouncedUpdateUnreadCount);
|
window.Whisper.events.on('updateUnreadCount', debouncedUpdateUnreadCount);
|
||||||
this.on('add', (model: ConversationModel): void => {
|
this.on('add', (model: ConversationModel): void => {
|
||||||
this.initMuteExpirationTimer(model);
|
// If the conversation is muted we set a timeout so when the mute expires
|
||||||
|
// we can reset the mute state on the model. If the mute has already expired
|
||||||
|
// then we reset the state right away.
|
||||||
|
model.startMuteTimer();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
addActive(model: ConversationModel) {
|
addActive(model: ConversationModel) {
|
||||||
|
@ -64,25 +67,6 @@ export function start(): void {
|
||||||
this.remove(model);
|
this.remove(model);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// If the conversation is muted we set a timeout so when the mute expires
|
|
||||||
// we can reset the mute state on the model. If the mute has already expired
|
|
||||||
// then we reset the state right away.
|
|
||||||
initMuteExpirationTimer(model: ConversationModel): void {
|
|
||||||
const muteExpiresAt = model.get('muteExpiresAt');
|
|
||||||
// This check for `muteExpiresAt` is likely redundant, but is needed to appease
|
|
||||||
// TypeScript.
|
|
||||||
if (model.isMuted() && muteExpiresAt) {
|
|
||||||
window.Signal.Services.onTimeout(
|
|
||||||
muteExpiresAt,
|
|
||||||
() => {
|
|
||||||
model.set({ muteExpiresAt: undefined });
|
|
||||||
},
|
|
||||||
model.getMuteTimeoutId()
|
|
||||||
);
|
|
||||||
} else if (muteExpiresAt) {
|
|
||||||
model.set({ muteExpiresAt: undefined });
|
|
||||||
}
|
|
||||||
},
|
|
||||||
updateUnreadCount() {
|
updateUnreadCount() {
|
||||||
const canCountMutedConversations = window.storage.get(
|
const canCountMutedConversations = window.storage.get(
|
||||||
'badge-count-muted-conversations'
|
'badge-count-muted-conversations'
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
import React, { KeyboardEvent, MouseEvent, ReactNode, useEffect } from 'react';
|
import React, { KeyboardEvent, MouseEvent, ReactNode, useEffect } from 'react';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { createPortal } from 'react-dom';
|
import { createPortal } from 'react-dom';
|
||||||
import { onTimeout, removeTimeout } from '../services/timers';
|
|
||||||
import { useRestoreFocus } from '../hooks/useRestoreFocus';
|
import { useRestoreFocus } from '../hooks/useRestoreFocus';
|
||||||
|
|
||||||
export type PropsType = {
|
export type PropsType = {
|
||||||
|
@ -48,11 +47,11 @@ export const Toast = ({
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const timeoutId = onTimeout(Date.now() + timeout, onClose);
|
const timeoutId = setTimeout(onClose, timeout);
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
if (timeoutId) {
|
if (timeoutId) {
|
||||||
removeTimeout(timeoutId);
|
clearTimeout(timeoutId);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}, [autoDismissDisabled, onClose, root, timeout]);
|
}, [autoDismissDisabled, onClose, root, timeout]);
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
/* eslint-disable class-methods-use-this */
|
/* eslint-disable class-methods-use-this */
|
||||||
/* eslint-disable camelcase */
|
/* eslint-disable camelcase */
|
||||||
import { compact } from 'lodash';
|
import { compact, isNumber } from 'lodash';
|
||||||
import {
|
import {
|
||||||
ConversationAttributesType,
|
ConversationAttributesType,
|
||||||
ConversationModelCollectionType,
|
ConversationModelCollectionType,
|
||||||
|
@ -190,6 +190,8 @@ export class ConversationModel extends window.Backbone
|
||||||
|
|
||||||
private lastIsTyping?: boolean;
|
private lastIsTyping?: boolean;
|
||||||
|
|
||||||
|
private muteTimer?: NodeJS.Timer;
|
||||||
|
|
||||||
// eslint-disable-next-line class-methods-use-this
|
// eslint-disable-next-line class-methods-use-this
|
||||||
defaults(): Partial<ConversationAttributesType> {
|
defaults(): Partial<ConversationAttributesType> {
|
||||||
return {
|
return {
|
||||||
|
@ -1593,7 +1595,7 @@ export class ConversationModel extends window.Backbone
|
||||||
}
|
}
|
||||||
|
|
||||||
const temporaryMemberCount = this.get('temporaryMemberCount');
|
const temporaryMemberCount = this.get('temporaryMemberCount');
|
||||||
if (window._.isNumber(temporaryMemberCount)) {
|
if (isNumber(temporaryMemberCount)) {
|
||||||
return temporaryMemberCount;
|
return temporaryMemberCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4826,6 +4828,24 @@ export class ConversationModel extends window.Backbone
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
startMuteTimer(): void {
|
||||||
|
if (this.muteTimer !== undefined) {
|
||||||
|
clearTimeout(this.muteTimer);
|
||||||
|
this.muteTimer = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
const muteExpiresAt = this.get('muteExpiresAt');
|
||||||
|
if (isNumber(muteExpiresAt) && muteExpiresAt < Number.MAX_SAFE_INTEGER) {
|
||||||
|
const delay = muteExpiresAt - Date.now();
|
||||||
|
if (delay <= 0) {
|
||||||
|
this.setMuteExpiration(0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.muteTimer = setTimeout(() => this.setMuteExpiration(0), delay);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
setMuteExpiration(
|
setMuteExpiration(
|
||||||
muteExpiresAt = 0,
|
muteExpiresAt = 0,
|
||||||
{ viaStorageServiceSync = false } = {}
|
{ viaStorageServiceSync = false } = {}
|
||||||
|
@ -4836,26 +4856,8 @@ export class ConversationModel extends window.Backbone
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// we use a timeoutId here so that we can reference the mute that was
|
|
||||||
// potentially set in the ConversationController. Specifically for a
|
|
||||||
// scenario where a conversation is already muted and we boot up the app,
|
|
||||||
// a timeout will be already set. But if we change the mute to a later
|
|
||||||
// date a new timeout would need to be set and the old one cleared. With
|
|
||||||
// this ID we can reference the existing timeout.
|
|
||||||
const timeoutId = this.getMuteTimeoutId();
|
|
||||||
window.Signal.Services.removeTimeout(timeoutId);
|
|
||||||
|
|
||||||
if (muteExpiresAt && muteExpiresAt < Number.MAX_SAFE_INTEGER) {
|
|
||||||
window.Signal.Services.onTimeout(
|
|
||||||
muteExpiresAt,
|
|
||||||
() => {
|
|
||||||
this.setMuteExpiration(0);
|
|
||||||
},
|
|
||||||
timeoutId
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.set({ muteExpiresAt });
|
this.set({ muteExpiresAt });
|
||||||
|
this.startMuteTimer();
|
||||||
if (!viaStorageServiceSync) {
|
if (!viaStorageServiceSync) {
|
||||||
this.captureChange('mutedUntilTimestamp');
|
this.captureChange('mutedUntilTimestamp');
|
||||||
}
|
}
|
||||||
|
@ -4866,10 +4868,6 @@ export class ConversationModel extends window.Backbone
|
||||||
return isMuted(this.get('muteExpiresAt'));
|
return isMuted(this.get('muteExpiresAt'));
|
||||||
}
|
}
|
||||||
|
|
||||||
getMuteTimeoutId(): string {
|
|
||||||
return `mute(${this.get('id')})`;
|
|
||||||
}
|
|
||||||
|
|
||||||
async notify(
|
async notify(
|
||||||
message: Readonly<MessageModel>,
|
message: Readonly<MessageModel>,
|
||||||
reaction?: WhatIsThis
|
reaction?: WhatIsThis
|
||||||
|
|
|
@ -7,18 +7,17 @@ import {
|
||||||
} from '../state/ducks/network';
|
} from '../state/ducks/network';
|
||||||
import { getSocketStatus } from '../shims/socketStatus';
|
import { getSocketStatus } from '../shims/socketStatus';
|
||||||
import * as log from '../logging/log';
|
import * as log from '../logging/log';
|
||||||
|
import { SECOND } from '../util/durations';
|
||||||
|
|
||||||
type NetworkActions = {
|
type NetworkActions = {
|
||||||
checkNetworkStatus: (x: CheckNetworkStatusPayloadType) => NetworkActionType;
|
checkNetworkStatus: (x: CheckNetworkStatusPayloadType) => NetworkActionType;
|
||||||
closeConnectingGracePeriod: () => NetworkActionType;
|
closeConnectingGracePeriod: () => NetworkActionType;
|
||||||
};
|
};
|
||||||
|
|
||||||
const REFRESH_INTERVAL = 5000;
|
|
||||||
|
|
||||||
export function initializeNetworkObserver(
|
export function initializeNetworkObserver(
|
||||||
networkActions: NetworkActions
|
networkActions: NetworkActions
|
||||||
): void {
|
): void {
|
||||||
log.info(`Initializing network observer every ${REFRESH_INTERVAL}ms`);
|
log.info('Initializing network observer');
|
||||||
|
|
||||||
const refresh = () => {
|
const refresh = () => {
|
||||||
networkActions.checkNetworkStatus({
|
networkActions.checkNetworkStatus({
|
||||||
|
@ -31,8 +30,7 @@ export function initializeNetworkObserver(
|
||||||
|
|
||||||
window.addEventListener('online', refresh);
|
window.addEventListener('online', refresh);
|
||||||
window.addEventListener('offline', refresh);
|
window.addEventListener('offline', refresh);
|
||||||
window.setInterval(refresh, REFRESH_INTERVAL);
|
|
||||||
window.setTimeout(() => {
|
window.setTimeout(() => {
|
||||||
networkActions.closeConnectingGracePeriod();
|
networkActions.closeConnectingGracePeriod();
|
||||||
}, REFRESH_INTERVAL);
|
}, 5 * SECOND);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,73 +0,0 @@
|
||||||
// Copyright 2020 Signal Messenger, LLC
|
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
|
||||||
|
|
||||||
import { v4 as getGuid } from 'uuid';
|
|
||||||
|
|
||||||
type TimeoutType = {
|
|
||||||
timestamp: number;
|
|
||||||
uuid: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
const timeoutStore: Map<string, () => void> = new Map();
|
|
||||||
const allTimeouts: Set<TimeoutType> = new Set();
|
|
||||||
|
|
||||||
setInterval(() => {
|
|
||||||
if (!allTimeouts.size) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const now = Date.now();
|
|
||||||
|
|
||||||
allTimeouts.forEach((timeout: TimeoutType) => {
|
|
||||||
const { timestamp, uuid } = timeout;
|
|
||||||
|
|
||||||
if (now >= timestamp) {
|
|
||||||
if (timeoutStore.has(uuid)) {
|
|
||||||
const callback = timeoutStore.get(uuid);
|
|
||||||
if (callback) {
|
|
||||||
callback();
|
|
||||||
}
|
|
||||||
timeoutStore.delete(uuid);
|
|
||||||
}
|
|
||||||
|
|
||||||
allTimeouts.delete(timeout);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}, 100);
|
|
||||||
|
|
||||||
export function onTimeout(
|
|
||||||
timestamp: number,
|
|
||||||
callback: () => void,
|
|
||||||
id?: string
|
|
||||||
): string {
|
|
||||||
if (id && timeoutStore.has(id)) {
|
|
||||||
throw new ReferenceError(`onTimeout: ${id} already exists`);
|
|
||||||
}
|
|
||||||
|
|
||||||
let uuid = id || getGuid();
|
|
||||||
while (timeoutStore.has(uuid)) {
|
|
||||||
uuid = getGuid();
|
|
||||||
}
|
|
||||||
|
|
||||||
timeoutStore.set(uuid, callback);
|
|
||||||
allTimeouts.add({
|
|
||||||
timestamp,
|
|
||||||
uuid,
|
|
||||||
});
|
|
||||||
|
|
||||||
return uuid;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function removeTimeout(uuid: string): void {
|
|
||||||
if (!timeoutStore.has(uuid)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
timeoutStore.delete(uuid);
|
|
||||||
|
|
||||||
allTimeouts.forEach((timeout: TimeoutType) => {
|
|
||||||
if (uuid === timeout.uuid) {
|
|
||||||
allTimeouts.delete(timeout);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
|
@ -4,8 +4,8 @@
|
||||||
import { ThunkAction } from 'redux-thunk';
|
import { ThunkAction } from 'redux-thunk';
|
||||||
import * as updateIpc from '../../shims/updateIpc';
|
import * as updateIpc from '../../shims/updateIpc';
|
||||||
import { DialogType } from '../../types/Dialogs';
|
import { DialogType } from '../../types/Dialogs';
|
||||||
|
import { DAY } from '../../util/durations';
|
||||||
import { StateType as RootStateType } from '../reducer';
|
import { StateType as RootStateType } from '../reducer';
|
||||||
import { onTimeout } from '../../services/timers';
|
|
||||||
|
|
||||||
// State
|
// State
|
||||||
|
|
||||||
|
@ -85,8 +85,6 @@ function showUpdateDialog(
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const ONE_DAY = 24 * 60 * 60 * 1000;
|
|
||||||
|
|
||||||
function snoozeUpdate(): ThunkAction<
|
function snoozeUpdate(): ThunkAction<
|
||||||
void,
|
void,
|
||||||
RootStateType,
|
RootStateType,
|
||||||
|
@ -95,12 +93,12 @@ function snoozeUpdate(): ThunkAction<
|
||||||
> {
|
> {
|
||||||
return (dispatch, getState) => {
|
return (dispatch, getState) => {
|
||||||
const { dialogType } = getState().updates;
|
const { dialogType } = getState().updates;
|
||||||
onTimeout(Date.now() + ONE_DAY, () => {
|
setTimeout(() => {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: UNSNOOZE_UPDATE,
|
type: UNSNOOZE_UPDATE,
|
||||||
payload: dialogType,
|
payload: dialogType,
|
||||||
});
|
});
|
||||||
});
|
}, DAY);
|
||||||
|
|
||||||
dispatch({
|
dispatch({
|
||||||
type: SNOOZE_UPDATE,
|
type: SNOOZE_UPDATE,
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
// Copyright 2021 Signal Messenger, LLC
|
// Copyright 2021 Signal Messenger, LLC
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
import { onTimeout } from '../services/timers';
|
import { MINUTE } from './durations';
|
||||||
|
|
||||||
class PostLinkExperience {
|
class PostLinkExperience {
|
||||||
private hasNotFinishedSync: boolean;
|
private hasNotFinishedSync: boolean;
|
||||||
|
@ -15,9 +15,9 @@ class PostLinkExperience {
|
||||||
|
|
||||||
// timeout "post link" after 10 minutes in case the syncs don't complete
|
// timeout "post link" after 10 minutes in case the syncs don't complete
|
||||||
// in time or are never called.
|
// in time or are never called.
|
||||||
onTimeout(Date.now() + 60 * 60 * 10 * 1000, () => {
|
setTimeout(() => {
|
||||||
this.stop();
|
this.stop();
|
||||||
});
|
}, 10 * MINUTE);
|
||||||
}
|
}
|
||||||
|
|
||||||
stop() {
|
stop() {
|
||||||
|
|
2
ts/window.d.ts
vendored
2
ts/window.d.ts
vendored
|
@ -291,8 +291,6 @@ declare global {
|
||||||
initializeGroupCredentialFetcher: () => void;
|
initializeGroupCredentialFetcher: () => void;
|
||||||
initializeNetworkObserver: (network: ReduxActions['network']) => void;
|
initializeNetworkObserver: (network: ReduxActions['network']) => void;
|
||||||
initializeUpdateListener: (updates: ReduxActions['updates']) => void;
|
initializeUpdateListener: (updates: ReduxActions['updates']) => void;
|
||||||
onTimeout: (timestamp: number, cb: () => void, id?: string) => string;
|
|
||||||
removeTimeout: (uuid: string) => void;
|
|
||||||
retryPlaceholders?: Util.RetryPlaceholders;
|
retryPlaceholders?: Util.RetryPlaceholders;
|
||||||
lightSessionResetQueue?: PQueue;
|
lightSessionResetQueue?: PQueue;
|
||||||
runStorageServiceSyncJob: () => Promise<void>;
|
runStorageServiceSyncJob: () => Promise<void>;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue