ee7cb0c8aed47e8e509e836dac364793bbebbd8a
[oweals/peertube.git] / client / src / app / app.module.ts
1 import { ApplicationRef, NgModule } from '@angular/core'
2 import { BrowserModule } from '@angular/platform-browser'
3 import {
4   removeNgStyles,
5   createNewHosts,
6   createInputTransfer
7 } from '@angularclass/hmr'
8
9 import { MetaModule, MetaLoader, MetaStaticLoader, PageTitlePositioning } from '@ngx-meta/core'
10 import 'bootstrap-loader'
11
12 import { ENV_PROVIDERS } from './environment'
13 import { AppRoutingModule } from './app-routing.module'
14 import { AppComponent } from './app.component'
15 import { AppState, InternalStateType } from './app.service'
16
17 import { AccountModule } from './account'
18 import { CoreModule } from './core'
19 import { LoginModule } from './login'
20 import { SignupModule } from './signup'
21 import { SharedModule } from './shared'
22 import { VideosModule } from './videos'
23 import { MenuComponent, MenuAdminComponent } from './menu'
24 import { HeaderComponent } from './header'
25
26 export function metaFactory (): MetaLoader {
27   return new MetaStaticLoader({
28     pageTitlePositioning: PageTitlePositioning.PrependPageTitle,
29     pageTitleSeparator: ' - ',
30     applicationName: 'PeerTube',
31     defaults: {
32       title: 'PeerTube',
33       description: 'PeerTube, a decentralized video streaming platform using P2P (BitTorrent) directly in the web browser'
34     }
35   })
36 }
37
38 type StoreType = {
39   state: InternalStateType,
40   restoreInputValues: () => void,
41   disposeOldHosts: () => void
42 }
43
44 // Application wide providers
45 const APP_PROVIDERS = [
46   AppState
47 ]
48
49 @NgModule({
50   bootstrap: [ AppComponent ],
51   declarations: [
52     AppComponent,
53
54     MenuComponent,
55     MenuAdminComponent,
56     HeaderComponent
57   ],
58   imports: [
59     BrowserModule,
60
61     CoreModule,
62     SharedModule,
63
64     AppRoutingModule,
65
66     AccountModule,
67     CoreModule,
68     LoginModule,
69     SignupModule,
70     SharedModule,
71     VideosModule,
72
73     MetaModule.forRoot({
74       provide: MetaLoader,
75       useFactory: (metaFactory)
76     })
77   ],
78   providers: [ // expose our Services and Providers into Angular's dependency injection
79     ENV_PROVIDERS,
80     APP_PROVIDERS
81   ]
82 })
83 export class AppModule {
84   constructor (
85     public appRef: ApplicationRef,
86     public appState: AppState
87   ) {}
88
89   public hmrOnInit (store: StoreType) {
90     if (!store || !store.state) {
91       return
92     }
93     console.log('HMR store', JSON.stringify(store, null, 2))
94     /**
95      * Set state
96      */
97     this.appState._state = store.state
98     /**
99      * Set input values
100      */
101     if ('restoreInputValues' in store) {
102       let restoreInputValues = store.restoreInputValues
103       setTimeout(restoreInputValues)
104     }
105
106     this.appRef.tick()
107     delete store.state
108     delete store.restoreInputValues
109   }
110
111   public hmrOnDestroy (store: StoreType) {
112     const cmpLocation = this.appRef.components.map((cmp) => cmp.location.nativeElement)
113     /**
114      * Save state
115      */
116     const state = this.appState._state
117     store.state = state
118     /**
119      * Recreate root elements
120      */
121     store.disposeOldHosts = createNewHosts(cmpLocation)
122     /**
123      * Save input values
124      */
125     store.restoreInputValues = createInputTransfer()
126     /**
127      * Remove styles
128      */
129     removeNgStyles()
130   }
131
132   public hmrAfterDestroy (store: StoreType) {
133     /**
134      * Display new elements
135      */
136     store.disposeOldHosts()
137     delete store.disposeOldHosts
138   }
139 }