Skip to content

Instantly share code, notes, and snippets.

@PaulBGD
Created May 20, 2017 19:34
Show Gist options
  • Save PaulBGD/dd80d09cbe53535c40ed72432ab9c982 to your computer and use it in GitHub Desktop.
Save PaulBGD/dd80d09cbe53535c40ed72432ab9c982 to your computer and use it in GitHub Desktop.
Some sort of routing system in an MVP (this is just MP) pattern
type Listener<T> = () => any;
type Canceller = () => void;
export interface Depends {
[key: string]: Model<any, any>;
}
abstract class Model<T, D extends Depends> {
private _listeners: Listener<T>[];
private _cancel: Canceller[]; // from old code, is this supposed to do something? maybe unload all data from a specific page?
public loading: boolean;
public value: T | null;
constructor(private depends: D, initialState?: T, initialLoading?: boolean) {
this._listeners = [];
this.loading = initialLoading && true;
this.value = initialState === undefined ? null : initialState;
this._cancel = Object.keys(depends).map(key => depends[ key ].watch(() => this._update(depends)));
this._update(depends); // do initial update
}
protected abstract _update(data: D);
public update() {
this._update(this.depends);
}
public watch(listener: Listener<T>): () => void {
this._listeners.push(listener);
return () => this._listeners.splice(this._listeners.indexOf(listener), 1);
}
private dispatch() {
this._listeners.forEach(listener => listener());
}
public set(value: T) {
const changed = value !== this.value;
this.value = value;
const oldLoading = this.loading;
this.loading = value === null;
if (changed || oldLoading !== this.loading) {
this.dispatch();
}
}
public setLoading(loading: boolean) {
const changed = loading !== this.loading;
if (changed) {
this.loading = loading;
this.dispatch();
}
}
}
export default Model;
import Model, { Depends } from './Model';
export interface Route<D> {
data: D;
scene: SvelteComponent;
}
interface RouteData {
stack: Route<any>[];
index: number;
}
type RouteDepends = Depends;
class RouteModel extends Model<RouteData, RouteDepends> {
constructor() {
super({}, {
stack: [],
index: -1,
}, false);
}
protected _update(data: Depends) {
// nothing to do
}
}
export default new RouteModel();
import routeModel, { Route } from '../models/RouteModel';
export function getCurrentRoute(): Route<any> {
const { stack, index } = routeModel.value;
if (index >= 0) {
return stack[index];
}
throw new Error('No routes yet.');
}
export function pop() {
const { stack, index } = routeModel.value;
routeModel.set({ stack, index: Math.max(0, index - 1) });
}
export function popToTop() {
const { stack } = routeModel.value;
routeModel.set({ stack, index: 0 });
}
export function push(route: Route<any>) {
const { stack, index } = routeModel.value;
stack.splice(index + 1);
stack.push(route);
routeModel.set({ stack, index: index + 1 });
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment