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 {Component, ViewEncapsulation} from '@angular/core';
import {RouteConfig, Router} from '@angular/router-deprecated'; import {RouteConfig} from '@angular/router-deprecated';
import {Subscription} from 'rxjs/Subscription';
import {Pages} from './pages'; 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? // TODO: is it really the best place to globally require that dependency?
require("!style!css!sass!./theme/sass/_ionicons.scss"); require("!style!css!sass!./theme/sass/_ionicons.scss");
@ -36,16 +35,10 @@ export class App {
isMenuCollapsed:boolean = false; isMenuCollapsed:boolean = false;
private _themeGlobalSubscription:Subscription; constructor(private _state:AppState) {
constructor(private _themeGlobal:ThemeGlobal) { this._state.subscribe('menu.isCollapsed', (isCollapsed) => {
this._themeGlobalSubscription = this._themeGlobal.getDataStream().subscribe((data) => { this.isMenuCollapsed = isCollapsed;
this.isMenuCollapsed = data['menu.isCollapsed'] != null ? data['menu.isCollapsed'] : this.isMenuCollapsed;
}); });
} }
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 // App
import {ThemeGlobal} from "./theme/theme.global"; import {AppState} from "./app.state";
export * from './app.component'; export * from './app.component';
// Application wide providers // Application wide providers
export const APP_PROVIDERS = [ export const APP_PROVIDERS = [
ThemeGlobal AppState
]; ];

View file

@ -1,7 +1,6 @@
import {Component} from '@angular/core'; import {Component} from '@angular/core';
import {Subscription} from "rxjs/Subscription";
import {ThemeGlobal} from "../../../theme"; import {AppState} from "../../../app.state";
@Component({ @Component({
selector: 'content-top', selector: 'content-top',
@ -10,16 +9,10 @@ import {ThemeGlobal} from "../../../theme";
}) })
export class ContentTop { export class ContentTop {
activePageTitle = ''; activePageTitle = '';
private _themeGlobalSubscription:Subscription;
constructor(private _themeGlobal:ThemeGlobal) { constructor(private _state:AppState) {
this._themeGlobalSubscription = this._themeGlobal.getDataStream().subscribe((data) => { this._state.subscribe('menu.activeLink', (activeLink) => {
this.activePageTitle = data['menu.activeLink'] != null ? data['menu.activeLink'].title : this.activePageTitle; 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 {Component, ViewEncapsulation} from '@angular/core';
import {ThemeGlobal} from '../../../theme'; import {AppState} from '../../../app.state';
import {ProfilePicturePipe} from '../../pipes'; import {ProfilePicturePipe} from '../../pipes';
import {MsgCenter} from '../../components/msgCenter'; import {MsgCenter} from '../../components/msgCenter';
import {ScrollPosition} from '../../directives'; import {ScrollPosition} from '../../directives';
@ -18,12 +18,12 @@ export class PageTop {
isMenuCollapsed:boolean = false; isMenuCollapsed:boolean = false;
constructor(private _themeGlobal:ThemeGlobal) { constructor(private _state:AppState) {
} }
toggleMenu() { toggleMenu() {
this.isMenuCollapsed = !this.isMenuCollapsed; this.isMenuCollapsed = !this.isMenuCollapsed;
this._themeGlobal.setData('menu.isCollapsed', this.isMenuCollapsed); this._state.notifyDataChanged('menu.isCollapsed', this.isMenuCollapsed);
} }
scrolledChanged(isScrolled) { scrolledChanged(isScrolled) {

View file

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