import { EVT } from './EVT' ; import { DOM } from './DOM' ; import { downloadArgument , DonwloadSuccessData , DownloadedMsg , } from './Download.d' ; import { store } from './Store' ; import { log } from './Log' ; import { lang } from './Lang' ; import { titleBar } from './TitleBar' ; import { Colors } from './Colors' ; import { form } from './Settings' ; import { Download } from './Download' ; import { progressBar } from './ProgressBar' ; interface TaskList { [ id ] : { index : number ; progressBarIndex : number ; } ; } class DownloadControl { constructor ( ) { this . createDownloadArea ( ) ; this . listenEvents ( ) ; } private readonly downloadThreadMax : number = 10 ; private downloadThread : number = 3 ; private taskBatch = 0 ; private statesList : number [ ] = [ ] ; private taskList : TaskList = { } ; private downloaded : number = 0 ; private reTryTimer : number = 0 ; private downloadArea : HTMLDivElement = document . createElement ( 'div' ) ; private totalNumberEl : HTMLSpanElement = document . createElement ( 'span' ) ; private downStatusEl : HTMLSpanElement = document . createElement ( 'span' ) ; private downloadStop : boolean = false ; private downloadPause : boolean = false ; public get downloadStopped ( ) { return this . downloadPause || this . downloadStop ; } private listenEvents ( ) { window . addEventListener ( EVT . events . crawlStart , ( ) => { this . hideDownloadArea ( ) ; this . reset ( ) ; } ) ; window . addEventListener ( EVT . events . crawlFinish , ( ) => { this . showDownloadArea ( ) ; this . beforeDownload ( ) ; } ) ; window . addEventListener ( EVT . events . skipSaveFile , ( ev ) => { const data = ev . detail . data as DonwloadSuccessData ; this . downloadSuccess ( data ) ; } ) ; chrome . runtime . onMessage . addListener ( ( msg ) => { if ( ! this . taskBatch ) { return ; } if ( msg . msg === 'downloaded' ) { EVT . fire ( EVT . events . downloadSucccess , msg . data ) ; this . downloadSuccess ( msg . data ) ; } else if ( msg . msg === 'download_err' ) { log . error ( `${ msg . data . url } Download error! Code: ${ msg . err }. Will try again later.` ) ; EVT . fire ( EVT . events . downloadError ) ; this . downloadError ( msg . data , msg . err ) ; } if ( msg . data && msg . data . uuid ) { log . error ( lang . transl ( '_uuid' ) ) ; } } ) ; } private set setDownloaded ( val ) { this . downloaded = val ; this . LogDownloadStates ( ) ; this . totalNumberEl . textContent = store . result . length . toString ( ) ; progressBar . setTotalProgress ( this . downloaded ) ; if ( this . downloaded === 0 ) { this . setDownStateText ( lang . transl ( '_未开始下载' ) ) ; } if ( this . downloaded === store . result . length ) { EVT . fire ( EVT . events . downloadComplete ) ; this . reset ( ) ; this . setDownStateText ( lang . transl ( '_下载完毕' ) ) ; log . success ( lang . transl ( '_下载完毕' ) , 2 ) ; titleBar . change ( '√' ) ; } } private downloadedAdd ( ) { this . setDownloaded = this . downloaded + 1 ; } private showDownloadArea ( ) { this . downloadArea . style . display = 'block' ; } private hideDownloadArea ( ) { this . downloadArea . style . display = 'none' ; } private setDownStateText ( str , color = '' ) { const el = document . createElement ( 'span' ) ; el . textContent = str ; if ( color ) { el . style . color = color ; } this . downStatusEl . innerHTML = '' ; this . downStatusEl . appendChild ( el ) ; } private reset ( ) { this . statesList = [ ] ; this . downloadPause = false ; this . downloadStop = false ; clearTimeout ( this . reTryTimer ) ; } private createDownloadArea ( ) { const html = `<div class="download_area">
    <p> ${ lang . transl ( '_共抓取到n个文件' , '<span class="fwb blue imgNum">0</span>' ) }</p>
    
    <div class="centerWrap_btns">
    <button class="startDownload" type="button" style="background:${ Colors . blue };"> ${ lang . transl ( '_下载按钮1' ) }</button>
    <button class="pauseDownload" type="button" style="background:#e49d00;"> ${ lang . transl ( '_下载按钮2' ) }</button>
    <button class="stopDownload" type="button" style="background:${ Colors . red };"> ${ lang . transl ( '_下载按钮3' ) }</button>
    <button class="previewFileName" type="button" style="background:${ Colors . green };"> ${ lang . transl ( '_预览文件名' ) }</button>
    </div>
    <div class="centerWrap_down_tips">
    <p>
    ${ lang . transl ( '_当前状态' ) }
    <span class="down_status blue"><span>${ lang . transl ( '_未开始下载' ) }</span></span>
    </p>
    </div>
    </div>` ; const el = DOM . useSlot ( 'downloadArea' , html ) ; this . downloadArea = el as HTMLDivElement ; this . downStatusEl = el . querySelector ( '.down_status ' ) as HTMLSpanElement ; this . totalNumberEl = el . querySelector ( '.imgNum' ) as HTMLSpanElement ; document . querySelector ( '.startDownload' ) ! . addEventListener ( 'click' , ( ) => { this . startDownload ( ) ; } ) ; document . querySelector ( '.pauseDownload' ) ! . addEventListener ( 'click' , ( ) => { this . pauseDownload ( ) ; } ) ; document . querySelector ( '.stopDownload' ) ! . addEventListener ( 'click' , ( ) => { this . stopDownload ( ) ; } ) ; document . querySelector ( '.previewFileName' ) ! . addEventListener ( 'click' , ( ) => { EVT . fire ( EVT . events . previewFileName ) ; } ) ; } private setDownloadThread ( ) { const setThread = parseInt ( form . downloadThread . value ) ; if ( setThread < 1 || setThread > this . downloadThreadMax || isNaN ( setThread ) ) { this . downloadThread = this . downloadThreadMax ; } else { this . downloadThread = setThread ; } if ( store . result . length - this . downloaded < this . downloadThread ) { this . downloadThread = store . result . length - this . downloaded ; } progressBar . reset ( this . downloadThread , this . downloaded ) ; } private beforeDownload ( ) { this . setDownloaded = 0 ; this . setDownloadThread ( ) ; const autoDownload = form . quietDownload . checked ; if ( ! autoDownload && ! store . states . quickDownload ) { titleBar . change ( '▶' ) ; } if ( autoDownload || store . states . quickDownload ) { this . startDownload ( ) ; } } private startDownload ( ) { if ( ! store . states . allowWork || store . result . length === 0 ) { return ; } if ( ! this . downloadPause ) { this . setDownloaded = 0 ; this . statesList = new Array ( store . result . length ) . fill ( - 1 ) ; this . taskBatch = new Date ( ) . getTime ( ) ; } else { for ( let index = 0 ; index < this . statesList . length ; index ++ ) { if ( this . statesList [ index ] === 0 ) { this . statesList [ index ] = - 1 ; } } } this . downloadPause = false ; this . downloadStop = false ; clearTimeout ( this . reTryTimer ) ; this . setDownloadThread ( ) ; EVT . fire ( EVT . events . downloadStart ) ; for ( let i = 0 ; i < this . downloadThread ; i ++ ) { this . createDownload ( i ) ; } this . setDownStateText ( lang . transl ( '_正在下载中' ) ) ; log . log ( lang . transl ( '_正在下载中' ) ) ; } private pauseDownload ( ) { clearTimeout ( this . reTryTimer ) ; if ( store . result . length === 0 ) { return ; } if ( this . downloadStop === true ) { return ; } if ( this . downloadPause === false ) { if ( ! store . states . allowWork ) { this . downloadPause = true ; EVT . fire ( EVT . events . downloadPause ) ; titleBar . change ( '║' ) ; this . setDownStateText ( lang . transl ( '_已暂停' ) , '#f00' ) ; log . warning ( lang . transl ( '_已暂停' ) , 2 ) ; } else { return ; } } } private stopDownload ( ) { clearTimeout ( this . reTryTimer ) ; if ( store . result . length === 0 || this . downloadStop ) { return ; } this . downloadStop = true ; EVT . fire ( EVT . events . downloadStop ) ; titleBar . change ( '■' ) ; this . setDownStateText ( lang . transl ( '_已停止' ) , '#f00' ) ; log . error ( lang . transl ( '_已停止' ) , 2 ) ; this . downloadPause = false ; } private downloadError ( data , err ? ) { if ( this . downloadPause || this . downloadStop ) { return false ; } const task = this . taskList [ data . id ] ; this . setDownloadedIndex ( task . index , - 1 ) ; this . createDownload ( task . progressBarIndex , err === 'SERVER_FAILED' ) ; } private downloadSuccess ( data ) { const task = this . taskList [ data . id ] ; this . setDownloadedIndex ( task . index , 1 ) ; this . downloadedAdd ( ) ; const no = task . progressBarIndex ; if ( this . checkContinueDownload ( ) ) { this . createDownload ( no ) ; } } private setDownloadedIndex ( index , value ) { this . statesList [ index ] = value ; } private checkContinueDownload ( ) { if ( this . downloaded < store . result . length ) { if ( this . downloadPause || this . downloadStop ) { return false ; } if ( this . downloaded + this . downloadThread - 1 < store . result . length ) { return true ; } else { return false ; } } else { return false ; } } private LogDownloadStates ( ) { let text = `${ this . downloaded } / ${ store . result . length }` ; log . log ( text , 2 , false ) ; } private createDownload ( progressBarIndex , useThumb = false ) { let length = this . statesList . length ; let index ; for ( let i = 0 ; i < length ; i ++ ) { if ( this . statesList [ i ] === - 1 ) { this . statesList [ i ] = 0 ; index = i ; break ; } } if ( index === undefined ) { throw new Error ( 'There are no data to download' ) ; } else { let result = store . result [ index ] ; if ( useThumb && result . retryUrl ) { ; [ result . url , result . retryUrl ] = [ result . retryUrl , result . url ] ; } const data = { id : result . fileId , data : result , index : index , progressBarIndex : progressBarIndex , taskBatch : this . taskBatch , } ; this . taskList [ data . data . fileId ] = { index , progressBarIndex : progressBarIndex , } ; new Download ( progressBarIndex , data ) ; } } } new DownloadControl ( ) ; export { } ;