app state

This commit is contained in:
nixa 2016-05-13 13:34:55 +03:00
parent e6be0e4519
commit 38e1c6cfa3
8 changed files with 62 additions and 57 deletions

View file

@ -1,9 +1,8 @@
import {Component, ViewEncapsulation} from '@angular/core';
import {RouteConfig, Router} from '@angular/router-deprecated';
import {Subscription} from 'rxjs/Subscription';
import {RouteConfig} from '@angular/router-deprecated';
import {Pages} from './pages';
import {ThemeGlobal} from "./theme";
import {AppState} from "./app.state";
// TODO: is it really the best place to globally require that dependency?
require("!style!css!sass!./theme/sass/_ionicons.scss");
@ -36,16 +35,10 @@ export class App {
isMenuCollapsed:boolean = false;
private _themeGlobalSubscription:Subscription;
constructor(private _state:AppState) {
constructor(private _themeGlobal:ThemeGlobal) {
this._themeGlobalSubscription = this._themeGlobal.getDataStream().subscribe((data) => {
this.isMenuCollapsed = data['menu.isCollapsed'] != null ? data['menu.isCollapsed'] : this.isMenuCollapsed;
this._state.subscribe('menu.isCollapsed', (isCollapsed) => {
this.isMenuCollapsed = isCollapsed;
});
}
ngOnDestroy() {
// prevent memory leak when component destroyed
this._themeGlobalSubscription.unsubscribe();
}
}

43
src/app/app.state.ts Normal file
View file

@ -0,0 +1,43 @@
import {Injectable} from '@angular/core'
import {Subject} from 'rxjs/Subject';
@Injectable()
export class AppState {
private _data = new Subject<Object>();
private _dataStream$ = this._data.asObservable();
private _subscriptions:Map<string, Array<Function>> = new Map<string, Array<Function>>();
constructor() {
this._dataStream$.subscribe((data) => this._onEvent(data));
}
notifyDataChanged(event, value) {
let current = this._data[event];
if (current != value) {
this._data[event] = value;
this._data.next({
event: event,
data: this._data[event]
});
}
}
subscribe(event:string, callback:Function) {
var subscribers = this._subscriptions.get(event) || [];
subscribers.push(callback);
this._subscriptions.set(event, subscribers);
}
_onEvent(data:any) {
var subscribers = this._subscriptions.get(data['event']) || [];
subscribers.forEach((callback) => {
callback.call(null, data['data']);
});
}
}

View file

@ -1,8 +1,8 @@
// App
import {ThemeGlobal} from "./theme/theme.global";
import {AppState} from "./app.state";
export * from './app.component';
// Application wide providers
export const APP_PROVIDERS = [
ThemeGlobal
AppState
];

View file

@ -1,7 +1,6 @@
import {Component} from '@angular/core';
import {Subscription} from "rxjs/Subscription";
import {ThemeGlobal} from "../../../theme";
import {AppState} from "../../../app.state";
@Component({
selector: 'content-top',
@ -10,16 +9,10 @@ import {ThemeGlobal} from "../../../theme";
})
export class ContentTop {
activePageTitle = '';
private _themeGlobalSubscription:Subscription;
constructor(private _themeGlobal:ThemeGlobal) {
this._themeGlobalSubscription = this._themeGlobal.getDataStream().subscribe((data) => {
this.activePageTitle = data['menu.activeLink'] != null ? data['menu.activeLink'].title : this.activePageTitle;
constructor(private _state:AppState) {
this._state.subscribe('menu.activeLink', (activeLink) => {
this.activePageTitle = activeLink.title;
});
}
ngOnDestroy() {
// prevent memory leak when component destroyed
this._themeGlobalSubscription.unsubscribe();
}
}

View file

@ -1,6 +1,6 @@
import {Component, ViewEncapsulation} from '@angular/core';
import {ThemeGlobal} from '../../../theme';
import {AppState} from '../../../app.state';
import {ProfilePicturePipe} from '../../pipes';
import {MsgCenter} from '../../components/msgCenter';
import {ScrollPosition} from '../../directives';
@ -18,12 +18,12 @@ export class PageTop {
isMenuCollapsed:boolean = false;
constructor(private _themeGlobal:ThemeGlobal) {
constructor(private _state:AppState) {
}
toggleMenu() {
this.isMenuCollapsed = !this.isMenuCollapsed;
this._themeGlobal.setData('menu.isCollapsed', this.isMenuCollapsed);
this._state.notifyDataChanged('menu.isCollapsed', this.isMenuCollapsed);
}
scrolledChanged(isScrolled) {

View file

@ -1,7 +1,8 @@
import {Component, ElementRef, HostListener, ViewEncapsulation} from '@angular/core';
import {Router} from '@angular/router-deprecated';
import {ThemeGlobal, layoutSizes} from '../../../theme';
import {AppState} from '../../../app.state';
import {layoutSizes} from '../../../theme';
import {SidebarService} from './sidebar.service';
// TODO: separate menu and sidebar
@ -33,7 +34,7 @@ export class Sidebar {
constructor(private _elementRef:ElementRef,
private _router:Router,
private _sidebarService:SidebarService,
private _themeGlobal:ThemeGlobal) {
private _state:AppState) {
}
@ -70,7 +71,7 @@ export class Sidebar {
menuCollapseStateChange(isCollapsed) {
this.isMenuCollapsed = isCollapsed;
this._themeGlobal.setData('menu.isCollapsed', this.isMenuCollapsed);
this._state.notifyDataChanged('menu.isCollapsed', this.isMenuCollapsed);
}
hoverItem($event) {
@ -123,6 +124,6 @@ export class Sidebar {
});
// notifies all subscribers
this._themeGlobal.setData('menu.activeLink', currentMenu);
this._state.notifyDataChanged('menu.activeLink', currentMenu);
}
}

View file

@ -1,2 +1 @@
export * from './theme.constants'
export * from './theme.global'

View file

@ -1,24 +0,0 @@
import {Injectable} from '@angular/core'
import {Subject} from 'rxjs/Subject';
@Injectable()
export class ThemeGlobal {
private _data = new Subject<Object>();
dataStream$ = this._data.asObservable();
constructor() {
}
setData(key, value) {
let current = this._data[key];
if (current != value) {
this._data[key] = value;
this._data.next(this._data);
}
}
getDataStream() {
return this.dataStream$;
}
}