]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blob - client/src/app/shared/shared-main/angular/defer-loading.directive.ts
53d6e70ba07fbc5bca6f252e8fb573ab751e4a0c
[github/Chocobozzz/PeerTube.git] / client / src / app / shared / shared-main / angular / defer-loading.directive.ts
1 import * as debug from 'debug'
2 import {
3 AfterViewInit,
4 ChangeDetectorRef,
5 ContentChild,
6 Directive,
7 ElementRef,
8 EmbeddedViewRef,
9 EventEmitter,
10 OnDestroy,
11 Output,
12 TemplateRef,
13 ViewContainerRef
14 } from '@angular/core'
15
16 const debugLogger = debug('peertube:main:DeferLoadingDirective')
17
18 @Directive({
19 selector: '[myDeferLoading]'
20 })
21 export class DeferLoadingDirective implements AfterViewInit, OnDestroy {
22 @ContentChild(TemplateRef) template: TemplateRef<any>
23
24 @Output() loaded: EventEmitter<any> = new EventEmitter()
25
26 view: EmbeddedViewRef<any>
27
28 private observer: IntersectionObserver
29
30 constructor (
31 private el: ElementRef,
32 private viewContainer: ViewContainerRef,
33 private cd: ChangeDetectorRef
34 ) { }
35
36 ngAfterViewInit () {
37 if (this.hasIncompatibleBrowser()) {
38 return this.load()
39 }
40
41 this.observer = new IntersectionObserver(entries => {
42 const entry = entries[0]
43 if (!entry.isIntersecting || entry.target !== this.el.nativeElement) return
44
45 this.observer.unobserve(this.el.nativeElement)
46 this.load()
47 }, { threshold: 0.1 })
48
49 this.observer.observe(this.el.nativeElement)
50 }
51
52 load () {
53 if (this.isLoaded()) return
54
55 debugLogger('Loading component')
56
57 this.viewContainer.clear()
58 this.view = this.viewContainer.createEmbeddedView(this.template, {}, 0)
59 this.loaded.emit()
60 this.cd.detectChanges()
61 }
62
63 isLoaded () {
64 return this.view != null
65 }
66
67 ngOnDestroy () {
68 this.view = null
69
70 if (this.observer) this.observer.disconnect()
71 }
72
73 private hasIncompatibleBrowser () {
74 return !('IntersectionObserver' in window)
75 }
76 }