Introduce new TreeView UI component
Key highlights: - Written from scratch to cater specifically to privacy.sexy's needs and requirements. - The visual look mimics the previous component with minimal changes, but its internal code is completely rewritten. - Lays groundwork for future functionalities like the "expand all" button a flat view mode as discussed in #158. - Facilitates the transition to Vue 3 by omitting the Vue 2.0 dependent `liquour-tree` as part of #230. Improvements and features: - Caching for quicker node queries. - Gradual rendering of nodes that introduces a noticable boost in performance, particularly during search/filtering. - `TreeView` solely governs the check states of branch nodes. Changes: - Keyboard interactions now alter the background color to highlight the focused item. Previously, it was changing the color of the text. - Better state management with clear separation of concerns: - `TreeView` exclusively manages indeterminate states. - `TreeView` solely governs the check states of branch nodes. - Introduce transaction pattern to update state in batches to minimize amount of events handled. - Improve keyboard focus, style background instead of foreground. Use hover/touch color on keyboard focus. - `SelectableTree` has been removed. Instead, `TreeView` is now directly integrated with `ScriptsTree`. - `ScriptsTree` has been refactored to incorporate hooks for clearer code and separation of duties. - Adopt Vue-idiomatic bindings instead of keeping a reference of the tree component. - Simplify and change filter event management. - Abandon global styles in favor of class-scoped styles. - Use global mixins with descriptive names to clarify indended functionality.
This commit is contained in:
@@ -6,6 +6,7 @@ import { SelectedScript } from '@/application/Context/State/Selection/SelectedSc
|
||||
import { IScript } from '@/domain/IScript';
|
||||
import { ScriptStub } from '@tests/unit/shared/Stubs/ScriptStub';
|
||||
import { ICategoryCollection } from '@/domain/ICategoryCollection';
|
||||
import { IUserSelection } from '@/application/Context/State/Selection/IUserSelection';
|
||||
import { CategoryCollectionStub } from './CategoryCollectionStub';
|
||||
import { UserSelectionStub } from './UserSelectionStub';
|
||||
import { UserFilterStub } from './UserFilterStub';
|
||||
@@ -13,42 +14,53 @@ import { ApplicationCodeStub } from './ApplicationCodeStub';
|
||||
import { CategoryStub } from './CategoryStub';
|
||||
|
||||
export class CategoryCollectionStateStub implements ICategoryCollectionState {
|
||||
private collectionStub = new CategoryCollectionStub();
|
||||
|
||||
public readonly code: IApplicationCode = new ApplicationCodeStub();
|
||||
|
||||
public filter: IUserFilter = new UserFilterStub();
|
||||
|
||||
public get os(): OperatingSystem {
|
||||
return this.collectionStub.os;
|
||||
return this.collection.os;
|
||||
}
|
||||
|
||||
public get collection(): ICategoryCollection {
|
||||
return this.collectionStub;
|
||||
}
|
||||
public collection: ICategoryCollection = new CategoryCollectionStub();
|
||||
|
||||
public readonly selection: UserSelectionStub;
|
||||
public selection: IUserSelection = new UserSelectionStub([]);
|
||||
|
||||
constructor(readonly allScripts: IScript[] = [new ScriptStub('script-id')]) {
|
||||
this.selection = new UserSelectionStub(allScripts);
|
||||
this.collectionStub = new CategoryCollectionStub()
|
||||
this.collection = new CategoryCollectionStub()
|
||||
.withOs(this.os)
|
||||
.withTotalScripts(this.allScripts.length)
|
||||
.withAction(new CategoryStub(0).withScripts(...allScripts));
|
||||
}
|
||||
|
||||
public withOs(os: OperatingSystem) {
|
||||
this.collectionStub = this.collectionStub.withOs(os);
|
||||
public withCollection(collection: ICategoryCollection): this {
|
||||
this.collection = collection;
|
||||
return this;
|
||||
}
|
||||
|
||||
public withFilter(filter: IUserFilter) {
|
||||
public withOs(os: OperatingSystem): this {
|
||||
if (this.collection instanceof CategoryCollectionStub) {
|
||||
this.collection = this.collection.withOs(os);
|
||||
} else {
|
||||
this.collection = new CategoryCollectionStub().withOs(os);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public withFilter(filter: IUserFilter): this {
|
||||
this.filter = filter;
|
||||
return this;
|
||||
}
|
||||
|
||||
public withSelectedScripts(initialScripts: readonly SelectedScript[]) {
|
||||
this.selection.withSelectedScripts(initialScripts);
|
||||
public withSelectedScripts(initialScripts: readonly SelectedScript[]): this {
|
||||
return this.withSelection(
|
||||
new UserSelectionStub([]).withSelectedScripts(initialScripts),
|
||||
);
|
||||
}
|
||||
|
||||
public withSelection(selection: IUserSelection) {
|
||||
this.selection = selection;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user