Skip to content

Commit

Permalink
feat: add loading signal for planet
Browse files Browse the repository at this point in the history
  • Loading branch information
why520crazy committed Mar 17, 2024
1 parent 3b46b76 commit 5034351
Show file tree
Hide file tree
Showing 5 changed files with 37 additions and 45 deletions.
7 changes: 4 additions & 3 deletions examples/portal/src/app/app.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,12 @@
</thy-nav>
</thy-sidebar>
</div>
<div id="app-host-container" class="thy-layout" [ngClass]="{ hide: !loadingDone }">
<div id="app-host-container" class="thy-layout" [ngClass]="{ hide: loading() }">
<div class="portal portal-container">
<router-outlet></router-outlet>
</div>
</div>

<thy-loading class="portal" *ngIf="!loadingDone" [thyDone]="loadingDone"></thy-loading>
@if (loading(); as loadingState) {
<thy-loading class="portal" [thyDone]="!loadingState"></thy-loading>
}
</thy-layout>
4 changes: 2 additions & 2 deletions examples/portal/src/app/app.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ export class AppComponent implements OnInit {

activeAppNames: string[] = [];

get loadingDone() {
return this.planet.loadingDone;
get loading() {
return this.planet.loading;
}

constructor(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,11 @@ class AppStatusChangeFaker {
expect(this.spy).toHaveBeenCalledTimes(fromCalledTimes + 1);
expect(this.spy).toHaveBeenCalledWith({ app: expectedApp, status: ApplicationStatus.bootstrapping });
expect(this.planetApplicationLoader.loadingDone).toBe(false);
expect(this.planetApplicationLoader.loading()).toBe(true);
appRefFaker.bootstrap();
expect(this.planetApplicationLoader.loadingDone).toBe(true);
expect(this.planetApplicationLoader.loading()).toBe(false);

expect(this.spy).toHaveBeenCalledTimes(fromCalledTimes + 3);

expect(this.spy).toHaveBeenCalledWith({ app: expectedApp, status: ApplicationStatus.bootstrapped });
Expand Down
55 changes: 20 additions & 35 deletions packages/planet/src/application/planet-application-loader.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Injectable, NgZone, ApplicationRef, Injector } from '@angular/core';
import { Injectable, NgZone, ApplicationRef, Injector, computed, signal } from '@angular/core';
import { of, Observable, Subject, forkJoin, from, throwError } from 'rxjs';
import { AssetsLoader } from '../assets-loader';
import { PlanetApplication, PlanetRouterEvent, SwitchModes, PlanetOptions } from '../planet.class';
Expand Down Expand Up @@ -54,6 +54,8 @@ export class PlanetApplicationLoader {

private appsLoadingStart$ = new Subject<AppsLoadingStartEvent>();

private innerLoading = signal(false);

public get appStatusChange(): Observable<AppStatusChangeEvent> {
return this.appStatusChange$.asObservable();
}
Expand All @@ -62,8 +64,13 @@ export class PlanetApplicationLoader {
return this.appsLoadingStart$.asObservable();
}

/**
* @deprecated please use loading signal
*/
public loadingDone = false;

public loading = this.innerLoading.asReadonly();

constructor(
private assetsLoader: AssetsLoader,
private planetApplicationService: PlanetApplicationService,
Expand All @@ -73,9 +80,7 @@ export class PlanetApplicationLoader {
applicationRef: ApplicationRef
) {
if (getApplicationLoader()) {
throw new Error(
'PlanetApplicationLoader has been injected in the portal, repeated injection is not allowed'
);
throw new Error('PlanetApplicationLoader has been injected in the portal, repeated injection is not allowed');
}

this.options = {
Expand All @@ -97,9 +102,7 @@ export class PlanetApplicationLoader {
this.ngZone.run(() => {
const fromStatus = this.appsStatus.get(app);
debug(
`app(${app.name}) status change: ${fromStatus ? ApplicationStatus[fromStatus] : 'empty'} => ${
ApplicationStatus[status]
}`
`app(${app.name}) status change: ${fromStatus ? ApplicationStatus[fromStatus] : 'empty'} => ${ApplicationStatus[status]}`
);
this.appsStatus.set(app, status);
this.appStatusChange$.next({
Expand All @@ -109,10 +112,7 @@ export class PlanetApplicationLoader {
});
}

private getAppStatusChange$(
app: PlanetApplication,
status = ApplicationStatus.bootstrapped
): Observable<PlanetApplication> {
private getAppStatusChange$(app: PlanetApplication, status = ApplicationStatus.bootstrapped): Observable<PlanetApplication> {
return this.appStatusChange.pipe(
filter(event => {
return event.app === app && event.status === status;
Expand Down Expand Up @@ -140,6 +140,7 @@ export class PlanetApplicationLoader {
private setLoadingDone() {
this.ngZone.run(() => {
this.loadingDone = true;
this.innerLoading.set(false);
});
}

Expand Down Expand Up @@ -188,9 +189,7 @@ export class PlanetApplicationLoader {
appStatus === ApplicationStatus.loadError
) {
debug(
`app(${app.name}) status is ${
ApplicationStatus[appStatus as ApplicationStatus]
}, start load assets`
`app(${app.name}) status is ${ApplicationStatus[appStatus as ApplicationStatus]}, start load assets`
);
hasAppsNeedLoadingAssets = true;
return this.ngZone.runOutsideAngular(() => {
Expand All @@ -202,6 +201,7 @@ export class PlanetApplicationLoader {
});
if (hasAppsNeedLoadingAssets) {
this.loadingDone = false;
this.innerLoading.set(true);
}
return loadApps$.length > 0 ? forkJoin(loadApps$) : of([] as PlanetApplication[]);
}),
Expand All @@ -212,19 +212,15 @@ export class PlanetApplicationLoader {
switchMap(app => {
const appStatus = this.appsStatus.get(app);
if (appStatus === ApplicationStatus.bootstrapped) {
debug(
`[routeChange] app(${app.name}) status is bootstrapped, show app and active`
);
debug(`[routeChange] app(${app.name}) status is bootstrapped, show app and active`);
this.showApp(app);
const appRef = getPlanetApplicationRef(app.name);
appRef?.navigateByUrl(event.url);
this.setAppStatus(app, ApplicationStatus.active);
this.setLoadingDone();
return of(app);
} else if (appStatus === ApplicationStatus.assetsLoaded) {
debug(
`[routeChange] app(${app.name}) status is assetsLoaded, start bootstrapping`
);
debug(`[routeChange] app(${app.name}) status is assetsLoaded, start bootstrapping`);
return this.bootstrapApp(app).pipe(
map(() => {
debug(`app(${app.name}) bootstrapped success, active it`);
Expand All @@ -237,9 +233,7 @@ export class PlanetApplicationLoader {
debug(`[routeChange] app(${app.name}) is active, do nothings`);
const appRef = getPlanetApplicationRef(app.name);
// Backwards compatibility sub app use old version which has not getCurrentRouterStateUrl
const currentUrl = appRef?.getCurrentRouterStateUrl
? appRef.getCurrentRouterStateUrl()
: '';
const currentUrl = appRef?.getCurrentRouterStateUrl ? appRef.getCurrentRouterStateUrl() : '';
if (currentUrl !== event.url) {
appRef?.navigateByUrl(event.url);
}
Expand All @@ -253,9 +247,7 @@ export class PlanetApplicationLoader {
return this.getAppStatusChange$(app).pipe(
take(1),
map(() => {
debug(
`app(${app.name}) status is bootstrapped by subscribe status change, active it`
);
debug(`app(${app.name}) status is bootstrapped by subscribe status change, active it`);
this.setAppStatus(app, ApplicationStatus.active);
this.showApp(app);
return app;
Expand Down Expand Up @@ -355,10 +347,7 @@ export class PlanetApplicationLoader {
}
}

private bootstrapApp(
app: PlanetApplication,
defaultStatus: 'hidden' | 'display' = 'display'
): Observable<PlanetApplicationRef> {
private bootstrapApp(app: PlanetApplication, defaultStatus: 'hidden' | 'display' = 'display'): Observable<PlanetApplicationRef> {
debug(`app(${app.name}) start bootstrapping`);
this.setAppStatus(app, ApplicationStatus.bootstrapping);
const appRef = getPlanetApplicationRef(app.name);
Expand Down Expand Up @@ -517,11 +506,7 @@ export class PlanetApplicationLoader {
return getPlanetApplicationRef(app.name);
})
);
} else if (
[ApplicationStatus.assetsLoading, ApplicationStatus.assetsLoaded, ApplicationStatus.bootstrapping].includes(
status
)
) {
} else if ([ApplicationStatus.assetsLoading, ApplicationStatus.assetsLoaded, ApplicationStatus.bootstrapping].includes(status)) {
debug(`preload app(${app.name}), status is ${ApplicationStatus[status]}, return until bootstrapped`);
return this.getAppStatusChange$(app).pipe(
take(1),
Expand Down
13 changes: 8 additions & 5 deletions packages/planet/src/planet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,7 @@ import { Injectable, Inject, Optional, Injector } from '@angular/core';
import { NavigationEnd, RouterEvent, Router } from '@angular/router';
import { PlanetOptions, PlanetApplication, PLANET_APPLICATIONS } from './planet.class';
import { PlanetApplicationService } from './application/planet-application.service';
import {
PlanetApplicationLoader,
AppsLoadingStartEvent,
AppStatusChangeEvent
} from './application/planet-application-loader';
import { PlanetApplicationLoader, AppsLoadingStartEvent, AppStatusChangeEvent } from './application/planet-application-loader';
import { Observable, Subscription } from 'rxjs';
import { filter, startWith, distinctUntilChanged, map } from 'rxjs/operators';
import {
Expand All @@ -30,10 +26,17 @@ export class Planet {
return getApplicationService();
}

/**
* @deprecated please use loading signal
*/
public get loadingDone() {
return this.planetApplicationLoader.loadingDone;
}

public get loading() {
return this.planetApplicationLoader.loading;
}

public get appStatusChange(): Observable<AppStatusChangeEvent> {
return this.planetApplicationLoader.appStatusChange;
}
Expand Down

0 comments on commit 5034351

Please sign in to comment.