Lazy load charts when listing my channels

This commit is contained in:
Chocobozzz 2022-03-21 11:40:25 +01:00
parent 11d70211af
commit 439b6b7bfb
No known key found for this signature in database
GPG Key ID: 583A612D890159BE
5 changed files with 94 additions and 5 deletions

View File

@ -41,8 +41,16 @@
<my-delete-button label (click)="deleteVideoChannel(videoChannel)"></my-delete-button>
</div>
<div *ngIf="!isInSmallView" class="w-100 d-flex justify-content-end">
<p-chart *ngIf="chartOptions && videoChannelsChartData && videoChannelsChartData[i]" type="line" [data]="videoChannelsChartData[i]" [options]="chartOptions" width="40vw" height="100px"></p-chart>
<div *ngIf="!isInSmallView" class="w-100 d-flex justify-content-end chart-container">
<div myDeferLoading>
<ng-template>
<p-chart
*ngIf="chartOptions && videoChannelsChartData && videoChannelsChartData[i]"
width="40vw" height="100px"
type="line" [data]="videoChannelsChartData[i]" [options]="chartOptions"
></p-chart>
</ng-template>
</div>
</div>
</div>
</div>

View File

@ -62,9 +62,10 @@ my-edit-button {
min-width: 190px;
}
::ng-deep .chartjs-render-monitor {
position: relative;
top: 1px;
.chart-container {
// Sync these values with the template
width: 40vw;
height: 100px;
}
.video-channels-header {

View File

@ -0,0 +1,76 @@
import * as debug from 'debug'
import {
AfterViewInit,
ChangeDetectorRef,
ContentChild,
Directive,
ElementRef,
EmbeddedViewRef,
EventEmitter,
OnDestroy,
Output,
TemplateRef,
ViewContainerRef
} from '@angular/core'
const logger = debug('peertube:main:DeferLoadingDirective')
@Directive({
selector: '[myDeferLoading]'
})
export class DeferLoadingDirective implements AfterViewInit, OnDestroy {
@ContentChild(TemplateRef) template: TemplateRef<any>
@Output() loaded: EventEmitter<any> = new EventEmitter()
view: EmbeddedViewRef<any>
private observer: IntersectionObserver
constructor (
private el: ElementRef,
private viewContainer: ViewContainerRef,
private cd: ChangeDetectorRef
) { }
ngAfterViewInit () {
if (this.hasIncompatibleBrowser()) {
return this.load()
}
this.observer = new IntersectionObserver(entries => {
const entry = entries[0]
if (!entry.isIntersecting || entry.target !== this.el.nativeElement) return
this.observer.unobserve(this.el.nativeElement)
this.load()
}, { threshold: 0.1 })
this.observer.observe(this.el.nativeElement)
}
load () {
if (this.isLoaded()) return
logger('Loading component')
this.viewContainer.clear()
this.view = this.viewContainer.createEmbeddedView(this.template, {}, 0)
this.loaded.emit()
this.cd.detectChanges()
}
isLoaded () {
return this.view != null
}
ngOnDestroy () {
this.view = null
if (this.observer) this.observer.disconnect()
}
private hasIncompatibleBrowser () {
return !('IntersectionObserver' in window)
}
}

View File

@ -1,5 +1,6 @@
export * from './autofocus.directive'
export * from './bytes.pipe'
export * from './defer-loading.directive'
export * from './duration-formatter.pipe'
export * from './from-now.pipe'
export * from './infinite-scroller.directive'

View File

@ -21,6 +21,7 @@ import { AccountService } from './account'
import {
AutofocusDirective,
BytesPipe,
DeferLoadingDirective,
DurationFormatterPipe,
FromNowPipe,
InfiniteScrollerDirective,
@ -80,6 +81,7 @@ import { VideoChannelService } from './video-channel'
BytesPipe,
DurationFormatterPipe,
AutofocusDirective,
DeferLoadingDirective,
InfiniteScrollerDirective,
PeerTubeTemplateDirective,
@ -139,6 +141,7 @@ import { VideoChannelService } from './video-channel'
NumberFormatterPipe,
DurationFormatterPipe,
AutofocusDirective,
DeferLoadingDirective,
InfiniteScrollerDirective,
PeerTubeTemplateDirective,