From 17c2a738bd2ff3aa29a03059d3c55fa39f241224 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Ska=C5=82ka?= Date: Fri, 22 Sep 2023 15:51:28 +0200 Subject: [PATCH 1/6] migrate NetworkConnection to TypeScript --- ...workConnection.js => NetworkConnection.ts} | 41 ++++++++----------- src/libs/Throttle.ts | 12 ++++++ 2 files changed, 30 insertions(+), 23 deletions(-) rename src/libs/{NetworkConnection.js => NetworkConnection.ts} (85%) create mode 100644 src/libs/Throttle.ts diff --git a/src/libs/NetworkConnection.js b/src/libs/NetworkConnection.ts similarity index 85% rename from src/libs/NetworkConnection.js rename to src/libs/NetworkConnection.ts index 9ca09c9154bc..743b55674b8a 100644 --- a/src/libs/NetworkConnection.js +++ b/src/libs/NetworkConnection.ts @@ -1,4 +1,3 @@ -import _ from 'underscore'; import Onyx from 'react-native-onyx'; import NetInfo from '@react-native-community/netinfo'; import AppStateMonitor from './AppStateMonitor'; @@ -7,33 +6,31 @@ import * as NetworkActions from './actions/Network'; import CONFIG from '../CONFIG'; import CONST from '../CONST'; import ONYXKEYS from '../ONYXKEYS'; +import throttle from './Throttle'; let isOffline = false; let hasPendingNetworkCheck = false; // Holds all of the callbacks that need to be triggered when the network reconnects let callbackID = 0; -const reconnectionCallbacks = {}; +const reconnectionCallbacks: Record Promise> = {}; /** * Loop over all reconnection callbacks and fire each one */ -const triggerReconnectionCallbacks = _.throttle( - (reason) => { - Log.info(`[NetworkConnection] Firing reconnection callbacks because ${reason}`); - _.each(reconnectionCallbacks, (callback) => callback()); - }, - 5000, - {trailing: false}, -); +const triggerReconnectionCallbacks = throttle((reason) => { + alert('X'); + Log.info(`[NetworkConnection] Firing reconnection callbacks because ${reason?.toString()}`); + Object.values(reconnectionCallbacks).forEach((callback) => { + callback(); + }); +}, 5000); /** * Called when the offline status of the app changes and if the network is "reconnecting" (going from offline to online) * then all of the reconnection callbacks are triggered - * - * @param {Boolean} isCurrentlyOffline */ -function setOfflineStatus(isCurrentlyOffline) { +function setOfflineStatus(isCurrentlyOffline: boolean): void { NetworkActions.setIsOffline(isCurrentlyOffline); // When reconnecting, ie, going from offline to online, all the reconnection callbacks @@ -72,7 +69,7 @@ Onyx.connect({ * internet connectivity or not. This is more reliable than the Pusher * `disconnected` event which takes about 10-15 seconds to emit. */ -function subscribeToNetInfo() { +function subscribeToNetInfo(): void { // Note: We are disabling the configuration for NetInfo when using the local web API since requests can get stuck in a 'Pending' state and are not reliable indicators for "offline". // If you need to test the "recheck" feature then switch to the production API proxy server. if (!CONFIG.IS_USING_LOCAL_WEB) { @@ -101,7 +98,7 @@ function subscribeToNetInfo() { // Subscribe to the state change event via NetInfo so we can update // whether a user has internet connectivity or not. NetInfo.addEventListener((state) => { - Log.info('[NetworkConnection] NetInfo state change', false, state); + Log.info('[NetworkConnection] NetInfo state change', false, {...state}); if (shouldForceOffline) { Log.info('[NetworkConnection] Not setting offline status because shouldForceOffline = true'); return; @@ -110,7 +107,7 @@ function subscribeToNetInfo() { }); } -function listenForReconnect() { +function listenForReconnect(): void { Log.info('[NetworkConnection] listenForReconnect called'); AppStateMonitor.addBecameActiveListener(() => { @@ -120,11 +117,9 @@ function listenForReconnect() { /** * Register callback to fire when we reconnect - * - * @param {Function} callback - must return a Promise - * @returns {Function} unsubscribe method + * @returns unsubscribe method */ -function onReconnect(callback) { +function onReconnect(callback: () => Promise): () => void { const currentID = callbackID; callbackID++; reconnectionCallbacks[currentID] = callback; @@ -134,14 +129,14 @@ function onReconnect(callback) { /** * Delete all queued reconnection callbacks */ -function clearReconnectionCallbacks() { - _.each(_.keys(reconnectionCallbacks), (key) => delete reconnectionCallbacks[key]); +function clearReconnectionCallbacks(): void { + Object.keys(reconnectionCallbacks).forEach((key) => delete reconnectionCallbacks[key]); } /** * Refresh NetInfo state. */ -function recheckNetworkConnection() { +function recheckNetworkConnection(): void { if (hasPendingNetworkCheck) { return; } diff --git a/src/libs/Throttle.ts b/src/libs/Throttle.ts new file mode 100644 index 000000000000..1a271b479d62 --- /dev/null +++ b/src/libs/Throttle.ts @@ -0,0 +1,12 @@ +function throttle(func: (...args: unknown[]) => void, timeFrame: number): (...args: unknown[]) => void { + let lastTime = 0; + return function (...args) { + const now = new Date().getTime(); + if (now - lastTime >= timeFrame) { + func(...args); + lastTime = now; + } + }; +} + +export default throttle; From 19c4b5e6713da2adb8b6f6b400b001a3d88b6a78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Ska=C5=82ka?= Date: Fri, 22 Sep 2023 16:03:08 +0200 Subject: [PATCH 2/6] remove alert --- src/libs/NetworkConnection.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/libs/NetworkConnection.ts b/src/libs/NetworkConnection.ts index 743b55674b8a..dea438dea7d0 100644 --- a/src/libs/NetworkConnection.ts +++ b/src/libs/NetworkConnection.ts @@ -19,7 +19,6 @@ const reconnectionCallbacks: Record Promise> = {}; * Loop over all reconnection callbacks and fire each one */ const triggerReconnectionCallbacks = throttle((reason) => { - alert('X'); Log.info(`[NetworkConnection] Firing reconnection callbacks because ${reason?.toString()}`); Object.values(reconnectionCallbacks).forEach((callback) => { callback(); From ddee576cd82f59be95346e5c22138aa2b54b213c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Ska=C5=82ka?= Date: Mon, 2 Oct 2023 17:46:06 +0200 Subject: [PATCH 3/6] add properly typed throttle function --- src/libs/NetworkConnection.ts | 3 ++- src/libs/Throttle.ts | 40 ++++++++++++++++++++++++++--------- 2 files changed, 32 insertions(+), 11 deletions(-) diff --git a/src/libs/NetworkConnection.ts b/src/libs/NetworkConnection.ts index dea438dea7d0..2ba9f9dd1604 100644 --- a/src/libs/NetworkConnection.ts +++ b/src/libs/NetworkConnection.ts @@ -18,7 +18,8 @@ const reconnectionCallbacks: Record Promise> = {}; /** * Loop over all reconnection callbacks and fire each one */ -const triggerReconnectionCallbacks = throttle((reason) => { +const [triggerReconnectionCallbacks] = throttle((reason: string) => { + alert(reason); Log.info(`[NetworkConnection] Firing reconnection callbacks because ${reason?.toString()}`); Object.values(reconnectionCallbacks).forEach((callback) => { callback(); diff --git a/src/libs/Throttle.ts b/src/libs/Throttle.ts index 1a271b479d62..f5e685f9bb64 100644 --- a/src/libs/Throttle.ts +++ b/src/libs/Throttle.ts @@ -1,12 +1,32 @@ -function throttle(func: (...args: unknown[]) => void, timeFrame: number): (...args: unknown[]) => void { - let lastTime = 0; - return function (...args) { - const now = new Date().getTime(); - if (now - lastTime >= timeFrame) { - func(...args); - lastTime = now; - } - }; -} +const throttle = (fn: (...args: A) => R, delay: number): [(...args: A) => R | undefined, () => void] => { + let wait = false; + let timeout: undefined | number; + let cancelled = false; + + return [ + (...args: A) => { + if (cancelled) { + return undefined; + } + if (wait) { + return undefined; + } + + const val = fn(...args); + + wait = true; + + timeout = window.setTimeout(() => { + wait = false; + }, delay); + + return val; + }, + () => { + cancelled = true; + clearTimeout(timeout); + }, + ]; +}; export default throttle; From acdbbd9c1dacbb6c5897d253ab97a83edfa29975 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Ska=C5=82ka?= Date: Mon, 2 Oct 2023 17:53:35 +0200 Subject: [PATCH 4/6] remove test code --- src/libs/NetworkConnection.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/libs/NetworkConnection.ts b/src/libs/NetworkConnection.ts index 2ba9f9dd1604..46067b29d4f7 100644 --- a/src/libs/NetworkConnection.ts +++ b/src/libs/NetworkConnection.ts @@ -19,7 +19,6 @@ const reconnectionCallbacks: Record Promise> = {}; * Loop over all reconnection callbacks and fire each one */ const [triggerReconnectionCallbacks] = throttle((reason: string) => { - alert(reason); Log.info(`[NetworkConnection] Firing reconnection callbacks because ${reason?.toString()}`); Object.values(reconnectionCallbacks).forEach((callback) => { callback(); From 485b9c638df1113fbbd999bc932beab061e8691a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Ska=C5=82ka?= Date: Wed, 4 Oct 2023 09:49:14 +0200 Subject: [PATCH 5/6] review changes --- src/libs/NetworkConnection.ts | 24 ++++++++++++++---------- src/libs/Throttle.ts | 32 -------------------------------- 2 files changed, 14 insertions(+), 42 deletions(-) delete mode 100644 src/libs/Throttle.ts diff --git a/src/libs/NetworkConnection.ts b/src/libs/NetworkConnection.ts index 46067b29d4f7..160a3aa3dee1 100644 --- a/src/libs/NetworkConnection.ts +++ b/src/libs/NetworkConnection.ts @@ -2,11 +2,11 @@ import Onyx from 'react-native-onyx'; import NetInfo from '@react-native-community/netinfo'; import AppStateMonitor from './AppStateMonitor'; import Log from './Log'; +import throttle from 'lodash/throttle'; import * as NetworkActions from './actions/Network'; import CONFIG from '../CONFIG'; import CONST from '../CONST'; import ONYXKEYS from '../ONYXKEYS'; -import throttle from './Throttle'; let isOffline = false; let hasPendingNetworkCheck = false; @@ -18,12 +18,16 @@ const reconnectionCallbacks: Record Promise> = {}; /** * Loop over all reconnection callbacks and fire each one */ -const [triggerReconnectionCallbacks] = throttle((reason: string) => { - Log.info(`[NetworkConnection] Firing reconnection callbacks because ${reason?.toString()}`); - Object.values(reconnectionCallbacks).forEach((callback) => { - callback(); - }); -}, 5000); +const triggerReconnectionCallbacks = throttle( + (reason) => { + Log.info(`[NetworkConnection] Firing reconnection callbacks because ${reason}`); + Object.values(reconnectionCallbacks).forEach((callback) => { + callback(); + }); + }, + 5000, + {trailing: false}, +); /** * Called when the offline status of the app changes and if the network is "reconnecting" (going from offline to online) @@ -106,7 +110,7 @@ function subscribeToNetInfo(): void { }); } -function listenForReconnect(): void { +function listenForReconnect() { Log.info('[NetworkConnection] listenForReconnect called'); AppStateMonitor.addBecameActiveListener(() => { @@ -128,14 +132,14 @@ function onReconnect(callback: () => Promise): () => void { /** * Delete all queued reconnection callbacks */ -function clearReconnectionCallbacks(): void { +function clearReconnectionCallbacks() { Object.keys(reconnectionCallbacks).forEach((key) => delete reconnectionCallbacks[key]); } /** * Refresh NetInfo state. */ -function recheckNetworkConnection(): void { +function recheckNetworkConnection() { if (hasPendingNetworkCheck) { return; } diff --git a/src/libs/Throttle.ts b/src/libs/Throttle.ts deleted file mode 100644 index f5e685f9bb64..000000000000 --- a/src/libs/Throttle.ts +++ /dev/null @@ -1,32 +0,0 @@ -const throttle = (fn: (...args: A) => R, delay: number): [(...args: A) => R | undefined, () => void] => { - let wait = false; - let timeout: undefined | number; - let cancelled = false; - - return [ - (...args: A) => { - if (cancelled) { - return undefined; - } - if (wait) { - return undefined; - } - - const val = fn(...args); - - wait = true; - - timeout = window.setTimeout(() => { - wait = false; - }, delay); - - return val; - }, - () => { - cancelled = true; - clearTimeout(timeout); - }, - ]; -}; - -export default throttle; From d899d973dbe3a4d62080fb60b584241030aa73ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Ska=C5=82ka?= Date: Wed, 4 Oct 2023 11:29:37 +0200 Subject: [PATCH 6/6] fix eslint error --- src/libs/NetworkConnection.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/NetworkConnection.ts b/src/libs/NetworkConnection.ts index 160a3aa3dee1..663a9c1b37d5 100644 --- a/src/libs/NetworkConnection.ts +++ b/src/libs/NetworkConnection.ts @@ -1,8 +1,8 @@ import Onyx from 'react-native-onyx'; import NetInfo from '@react-native-community/netinfo'; +import throttle from 'lodash/throttle'; import AppStateMonitor from './AppStateMonitor'; import Log from './Log'; -import throttle from 'lodash/throttle'; import * as NetworkActions from './actions/Network'; import CONFIG from '../CONFIG'; import CONST from '../CONST';