Remove ts/services/timers.ts

This commit is contained in:
Fedor Indutny 2021-10-06 14:59:34 -07:00 committed by GitHub
parent 26eabf16a8
commit a537204fc0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 38 additions and 144 deletions

View file

@ -147,7 +147,6 @@ const {
initializeUpdateListener,
} = require('../../ts/services/updateListener');
const { calling } = require('../../ts/services/calling');
const { onTimeout, removeTimeout } = require('../../ts/services/timers');
const {
enableStorageService,
eraseAllStorageServiceState,
@ -388,8 +387,6 @@ exports.setup = (options = {}) => {
initializeGroupCredentialFetcher,
initializeNetworkObserver,
initializeUpdateListener,
onTimeout,
removeTimeout,
runStorageServiceSyncJob,
storageServiceUploadJob,
};

View file

@ -383,11 +383,6 @@ try {
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 { isValidGuid } = require('./ts/util/isValidGuid');
const { ActiveWindowService } = require('./ts/services/ActiveWindowService');

View file

@ -54,7 +54,10 @@ export function start(): void {
this.on('add remove change:unreadCount', debouncedUpdateUnreadCount);
window.Whisper.events.on('updateUnreadCount', debouncedUpdateUnreadCount);
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) {
@ -64,25 +67,6 @@ export function start(): void {
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() {
const canCountMutedConversations = window.storage.get(
'badge-count-muted-conversations'

View file

@ -4,7 +4,6 @@
import React, { KeyboardEvent, MouseEvent, ReactNode, useEffect } from 'react';
import classNames from 'classnames';
import { createPortal } from 'react-dom';
import { onTimeout, removeTimeout } from '../services/timers';
import { useRestoreFocus } from '../hooks/useRestoreFocus';
export type PropsType = {
@ -48,11 +47,11 @@ export const Toast = ({
return;
}
const timeoutId = onTimeout(Date.now() + timeout, onClose);
const timeoutId = setTimeout(onClose, timeout);
return () => {
if (timeoutId) {
removeTimeout(timeoutId);
clearTimeout(timeoutId);
}
};
}, [autoDismissDisabled, onClose, root, timeout]);

View file

@ -3,7 +3,7 @@
/* eslint-disable class-methods-use-this */
/* eslint-disable camelcase */
import { compact } from 'lodash';
import { compact, isNumber } from 'lodash';
import {
ConversationAttributesType,
ConversationModelCollectionType,
@ -190,6 +190,8 @@ export class ConversationModel extends window.Backbone
private lastIsTyping?: boolean;
private muteTimer?: NodeJS.Timer;
// eslint-disable-next-line class-methods-use-this
defaults(): Partial<ConversationAttributesType> {
return {
@ -1593,7 +1595,7 @@ export class ConversationModel extends window.Backbone
}
const temporaryMemberCount = this.get('temporaryMemberCount');
if (window._.isNumber(temporaryMemberCount)) {
if (isNumber(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(
muteExpiresAt = 0,
{ viaStorageServiceSync = false } = {}
@ -4836,26 +4856,8 @@ export class ConversationModel extends window.Backbone
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.startMuteTimer();
if (!viaStorageServiceSync) {
this.captureChange('mutedUntilTimestamp');
}
@ -4866,10 +4868,6 @@ export class ConversationModel extends window.Backbone
return isMuted(this.get('muteExpiresAt'));
}
getMuteTimeoutId(): string {
return `mute(${this.get('id')})`;
}
async notify(
message: Readonly<MessageModel>,
reaction?: WhatIsThis

View file

@ -7,18 +7,17 @@ import {
} from '../state/ducks/network';
import { getSocketStatus } from '../shims/socketStatus';
import * as log from '../logging/log';
import { SECOND } from '../util/durations';
type NetworkActions = {
checkNetworkStatus: (x: CheckNetworkStatusPayloadType) => NetworkActionType;
closeConnectingGracePeriod: () => NetworkActionType;
};
const REFRESH_INTERVAL = 5000;
export function initializeNetworkObserver(
networkActions: NetworkActions
): void {
log.info(`Initializing network observer every ${REFRESH_INTERVAL}ms`);
log.info('Initializing network observer');
const refresh = () => {
networkActions.checkNetworkStatus({
@ -31,8 +30,7 @@ export function initializeNetworkObserver(
window.addEventListener('online', refresh);
window.addEventListener('offline', refresh);
window.setInterval(refresh, REFRESH_INTERVAL);
window.setTimeout(() => {
networkActions.closeConnectingGracePeriod();
}, REFRESH_INTERVAL);
}, 5 * SECOND);
}

View file

@ -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);
}
});
}

View file

@ -4,8 +4,8 @@
import { ThunkAction } from 'redux-thunk';
import * as updateIpc from '../../shims/updateIpc';
import { DialogType } from '../../types/Dialogs';
import { DAY } from '../../util/durations';
import { StateType as RootStateType } from '../reducer';
import { onTimeout } from '../../services/timers';
// State
@ -85,8 +85,6 @@ function showUpdateDialog(
};
}
const ONE_DAY = 24 * 60 * 60 * 1000;
function snoozeUpdate(): ThunkAction<
void,
RootStateType,
@ -95,12 +93,12 @@ function snoozeUpdate(): ThunkAction<
> {
return (dispatch, getState) => {
const { dialogType } = getState().updates;
onTimeout(Date.now() + ONE_DAY, () => {
setTimeout(() => {
dispatch({
type: UNSNOOZE_UPDATE,
payload: dialogType,
});
});
}, DAY);
dispatch({
type: SNOOZE_UPDATE,

View file

@ -1,7 +1,7 @@
// Copyright 2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import { onTimeout } from '../services/timers';
import { MINUTE } from './durations';
class PostLinkExperience {
private hasNotFinishedSync: boolean;
@ -15,9 +15,9 @@ class PostLinkExperience {
// timeout "post link" after 10 minutes in case the syncs don't complete
// in time or are never called.
onTimeout(Date.now() + 60 * 60 * 10 * 1000, () => {
setTimeout(() => {
this.stop();
});
}, 10 * MINUTE);
}
stop() {

2
ts/window.d.ts vendored
View file

@ -291,8 +291,6 @@ declare global {
initializeGroupCredentialFetcher: () => void;
initializeNetworkObserver: (network: ReduxActions['network']) => void;
initializeUpdateListener: (updates: ReduxActions['updates']) => void;
onTimeout: (timestamp: number, cb: () => void, id?: string) => string;
removeTimeout: (uuid: string) => void;
retryPlaceholders?: Util.RetryPlaceholders;
lightSessionResetQueue?: PQueue;
runStorageServiceSyncJob: () => Promise<void>;