Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add cancel function when you select an option in search and navigate away from the optionList #42471

1 change: 1 addition & 0 deletions src/libs/API/parameters/SearchForReportsParams.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
type SearchForReportsParams = {
searchInput: string;
canCancel?: boolean;
};

export default SearchForReportsParams;
22 changes: 15 additions & 7 deletions src/libs/HttpUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import HttpsError from './Errors/HttpsError';
let shouldFailAllRequests = false;
let shouldForceOffline = false;

type AbortCommand = 'All' | 'SearchForReports';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you can infer this based on API commands (typeof consts) OR 'All'?


Onyx.connect({
key: ONYXKEYS.NETWORK,
callback: (network) => {
Expand All @@ -26,7 +28,9 @@ Onyx.connect({
});

// We use the AbortController API to terminate pending request in `cancelPendingRequests`
let cancellationController = new AbortController();
const abortControllerMap = new Map<AbortCommand, AbortController>();
abortControllerMap.set('All', new AbortController());
abortControllerMap.set('SearchForReports', new AbortController());

// Some existing old commands (6+ years) exempted from the auth writes count check
const exemptedCommandsWithAuthWrites: string[] = ['SetWorkspaceAutoReportingFrequency'];
Expand All @@ -45,11 +49,11 @@ const APICommandRegex = /\/api\/([^&?]+)\??.*/;
* Send an HTTP request, and attempt to resolve the json response.
* If there is a network error, we'll set the application offline.
*/
function processHTTPRequest(url: string, method: RequestType = 'get', body: FormData | null = null, canCancel = true): Promise<Response> {
function processHTTPRequest(url: string, method: RequestType = 'get', body: FormData | null = null, abortSignal: AbortSignal | undefined = undefined): Promise<Response> {
const startTime = new Date().valueOf();
return fetch(url, {
// We hook requests to the same Controller signal, so we can cancel them all at once
signal: canCancel ? cancellationController.signal : undefined,
signal: abortSignal,
method,
body,
})
Expand Down Expand Up @@ -159,15 +163,19 @@ function xhr(command: string, data: Record<string, unknown>, type: RequestType =
});

const url = ApiUtils.getCommandURL({shouldUseSecure, command});
return processHTTPRequest(url, type, formData, Boolean(data.canCancel));

const abortSignalController = data.canCancel ? abortControllerMap.get(command as AbortCommand) ?? abortControllerMap.get('All') : undefined;
return processHTTPRequest(url, type, formData, abortSignalController?.signal);
}

function cancelPendingRequests() {
cancellationController.abort();
function cancelPendingRequests(command: AbortCommand = 'All') {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably would be good to add a new const in I would use the READ_COMMANDS object

const controller = abortControllerMap.get(command) ?? abortControllerMap.get('All');

controller?.abort();

// We create a new instance because once `abort()` is called any future requests using the same controller would
// automatically get rejected: https://dom.spec.whatwg.org/#abortcontroller-api-integration
cancellationController = new AbortController();
abortControllerMap.set(command, new AbortController());
}

export default {
Expand Down
2 changes: 1 addition & 1 deletion src/libs/actions/Report.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3546,7 +3546,7 @@ function searchForReports(searchInput: string, policyID?: string) {
];

const searchForRoomToMentionParams: SearchForRoomsToMentionParams = {query: searchInput, policyID: policyID ?? ''};
const searchForReportsParams: SearchForReportsParams = {searchInput};
const searchForReportsParams: SearchForReportsParams = {searchInput, canCancel: true};

API.read(policyID ? READ_COMMANDS.SEARCH_FOR_ROOMS_TO_MENTION : READ_COMMANDS.SEARCH_FOR_REPORTS, policyID ? searchForRoomToMentionParams : searchForReportsParams, {
successData,
Expand Down
3 changes: 3 additions & 0 deletions src/pages/ChatFinderPage/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import useDebouncedState from '@hooks/useDebouncedState';
import useDismissedReferralBanners from '@hooks/useDismissedReferralBanners';
import useLocalize from '@hooks/useLocalize';
import useNetwork from '@hooks/useNetwork';
import HttpUtils from '@libs/HttpUtils';
import type {MaybePhraseKey} from '@libs/Localize';
import Navigation from '@libs/Navigation/Navigation';
import type {RootStackParamList} from '@libs/Navigation/types';
Expand Down Expand Up @@ -143,6 +144,8 @@ function ChatFinderPage({betas, isSearchingForReports, navigation}: ChatFinderPa
return;
}

HttpUtils.cancelPendingRequests('SearchForReports');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would use the READ_COMMANDS.SEARCH_FOR_REPORTS


if (option.reportID) {
setSearchValue('');
Navigation.dismissModal(option.reportID);
Expand Down
Loading