Skip to content

Commit

Permalink
perf: reduce report connection
Browse files Browse the repository at this point in the history
  • Loading branch information
hurali97 committed Jan 30, 2024
1 parent 467e884 commit b58de10
Show file tree
Hide file tree
Showing 11 changed files with 142 additions and 86 deletions.
11 changes: 4 additions & 7 deletions src/libs/BrickRoadsUtils.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,18 @@
import type {OnyxCollection} from 'react-native-onyx';
import Onyx from 'react-native-onyx';
import type {ValueOf} from 'type-fest';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import type {Report} from '@src/types/onyx';
import * as OptionsListUtils from './OptionsListUtils';
import * as ReportActionsUtils from './ReportActionsUtils';
import * as ReportUtils from './ReportUtils';
import ReportCollectionObserver from './ReportCollectionObserver';

let allReports: OnyxCollection<Report>;
let allReports: OnyxCollection<Report> = {};

type BrickRoad = ValueOf<typeof CONST.BRICK_ROAD> | undefined;

Onyx.connect({
key: ONYXKEYS.COLLECTION.REPORT,
waitForCollectionCallback: true,
callback: (value) => (allReports = value),
ReportCollectionObserver.getInstance(true).addListener((value) => {
allReports = value as OnyxCollection<Report>;
});

/**
Expand Down
14 changes: 6 additions & 8 deletions src/libs/OptionsListUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import * as ReportUtils from './ReportUtils';
import * as TaskUtils from './TaskUtils';
import * as TransactionUtils from './TransactionUtils';
import * as UserUtils from './UserUtils';
import ReportCollectionObserver from './ReportCollectionObserver';

/**
* OptionsListUtils is used to build a list options passed to the OptionsList component. Several different UI views can
Expand Down Expand Up @@ -100,14 +101,11 @@ Onyx.connect({
});

const policyExpenseReports = {};
Onyx.connect({
key: ONYXKEYS.COLLECTION.REPORT,
callback: (report, key) => {
if (!ReportUtils.isPolicyExpenseChat(report)) {
return;
}
policyExpenseReports[key] = report;
},
ReportCollectionObserver.getInstance().addListener((report, key) => {
if (!ReportUtils.isPolicyExpenseChat(report)) {
return;
}
policyExpenseReports[key] = report;
});

let allTransactions = {};
Expand Down
18 changes: 8 additions & 10 deletions src/libs/ReportActionsUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import * as Localize from './Localize';
import Log from './Log';
import type {MessageElementBase, MessageTextElement} from './MessageElement';
import * as PersonalDetailsUtils from './PersonalDetailsUtils';
import ReportCollectionObserver from './ReportCollectionObserver';

type LastVisibleMessage = {
lastMessageTranslationKey?: string;
Expand All @@ -39,17 +40,14 @@ type MemberChangeMessageRoomReferenceElement = {

type MemberChangeMessageElement = MessageTextElement | MemberChangeMessageUserMentionElement | MemberChangeMessageRoomReferenceElement;

const allReports: OnyxCollection<Report> = {};
Onyx.connect({
key: ONYXKEYS.COLLECTION.REPORT,
callback: (report, key) => {
if (!key || !report) {
return;
}
let allReports: OnyxCollection<Report> = {};
ReportCollectionObserver.getInstance().addListener((report, key) => {
if (!key || !report) {
return;
}

const reportID = CollectionUtils.extractCollectionItemID(key);
allReports[reportID] = report;
},
const reportID = CollectionUtils.extractCollectionItemID(key);
allReports[reportID] = report;
});

const allReportActions: OnyxCollection<ReportActions> = {};
Expand Down
79 changes: 79 additions & 0 deletions src/libs/ReportCollectionObserver.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import ONYXKEYS from "@src/ONYXKEYS";
import { NativeEventEmitter, NativeModule } from "react-native";
import Onyx from "react-native-onyx";

const nativeModuleTemplate: NativeModule = {
addListener: () => {},
removeListeners: () => {},
};

const eventTypeWait = 'observe_report_wait_';
const eventTypeWithoutWait = 'observe_report_';

class BaseClass {
/**
* @property eventHandler - the NativeEventEmitter instance
*/
protected eventHandler: NativeEventEmitter;
protected constructor() {
this.eventHandler = new NativeEventEmitter(nativeModuleTemplate);
}
}

class ReportCollectionObserverWithWait extends BaseClass {
private static instance: ReportCollectionObserverWithWait;
protected constructor() {
super();
ReportCollectionObserverWithWait.instance = this;
Onyx.connect({
key: ONYXKEYS.COLLECTION.REPORT,
waitForCollectionCallback: true,
callback: (value) => {
this.eventHandler.emit(eventTypeWait, value);
},
});
}

public static getInstance(): ReportCollectionObserverWithWait {
// Ensure singleton instance
return ReportCollectionObserverWithWait.instance ?? new ReportCollectionObserverWithWait();
}

addListener(listener: (event: unknown) => void, context?: unknown) {
this.eventHandler.addListener(eventTypeWait, listener, Object(context));
}
}

class ReportCollectionObserverWithOutWait extends BaseClass {
private static instance: ReportCollectionObserverWithOutWait;
protected constructor() {
super();
ReportCollectionObserverWithOutWait.instance = this;
Onyx.connect({
key: ONYXKEYS.COLLECTION.REPORT,
callback: (value, key) => {
this.eventHandler.emit(eventTypeWithoutWait, value, key);
},
});
}

public static getInstance(): ReportCollectionObserverWithOutWait {
// Ensure singleton instance
return ReportCollectionObserverWithOutWait.instance ?? new ReportCollectionObserverWithOutWait();
}

addListener(listener: (event: unknown) => void, context?: unknown) {
this.eventHandler.addListener(eventTypeWithoutWait, listener, Object(context));
}
}

class ReportCollectionObserver {
public static getInstance(waitForCollectionCallback?: boolean): ReportCollectionObserverWithWait | ReportCollectionObserverWithOutWait {
if (waitForCollectionCallback) {
return ReportCollectionObserverWithWait.getInstance();
}
return ReportCollectionObserverWithOutWait.getInstance();
}
}

export default ReportCollectionObserver;
7 changes: 3 additions & 4 deletions src/libs/ReportUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ import type {LastVisibleMessage} from './ReportActionsUtils';
import * as TransactionUtils from './TransactionUtils';
import * as Url from './Url';
import * as UserUtils from './UserUtils';
import ReportCollectionObserver from './ReportCollectionObserver';

type WelcomeMessage = {showReportName: boolean; phrase1?: string; phrase2?: string};

Expand Down Expand Up @@ -395,10 +396,8 @@ Onyx.connect({
});

let allReports: OnyxCollection<Report>;
Onyx.connect({
key: ONYXKEYS.COLLECTION.REPORT,
waitForCollectionCallback: true,
callback: (value) => (allReports = value),
ReportCollectionObserver.getInstance(true).addListener((value) => {
allReports = value as OnyxCollection<Report>;
});

let doesDomainHaveApprovedAccountant = false;
Expand Down
19 changes: 8 additions & 11 deletions src/libs/TaskUtils.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,19 @@
import type {OnyxEntry} from 'react-native-onyx';
import Onyx from 'react-native-onyx';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import type {Report} from '@src/types/onyx';
import type ReportAction from '@src/types/onyx/ReportAction';
import * as CollectionUtils from './CollectionUtils';
import * as Localize from './Localize';
import ReportCollectionObserver from './ReportCollectionObserver';

const allReports: Record<string, Report> = {};
Onyx.connect({
key: ONYXKEYS.COLLECTION.REPORT,
callback: (report, key) => {
if (!key || !report) {
return;
}
const reportID = CollectionUtils.extractCollectionItemID(key);
allReports[reportID] = report;
},
let allReports: Record<string, Report> = {};
ReportCollectionObserver.getInstance().addListener((report, key) => {
if (!key || !report) {
return;
}
const reportID = CollectionUtils.extractCollectionItemID(key);
allReports[reportID] = report;
});

/**
Expand Down
9 changes: 4 additions & 5 deletions src/libs/TransactionUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import type {EmptyObject} from '@src/types/utils/EmptyObject';
import {isCorporateCard, isExpensifyCard} from './CardUtils';
import DateUtils from './DateUtils';
import * as NumberUtils from './NumberUtils';
import ReportCollectionObserver from './ReportCollectionObserver';

type AdditionalTransactionChanges = {comment?: string; waypoints?: WaypointCollection};

Expand All @@ -30,11 +31,9 @@ Onyx.connect({
},
});

let allReports: OnyxCollection<Report>;
Onyx.connect({
key: ONYXKEYS.COLLECTION.REPORT,
waitForCollectionCallback: true,
callback: (value) => (allReports = value),
let allReports: OnyxCollection<Report> = {};
ReportCollectionObserver.getInstance(true).addListener((value) => {
allReports = value as OnyxCollection<Report>;
});

function isDistanceRequest(transaction: Transaction): boolean {
Expand Down
13 changes: 4 additions & 9 deletions src/libs/UnreadIndicatorUpdater/index.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import type {OnyxCollection} from 'react-native-onyx';
import Onyx from 'react-native-onyx';
import * as ReportUtils from '@libs/ReportUtils';
import Navigation, {navigationRef} from '@navigation/Navigation';
import ONYXKEYS from '@src/ONYXKEYS';
import type {Report} from '@src/types/onyx';
import updateUnread from './updateUnread';
import ReportCollectionObserver from '@libs/ReportCollectionObserver';

let allReports: OnyxCollection<Report> = {};

Expand All @@ -18,13 +17,9 @@ const triggerUnreadUpdate = () => {
updateUnread(unreadReports.length);
};

Onyx.connect({
key: ONYXKEYS.COLLECTION.REPORT,
waitForCollectionCallback: true,
callback: (reportsFromOnyx) => {
allReports = reportsFromOnyx;
triggerUnreadUpdate();
},
ReportCollectionObserver.getInstance(true).addListener((reportsFromOnyx) => {
allReports = reportsFromOnyx as OnyxCollection<Report>;
triggerUnreadUpdate();
});

navigationRef.addListener('state', () => {
Expand Down
9 changes: 4 additions & 5 deletions src/libs/actions/IOU.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import ViolationsUtils from '@libs/ViolationsUtils';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
import ReportCollectionObserver from '@libs/ReportCollectionObserver';
import * as Policy from './Policy';
import * as Report from './Report';

Expand All @@ -43,11 +44,9 @@ Onyx.connect({
},
});

let allReports;
Onyx.connect({
key: ONYXKEYS.COLLECTION.REPORT,
waitForCollectionCallback: true,
callback: (val) => (allReports = val),
let allReports = {};
ReportCollectionObserver.getInstance(true).addListener((value) => {
allReports = value;
});

let allTransactions;
Expand Down
28 changes: 13 additions & 15 deletions src/libs/actions/PriorityMode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import Log from '@libs/Log';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import type {Report} from '@src/types/onyx';
import ReportCollectionObserver from '@libs/ReportCollectionObserver';

/**
* This actions file is used to automatically switch a user into #focus mode when they exceed a certain number of reports. We do this primarily for performance reasons.
Expand Down Expand Up @@ -35,25 +36,22 @@ Onyx.connect({
// eslint-disable-next-line @typescript-eslint/no-use-before-define
const autoSwitchToFocusMode = debounce(tryFocusModeUpdate, 300, {leading: true});

let allReports: OnyxCollection<Report> | undefined;
Onyx.connect({
key: ONYXKEYS.COLLECTION.REPORT,
callback: (report, key) => {
if (!key || !report) {
return;
}
let allReports: OnyxCollection<Report> | undefined = {};
ReportCollectionObserver.getInstance().addListener((report, key) => {
if (!key || !report) {
return;
}

if (!allReports) {
allReports = {};
}
if (!allReports) {
allReports = {};
}

const reportID = CollectionUtils.extractCollectionItemID(key);
const reportID = CollectionUtils.extractCollectionItemID(key);

allReports[reportID] = report;
allReports[reportID] = report;

// Each time a new report is added we will check to see if the user should be switched
autoSwitchToFocusMode();
},
// Each time a new report is added we will check to see if the user should be switched
autoSwitchToFocusMode();
});

let isLoadingReportData = true;
Expand Down
21 changes: 9 additions & 12 deletions src/libs/actions/Report.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ import type {EmptyObject} from '@src/types/utils/EmptyObject';
import {isEmptyObject, isNotEmptyObject} from '@src/types/utils/EmptyObject';
import * as Session from './Session';
import * as Welcome from './Welcome';
import ReportCollectionObserver from '@libs/ReportCollectionObserver';

type SubscriberCallback = (isFromCurrentUser: boolean, reportActionID: string | undefined) => void;

Expand Down Expand Up @@ -83,15 +84,12 @@ Onyx.connect({
});

const currentReportData: OnyxCollection<Report> = {};
Onyx.connect({
key: ONYXKEYS.COLLECTION.REPORT,
callback: (report, key) => {
if (!key || !report) {
return;
}
const reportID = CollectionUtils.extractCollectionItemID(key);
currentReportData[reportID] = report;
},
ReportCollectionObserver.getInstance().addListener((report, key) => {
if (!key || !report) {
return;
}
const reportID = CollectionUtils.extractCollectionItemID(key);
currentReportData[reportID] = report;
});

let isNetworkOffline = false;
Expand Down Expand Up @@ -1088,9 +1086,8 @@ function handleReportChanged(report: OnyxEntry<Report>) {
}
}

Onyx.connect({
key: ONYXKEYS.COLLECTION.REPORT,
callback: handleReportChanged,
ReportCollectionObserver.getInstance().addListener((value) => {
handleReportChanged(value);
});

/** Deletes a comment from the report, basically sets it as empty string */
Expand Down

0 comments on commit b58de10

Please sign in to comment.