This commit introduces a batched debounce mechanism for managing user
selection state changes. It effectively reduces unnecessary processing
during rapid script checking, preventing multiple triggers for code
compilation and UI rendering.
Key improvements include:
- Enhanced performance, especially noticeable when selecting large
categories. This update resolves minor UI freezes experienced when
selecting categories with numerous scripts.
- Correction of a bug where the code area only highlighted the last
selected script when multiple scripts were chosen.
Other changes include:
- Timing functions:
- Create a `Timing` folder for `throttle` and the new
`batchedDebounce` functions.
- Move these functions to the application layer from the presentation
layer, reflecting their application-wide use.
- Refactor existing code for improved clarity, naming consistency, and
adherence to new naming conventions.
- Add missing unit tests.
- `UserSelection`:
- State modifications in `UserSelection` now utilize a singular object
inspired by the CQRS pattern, enabling batch updates and flexible
change configurations, thereby simplifying change management.
- Remove the `I` prefix from related interfaces to align with new coding
standards.
- Refactor related code for better testability in isolation with
dependency injection.
- Repository:
- Move repository abstractions to the application layer.
- Improve repository abstraction to combine `ReadonlyRepository` and
`MutableRepository` interfaces.
- E2E testing:
- Introduce E2E tests to validate the correct batch selection
behavior.
- Add a specialized data attribute in `TheCodeArea.vue` for improved
testability.
- Reorganize shared Cypress functions for a more idiomatic Cypress
approach.
- Improve test documentation with related information.
- `SelectedScript`:
- Create an abstraction for simplified testability.
- Introduce `SelectedScriptStub` in tests as a substitute for the
actual object.
52 lines
1.8 KiB
TypeScript
52 lines
1.8 KiB
TypeScript
import { ICategoryCollection } from '@/domain/ICategoryCollection';
|
|
import { OperatingSystem } from '@/domain/OperatingSystem';
|
|
import { UserFilter } from './Filter/UserFilter';
|
|
import { IUserFilter } from './Filter/IUserFilter';
|
|
import { ApplicationCode } from './Code/ApplicationCode';
|
|
import { UserSelection } from './Selection/UserSelection';
|
|
import { ICategoryCollectionState } from './ICategoryCollectionState';
|
|
import { IApplicationCode } from './Code/IApplicationCode';
|
|
import { UserSelectionFacade } from './Selection/UserSelectionFacade';
|
|
|
|
export class CategoryCollectionState implements ICategoryCollectionState {
|
|
public readonly os: OperatingSystem;
|
|
|
|
public readonly code: IApplicationCode;
|
|
|
|
public readonly selection: UserSelection;
|
|
|
|
public readonly filter: IUserFilter;
|
|
|
|
public constructor(
|
|
public readonly collection: ICategoryCollection,
|
|
selectionFactory = DefaultSelectionFactory,
|
|
codeFactory = DefaultCodeFactory,
|
|
filterFactory = DefaultFilterFactory,
|
|
) {
|
|
this.selection = selectionFactory(collection, []);
|
|
this.code = codeFactory(this.selection.scripts, collection.scripting);
|
|
this.filter = filterFactory(collection);
|
|
this.os = collection.os;
|
|
}
|
|
}
|
|
|
|
export type CodeFactory = (
|
|
...params: ConstructorParameters<typeof ApplicationCode>
|
|
) => IApplicationCode;
|
|
|
|
const DefaultCodeFactory: CodeFactory = (...params) => new ApplicationCode(...params);
|
|
|
|
export type SelectionFactory = (
|
|
...params: ConstructorParameters<typeof UserSelectionFacade>
|
|
) => UserSelection;
|
|
|
|
const DefaultSelectionFactory: SelectionFactory = (
|
|
...params
|
|
) => new UserSelectionFacade(...params);
|
|
|
|
export type FilterFactory = (
|
|
...params: ConstructorParameters<typeof UserFilter>
|
|
) => IUserFilter;
|
|
|
|
const DefaultFilterFactory: FilterFactory = (...params) => new UserFilter(...params);
|