Skip to content

Commit

Permalink
refactor event handling to consume base class for lifecycling
Browse files Browse the repository at this point in the history
  • Loading branch information
undergroundwires committed Feb 4, 2021
1 parent 34b8822 commit f1e21ba
Show file tree
Hide file tree
Showing 23 changed files with 172 additions and 196 deletions.
4 changes: 2 additions & 2 deletions src/application/Context/ApplicationContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ import { CategoryCollectionState } from './State/CategoryCollectionState';
import { IApplication } from '@/domain/IApplication';
import { OperatingSystem } from '@/domain/OperatingSystem';
import { ICategoryCollection } from '@/domain/ICategoryCollection';
import { Signal } from '@/infrastructure/Events/Signal';
import { EventSource } from '@/infrastructure/Events/EventSource';

type StateMachine = Map<OperatingSystem, ICategoryCollectionState>;

export class ApplicationContext implements IApplicationContext {
public readonly contextChanged = new Signal<IApplicationContextChangedEvent>();
public readonly contextChanged = new EventSource<IApplicationContextChangedEvent>();
public collection: ICategoryCollection;
public currentOs: OperatingSystem;

Expand Down
4 changes: 2 additions & 2 deletions src/application/Context/IApplicationContext.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { ICategoryCollectionState } from './State/ICategoryCollectionState';
import { OperatingSystem } from '@/domain/OperatingSystem';
import { ISignal } from '@/infrastructure/Events/ISignal';
import { IEventSource } from '@/infrastructure/Events/IEventSource';
import { IApplication } from '@/domain/IApplication';

export interface IApplicationContext {
readonly app: IApplication;
readonly state: ICategoryCollectionState;
readonly contextChanged: ISignal<IApplicationContextChangedEvent>;
readonly contextChanged: IEventSource<IApplicationContextChangedEvent>;
changeContext(os: OperatingSystem): void;
}

Expand Down
4 changes: 2 additions & 2 deletions src/application/Context/State/Code/ApplicationCode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ import { ICodeChangedEvent } from './Event/ICodeChangedEvent';
import { SelectedScript } from '@/application/Context/State/Selection/SelectedScript';
import { IUserSelection } from '@/application/Context/State/Selection/IUserSelection';
import { UserScriptGenerator } from './Generation/UserScriptGenerator';
import { Signal } from '@/infrastructure/Events/Signal';
import { EventSource } from '@/infrastructure/Events/EventSource';
import { IApplicationCode } from './IApplicationCode';
import { IUserScriptGenerator } from './Generation/IUserScriptGenerator';
import { IScriptingDefinition } from '@/domain/IScriptingDefinition';

export class ApplicationCode implements IApplicationCode {
public readonly changed = new Signal<ICodeChangedEvent>();
public readonly changed = new EventSource<ICodeChangedEvent>();
public current: string;

private scriptPositions = new Map<SelectedScript, CodePosition>();
Expand Down
4 changes: 2 additions & 2 deletions src/application/Context/State/Code/IApplicationCode.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { ICodeChangedEvent } from './Event/ICodeChangedEvent';
import { ISignal } from '@/infrastructure/Events/ISignal';
import { IEventSource } from '@/infrastructure/Events/IEventSource';

export interface IApplicationCode {
readonly changed: ISignal<ICodeChangedEvent>;
readonly changed: IEventSource<ICodeChangedEvent>;
readonly current: string;
}
6 changes: 3 additions & 3 deletions src/application/Context/State/Filter/IUserFilter.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { ISignal } from '@/infrastructure/Events/ISignal';
import { IEventSource } from '@/infrastructure/Events/IEventSource';
import { IFilterResult } from './IFilterResult';

export interface IUserFilter {
readonly currentFilter: IFilterResult | undefined;
readonly filtered: ISignal<IFilterResult>;
readonly filterRemoved: ISignal<void>;
readonly filtered: IEventSource<IFilterResult>;
readonly filterRemoved: IEventSource<void>;
setFilter(filter: string): void;
removeFilter(): void;
}
6 changes: 3 additions & 3 deletions src/application/Context/State/Filter/UserFilter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ import { IScript } from '@/domain/IScript';
import { FilterResult } from './FilterResult';
import { IFilterResult } from './IFilterResult';
import { IUserFilter } from './IUserFilter';
import { Signal } from '@/infrastructure/Events/Signal';
import { EventSource } from '@/infrastructure/Events/EventSource';
import { ICategoryCollection } from '@/domain/ICategoryCollection';

export class UserFilter implements IUserFilter {
public readonly filtered = new Signal<IFilterResult>();
public readonly filterRemoved = new Signal<void>();
public readonly filtered = new EventSource<IFilterResult>();
public readonly filterRemoved = new EventSource<void>();
public currentFilter: IFilterResult | undefined;

constructor(private collection: ICategoryCollection) {
Expand Down
4 changes: 2 additions & 2 deletions src/application/Context/State/Selection/IUserSelection.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { SelectedScript } from './SelectedScript';
import { IScript } from '@/domain/IScript';
import { ICategory } from '@/domain/ICategory';
import { ISignal } from '@/infrastructure/Events/ISignal';
import { IEventSource } from '@/infrastructure/Events/IEventSource';

export interface IUserSelection {
readonly changed: ISignal<ReadonlyArray<SelectedScript>>;
readonly changed: IEventSource<ReadonlyArray<SelectedScript>>;
readonly selectedScripts: ReadonlyArray<SelectedScript>;
readonly totalSelected: number;
areAllSelected(category: ICategory): boolean;
Expand Down
4 changes: 2 additions & 2 deletions src/application/Context/State/Selection/UserSelection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ import { SelectedScript } from './SelectedScript';
import { IUserSelection } from './IUserSelection';
import { InMemoryRepository } from '@/infrastructure/Repository/InMemoryRepository';
import { IScript } from '@/domain/IScript';
import { Signal } from '@/infrastructure/Events/Signal';
import { EventSource } from '@/infrastructure/Events/EventSource';
import { IRepository } from '@/infrastructure/Repository/IRepository';
import { ICategory } from '@/domain/ICategory';
import { ICategoryCollection } from '@/domain/ICategoryCollection';

export class UserSelection implements IUserSelection {
public readonly changed = new Signal<ReadonlyArray<SelectedScript>>();
public readonly changed = new EventSource<ReadonlyArray<SelectedScript>>();
private readonly scripts: IRepository<string, SelectedScript>;

constructor(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { EventHandler, ISignal } from './ISignal';
import { IEventSubscription } from './ISubscription';
import { EventHandler, IEventSource, IEventSubscription } from './IEventSource';

export class Signal<T> implements ISignal<T> {
export class EventSource<T> implements IEventSource<T> {
private handlers = new Map<number, EventHandler<T>>();

public on(handler: EventHandler<T>): IEventSubscription {
Expand Down
12 changes: 12 additions & 0 deletions src/infrastructure/Events/EventSubscriptionCollection.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { IEventSubscription } from './IEventSource';

export class EventSubscriptionCollection {
private readonly subscriptions = new Array<IEventSubscription>();
public register(...subscriptions: IEventSubscription[]) {
this.subscriptions.push(...subscriptions);
}
public unsubscribeAll() {
this.subscriptions.forEach((listener) => listener.unsubscribe());
this.subscriptions.splice(0, this.subscriptions.length);
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import { IEventSubscription } from './ISubscription';
export interface ISignal<T> {
export interface IEventSource<T> {
on(handler: EventHandler<T>): IEventSubscription;
}

export interface IEventSubscription {
unsubscribe(): void;
}

export type EventHandler<T> = (data: T) => void;


3 changes: 0 additions & 3 deletions src/infrastructure/Events/ISubscription.ts

This file was deleted.

6 changes: 3 additions & 3 deletions src/infrastructure/Threading/AsyncLazy.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Signal } from '../Events/Signal';
import { EventSource } from '../Events/EventSource';

export class AsyncLazy<T> {
private valueCreated = new Signal();
private valueCreated = new EventSource();
private isValueCreated = false;
private isCreatingValue = false;
private value: T | undefined;
Expand All @@ -15,7 +15,7 @@ export class AsyncLazy<T> {
public async getValueAsync(): Promise<T> {
// If value is already created, return the value directly
if (this.isValueCreated) {
return Promise.resolve(this.value as T);
return Promise.resolve(this.value);
}
// If value is being created, wait until the value is created and then return it.
if (this.isCreatingValue) {
Expand Down
19 changes: 4 additions & 15 deletions src/presentation/CodeButtons/TheCodeButtons.vue
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,7 @@ import MacOsInstructions from './MacOsInstructions.vue';
import { Environment } from '@/application/Environment/Environment';
import { ICategoryCollectionState } from '@/application/Context/State/ICategoryCollectionState';
import { ScriptingLanguage } from '@/domain/ScriptingLanguage';
import { IApplication } from '@/domain/IApplication';
import { IApplicationCode } from '@/application/Context/State/Code/IApplicationCode';
import { IEventSubscription } from '@/infrastructure/Events/ISubscription';
import { IScriptingDefinition } from '@/domain/IScriptingDefinition';
import { OperatingSystem } from '@/domain/OperatingSystem';
Expand All @@ -55,8 +53,6 @@ export default class TheCodeButtons extends StatefulVue {
public isMacOsCollection = false;
public fileName = '';
private codeListener: IEventSubscription;
public async copyCodeAsync() {
const code = await this.getCurrentCodeAsync();
Clipboard.copyText(code.current);
Expand All @@ -68,13 +64,8 @@ export default class TheCodeButtons extends StatefulVue {
this.$modal.show(this.macOsModalName);
}
}
public destroyed() {
if (this.codeListener) {
this.codeListener.unsubscribe();
}
}
protected initialize(app: IApplication): void {
protected initialize(): void {
return;
}
protected handleCollectionState(newState: ICategoryCollectionState): void {
Expand All @@ -90,12 +81,10 @@ export default class TheCodeButtons extends StatefulVue {
}
private async react(code: IApplicationCode) {
this.hasCode = code.current && code.current.length > 0;
if (this.codeListener) {
this.codeListener.unsubscribe();
}
this.codeListener = code.changed.on((newCode) => {
this.events.unsubscribeAll();
this.events.register(code.changed.on((newCode) => {
this.hasCode = newCode && newCode.code.length > 0;
});
}));
}
}
Expand Down
28 changes: 13 additions & 15 deletions src/presentation/Scripts/Cards/CardListItem.vue
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@
import { Component, Prop, Watch, Emit } from 'vue-property-decorator';
import ScriptsTree from '@/presentation/Scripts/ScriptsTree/ScriptsTree.vue';
import { StatefulVue } from '@/presentation/StatefulVue';
import { IEventSubscription } from '@/infrastructure/Events/ISubscription';
@Component({
components: {
Expand All @@ -50,17 +49,11 @@ export default class CardListItem extends StatefulVue {
public isAnyChildSelected = false;
public areAllChildrenSelected = false;
private selectionChangedListener: IEventSubscription;
public async mounted() {
this.updateStateAsync(this.categoryId);
const context = await this.getCurrentContextAsync();
this.selectionChangedListener = context.state.selection.changed.on(() => this.updateStateAsync(this.categoryId));
}
public destroyed() {
if (this.selectionChangedListener) {
this.selectionChangedListener.unsubscribe();
}
this.events.register(context.state.selection.changed.on(
() => this.updateSelectionIndicatorsAsync(this.categoryId)));
await this.updateStateAsync(this.categoryId);
}
@Emit('selected')
public onSelected(isExpanded: boolean) {
Expand All @@ -81,19 +74,24 @@ export default class CardListItem extends StatefulVue {
@Watch('categoryId')
public async updateStateAsync(value: |number) {
const context = await this.getCurrentContextAsync();
const category = !value ? undefined : context.state.collection.findCategory(this.categoryId);
const category = !value ? undefined : context.state.collection.findCategory(value);
this.cardTitle = category ? category.name : undefined;
const currentSelection = context.state.selection;
this.isAnyChildSelected = category ? currentSelection.isAnySelected(category) : false;
this.areAllChildrenSelected = category ? currentSelection.areAllSelected(category) : false;
await this.updateSelectionIndicatorsAsync(value);
}
protected initialize(): void {
return;
}
protected handleCollectionState(): void {
// No need, as categoryId will be updated instead
return;
}
private async updateSelectionIndicatorsAsync(categoryId: number) {
const context = await this.getCurrentContextAsync();
const selection = context.state.selection;
const category = context.state.collection.findCategory(categoryId);
this.isAnyChildSelected = category ? selection.isAnySelected(category) : false;
this.areAllChildrenSelected = category ? selection.areAllSelected(category) : false;
}
}
</script>
Expand Down
27 changes: 10 additions & 17 deletions src/presentation/Scripts/ScriptsTree/ScriptsTree.vue
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,6 @@ import SelectableTree from './SelectableTree/SelectableTree.vue';
import { INode, NodeType } from './SelectableTree/Node/INode';
import { SelectedScript } from '@/application/Context/State/Selection/SelectedScript';
import { INodeSelectedEvent } from './SelectableTree/INodeSelectedEvent';
import { IApplication } from '@/domain/IApplication';
import { IEventSubscription } from '@/infrastructure/Events/ISubscription';
@Component({
components: {
Expand All @@ -43,7 +41,6 @@ export default class ScriptsTree extends StatefulVue {
public filterText?: string = null;
private filtered?: IFilterResult;
private listeners = new Array<IEventSubscription>();
public async toggleNodeSelectionAsync(event: INodeSelectedEvent) {
const context = await this.getCurrentContextAsync();
Expand Down Expand Up @@ -75,31 +72,27 @@ export default class ScriptsTree extends StatefulVue {
|| this.filtered.categoryMatches.some(
(category: ICategory) => node.id === getCategoryNodeId(category));
}
public destroyed() {
this.unsubscribeAll();
}
protected initialize(app: IApplication): void {
protected initialize(): void {
return;
}
protected async handleCollectionState(newState: ICategoryCollectionState) {
this.setCurrentFilter(newState.filter.currentFilter);
if (!this.categoryId) {
this.nodes = parseAllCategories(newState.collection);
}
this.unsubscribeAll();
this.subscribe(newState);
this.events.unsubscribeAll();
this.subscribeState(newState);
}
private subscribe(state: ICategoryCollectionState) {
this.listeners.push(state.selection.changed.on(this.handleSelectionChanged));
this.listeners.push(state.filter.filterRemoved.on(this.handleFilterRemoved));
this.listeners.push(state.filter.filtered.on(this.handleFiltered));
}
private unsubscribeAll() {
this.listeners.forEach((listener) => listener.unsubscribe());
this.listeners.splice(0, this.listeners.length);
private subscribeState(state: ICategoryCollectionState) {
this.events.register(
state.selection.changed.on(this.handleSelectionChanged),
state.filter.filterRemoved.on(this.handleFilterRemoved),
state.filter.filtered.on(this.handleFiltered),
);
}
private setCurrentFilter(currentFilter: IFilterResult | undefined) {
if (!currentFilter) {
this.handleFilterRemoved();
Expand Down
Loading

0 comments on commit f1e21ba

Please sign in to comment.