-
-
Notifications
You must be signed in to change notification settings - Fork 170
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fix code highlighting and optimize category select
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.
- Loading branch information
1 parent
4531645
commit cb42f11
Showing
79 changed files
with
2,729 additions
and
1,347 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
import { PlatformTimer } from './PlatformTimer'; | ||
import { TimeoutType, Timer } from './Timer'; | ||
|
||
export function batchedDebounce<T>( | ||
callback: (batches: readonly T[]) => void, | ||
waitInMs: number, | ||
timer: Timer = PlatformTimer, | ||
): (arg: T) => void { | ||
let lastTimeoutId: TimeoutType | undefined; | ||
let batches: Array<T> = []; | ||
|
||
return (arg: T) => { | ||
batches.push(arg); | ||
|
||
const later = () => { | ||
callback(batches); | ||
batches = []; | ||
lastTimeoutId = undefined; | ||
}; | ||
|
||
if (lastTimeoutId !== undefined) { | ||
timer.clearTimeout(lastTimeoutId); | ||
} | ||
|
||
lastTimeoutId = timer.setTimeout(later, waitInMs); | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
import { Timer } from './Timer'; | ||
|
||
export const PlatformTimer: Timer = { | ||
setTimeout: (callback, ms) => setTimeout(callback, ms), | ||
clearTimeout: (timeoutId) => clearTimeout(timeoutId), | ||
dateNow: () => Date.now(), | ||
}; |
30 changes: 7 additions & 23 deletions
30
...resentation/components/Shared/Throttle.ts → src/application/Common/Timing/Throttle.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
// Allows aligning with both NodeJs (NodeJs.Timeout) and Window type (number) | ||
export type TimeoutType = ReturnType<typeof setTimeout>; | ||
|
||
export interface Timer { | ||
setTimeout: (callback: () => void, ms: number) => TimeoutType; | ||
clearTimeout: (timeoutId: TimeoutType) => void; | ||
dateNow(): number; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,7 @@ | ||
import { SelectedScript } from '@/application/Context/State/Selection/SelectedScript'; | ||
import { ICodePosition } from '@/application/Context/State/Code/Position/ICodePosition'; | ||
import { SelectedScript } from '@/application/Context/State/Selection/Script/SelectedScript'; | ||
|
||
export interface IUserScript { | ||
code: string; | ||
scriptPositions: Map<SelectedScript, ICodePosition>; | ||
readonly code: string; | ||
readonly scriptPositions: Map<SelectedScript, ICodePosition>; | ||
} |
5 changes: 3 additions & 2 deletions
5
src/application/Context/State/Code/Generation/IUserScriptGenerator.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,10 @@ | ||
import { SelectedScript } from '@/application/Context/State/Selection/SelectedScript'; | ||
import { IScriptingDefinition } from '@/domain/IScriptingDefinition'; | ||
import { SelectedScript } from '@/application/Context/State/Selection/Script/SelectedScript'; | ||
import { IUserScript } from './IUserScript'; | ||
|
||
export interface IUserScriptGenerator { | ||
buildCode( | ||
selectedScripts: ReadonlyArray<SelectedScript>, | ||
scriptingDefinition: IScriptingDefinition): IUserScript; | ||
scriptingDefinition: IScriptingDefinition, | ||
): IUserScript; | ||
} |
2 changes: 1 addition & 1 deletion
2
src/application/Context/State/Code/Generation/UserScriptGenerator.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,18 +1,18 @@ | ||
import { ICategoryCollection } from '@/domain/ICategoryCollection'; | ||
import { OperatingSystem } from '@/domain/OperatingSystem'; | ||
import { IReadOnlyUserFilter, IUserFilter } from './Filter/IUserFilter'; | ||
import { IReadOnlyUserSelection, IUserSelection } from './Selection/IUserSelection'; | ||
import { ReadonlyUserSelection, UserSelection } from './Selection/UserSelection'; | ||
import { IApplicationCode } from './Code/IApplicationCode'; | ||
|
||
export interface IReadOnlyCategoryCollectionState { | ||
readonly code: IApplicationCode; | ||
readonly os: OperatingSystem; | ||
readonly filter: IReadOnlyUserFilter; | ||
readonly selection: IReadOnlyUserSelection; | ||
readonly selection: ReadonlyUserSelection; | ||
readonly collection: ICategoryCollection; | ||
} | ||
|
||
export interface ICategoryCollectionState extends IReadOnlyCategoryCollectionState { | ||
readonly filter: IUserFilter; | ||
readonly selection: IUserSelection; | ||
readonly selection: UserSelection; | ||
} |
11 changes: 11 additions & 0 deletions
11
src/application/Context/State/Selection/Category/CategorySelection.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
import { ICategory } from '@/domain/ICategory'; | ||
import { CategorySelectionChangeCommand } from './CategorySelectionChange'; | ||
|
||
export interface ReadonlyCategorySelection { | ||
areAllScriptsSelected(category: ICategory): boolean; | ||
isAnyScriptSelected(category: ICategory): boolean; | ||
} | ||
|
||
export interface CategorySelection extends ReadonlyCategorySelection { | ||
processChanges(action: CategorySelectionChangeCommand): void; | ||
} |
15 changes: 15 additions & 0 deletions
15
src/application/Context/State/Selection/Category/CategorySelectionChange.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
type CategorySelectionStatus = { | ||
readonly isSelected: true; | ||
readonly isReverted: boolean; | ||
} | { | ||
readonly isSelected: false; | ||
}; | ||
|
||
export interface CategorySelectionChange { | ||
readonly categoryId: number; | ||
readonly newStatus: CategorySelectionStatus; | ||
} | ||
|
||
export interface CategorySelectionChangeCommand { | ||
readonly changes: readonly CategorySelectionChange[]; | ||
} |
60 changes: 60 additions & 0 deletions
60
src/application/Context/State/Selection/Category/ScriptToCategorySelectionMapper.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
import { ICategory } from '@/domain/ICategory'; | ||
import { ICategoryCollection } from '@/domain/ICategoryCollection'; | ||
import { ScriptSelection } from '../Script/ScriptSelection'; | ||
import { ScriptSelectionChange } from '../Script/ScriptSelectionChange'; | ||
import { CategorySelection } from './CategorySelection'; | ||
import { CategorySelectionChange, CategorySelectionChangeCommand } from './CategorySelectionChange'; | ||
|
||
export class ScriptToCategorySelectionMapper implements CategorySelection { | ||
constructor( | ||
private readonly scriptSelection: ScriptSelection, | ||
private readonly collection: ICategoryCollection, | ||
) { | ||
|
||
} | ||
|
||
public areAllScriptsSelected(category: ICategory): boolean { | ||
const { selectedScripts } = this.scriptSelection; | ||
if (selectedScripts.length === 0) { | ||
return false; | ||
} | ||
const scripts = category.getAllScriptsRecursively(); | ||
if (selectedScripts.length < scripts.length) { | ||
return false; | ||
} | ||
return scripts.every( | ||
(script) => selectedScripts.some((selected) => selected.id === script.id), | ||
); | ||
} | ||
|
||
public isAnyScriptSelected(category: ICategory): boolean { | ||
const { selectedScripts } = this.scriptSelection; | ||
if (selectedScripts.length === 0) { | ||
return false; | ||
} | ||
return selectedScripts.some((s) => category.includes(s.script)); | ||
} | ||
|
||
public processChanges(action: CategorySelectionChangeCommand): void { | ||
const scriptChanges = action.changes.reduce((changes, change) => { | ||
changes.push(...this.collectScriptChanges(change)); | ||
return changes; | ||
}, new Array<ScriptSelectionChange>()); | ||
this.scriptSelection.processChanges({ | ||
changes: scriptChanges, | ||
}); | ||
} | ||
|
||
private collectScriptChanges(change: CategorySelectionChange): ScriptSelectionChange[] { | ||
const category = this.collection.getCategory(change.categoryId); | ||
const scripts = category.getAllScriptsRecursively(); | ||
const scriptsChangesInCategory = scripts | ||
.map((script): ScriptSelectionChange => ({ | ||
scriptId: script.id, | ||
newStatus: { | ||
...change.newStatus, | ||
}, | ||
})); | ||
return scriptsChangesInCategory; | ||
} | ||
} |
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.