Switch to a reducer for tracking update state fixing flicker issues due to continuous renders (#10280)

This commit is contained in:
Jacob Richman
2025-10-01 14:53:15 -07:00
committed by GitHub
parent ef76a801c4
commit a404fb8d2e
13 changed files with 599 additions and 361 deletions

View File

@@ -4,6 +4,8 @@
* SPDX-License-Identifier: Apache-2.0
*/
import { checkExhaustive } from '../../utils/checks.js';
export enum ExtensionUpdateState {
CHECKING_FOR_UPDATES = 'checking for updates',
UPDATED_NEEDS_RESTART = 'updated, needs restart',
@@ -14,3 +16,74 @@ export enum ExtensionUpdateState {
NOT_UPDATABLE = 'not updatable',
UNKNOWN = 'unknown',
}
export interface ExtensionUpdateStatus {
status: ExtensionUpdateState;
processed: boolean;
}
export interface ExtensionUpdatesState {
extensionStatuses: Map<string, ExtensionUpdateStatus>;
batchChecksInProgress: number;
}
export const initialExtensionUpdatesState: ExtensionUpdatesState = {
extensionStatuses: new Map(),
batchChecksInProgress: 0,
};
export type ExtensionUpdateAction =
| {
type: 'SET_STATE';
payload: { name: string; state: ExtensionUpdateState };
}
| {
type: 'SET_PROCESSED';
payload: { name: string; processed: boolean };
}
| { type: 'BATCH_CHECK_START' }
| { type: 'BATCH_CHECK_END' };
export function extensionUpdatesReducer(
state: ExtensionUpdatesState,
action: ExtensionUpdateAction,
): ExtensionUpdatesState {
switch (action.type) {
case 'SET_STATE': {
const existing = state.extensionStatuses.get(action.payload.name);
if (existing?.status === action.payload.state) {
return state;
}
const newStatuses = new Map(state.extensionStatuses);
newStatuses.set(action.payload.name, {
status: action.payload.state,
processed: false,
});
return { ...state, extensionStatuses: newStatuses };
}
case 'SET_PROCESSED': {
const existing = state.extensionStatuses.get(action.payload.name);
if (!existing || existing.processed === action.payload.processed) {
return state;
}
const newStatuses = new Map(state.extensionStatuses);
newStatuses.set(action.payload.name, {
...existing,
processed: action.payload.processed,
});
return { ...state, extensionStatuses: newStatuses };
}
case 'BATCH_CHECK_START':
return {
...state,
batchChecksInProgress: state.batchChecksInProgress + 1,
};
case 'BATCH_CHECK_END':
return {
...state,
batchChecksInProgress: state.batchChecksInProgress - 1,
};
default:
checkExhaustive(action);
}
}