import { isEmpty } from 'ngx-tethys/util' ; import { Component , OnInit , ElementRef , Renderer2 , Output , EventEmitter , HostBinding , Input , NgZone , OnDestroy , Inject } from '@angular/core' ; import { mimeTypeConvert } from './util' ; import { fromEvent , Subject } from 'rxjs' ; import { takeUntil , filter , tap } from 'rxjs/operators' ; import { THY_UPLOADER_DEFAULT_OPTIONS , ThyUploaderConfig } from './uploader.config' ; import { FileSelectBaseComponent } from './file-select-base' ; @ Component ( { selector : '[thyFileDrop]' , template : `
        <ng-content></ng-content>
    ` } ) export class ThyFileDropComponent extends FileSelectBaseComponent implements OnInit , OnDestroy { @ HostBinding ( 'class.drop-over' ) @ HostBinding ( 'class.thy-drop-over' ) isDragOver = false ; private dragOverCustomClass : string ; @ Input ( ) set thyFileDropClassName ( value ) { this . dragOverCustomClass = value ; } @ Input ( ) set thyAcceptType ( value ) { this . acceptType = mimeTypeConvert ( value ) ; } @ Output ( ) thyOnDrop = new EventEmitter ( ) ; private ngUnsubscribe$ = new Subject ( ) ; constructor ( public elementRef , public renderer , public ngZone , @ Inject ( THY_UPLOADER_DEFAULT_OPTIONS ) public defaultConfig ) { super ( elementRef , defaultConfig ) ; } public ngOnInit ( ) { this . ngZone . runOutsideAngular ( ( ) => { fromEvent ( this . elementRef . nativeElement , 'dragenter' ) . pipe ( takeUntil ( this . ngUnsubscribe$ ) , tap ( ( event ) => { event . preventDefault ( ) ; } ) , filter ( event => event . dataTransfer . items && event . dataTransfer . items . length > 0 ) ) . subscribe ( ( event ) => { if ( this . checkRejectFolderAndHtmlElement ( event ) ) { const files = this . filterFilesOrItems ( Array . from ( event . dataTransfer . items ) ) ; if ( ! isEmpty ( files ) ) { this . ngZone . run ( ( ) => { this . isDragOver = true ; this . toggleDropOverClassName ( ) ; } ) ; } } } ) ; fromEvent ( this . elementRef . nativeElement , 'dragover' ) . pipe ( takeUntil ( this . ngUnsubscribe$ ) ) . subscribe ( ( event ) => { event . preventDefault ( ) ; } ) ; fromEvent ( this . elementRef . nativeElement , 'dragleave' ) . pipe ( takeUntil ( this . ngUnsubscribe$ ) ) . subscribe ( ( event ) => { this . ngZone . run ( ( ) => { if ( ! this . elementRef . nativeElement . contains ( event . fromElement ) ) { this . resetDragOver ( ) ; this . toggleDropOverClassName ( ) ; } } ) ; } ) ; fromEvent ( this . elementRef . nativeElement , 'drop' ) . pipe ( takeUntil ( this . ngUnsubscribe$ ) , tap ( ( event ) => { event . preventDefault ( ) ; } ) ) . subscribe ( ( event ) => { this . ngZone . run ( ( ) => { if ( this . checkRejectFolderAndHtmlElement ( event ) ) { const files = this . filterFilesOrItems ( event . dataTransfer ? Array . from ( event . dataTransfer . files ) : [ ] ) ; if ( ! isEmpty ( files ) ) { this . selectFiles ( event , Array . from ( event . dataTransfer . files ) , this . thyOnDrop ) ; } } this . resetDragOver ( ) ; this . toggleDropOverClassName ( ) ; } ) ; } ) ; } ) ; } private checkRejectFolderAndHtmlElement ( event ) { const items = event . dataTransfer ? event . dataTransfer . items : [ ] ; let res = true ; for ( let index = 0 ; index < items . length ; index ++ ) { const item = items [ index ] ; const entry = this . getAsEntry ( item ) ; if ( item . kind !== 'file' || ( entry && ! entry . isFile ) ) { res = false ; } } return res ; } private getAsEntry ( item ) { let entry ; if ( item [ 'getAsEntry' ] ) { entry = item [ 'getAsEntry' ] ( ) ; } else if ( item . webkitGetAsEntry ) { entry = item . webkitGetAsEntry ( ) ; } return entry ; } private filterFilesOrItems ( items ) { if ( this . acceptType && this . acceptType != '*/*' ) { return items . filter ( item => { return this . acceptType . includes ( item . type ) ; } ) ; } else { return Array . from ( items ) ; } } private toggleDropOverClassName ( ) { if ( this . dragOverCustomClass ) { if ( this . isDragOver ) { this . renderer . addClass ( this . elementRef . nativeElement , this . dragOverCustomClass ) ; } else { this . renderer . removeClass ( this . elementRef . nativeElement , this . dragOverCustomClass ) ; } } } private setDragOverState ( isDragOver ) { this . isDragOver = isDragOver ; } private resetDragOver ( ) { this . setDragOverState ( false ) ; } public ngOnDestroy ( ) { this . ngUnsubscribe$ . next ( ) ; this . ngUnsubscribe$ . complete ( ) ; } }