mirror of
https://github.com/Myxelium/Bridge-Multi.git
synced 2026-04-11 14:19:38 +00:00
More download bugfixes
This commit is contained in:
12
package-lock.json
generated
12
package-lock.json
generated
@@ -2142,6 +2142,15 @@
|
|||||||
"integrity": "sha512-Q1y515GcOdTHgagaVFhHnIFQ38ygs/kmxdNpvpou+raI9UO3YZcHDngBSYKQklcKlvA7iuQlmIKbzvmxcOE9CQ==",
|
"integrity": "sha512-Q1y515GcOdTHgagaVFhHnIFQ38ygs/kmxdNpvpou+raI9UO3YZcHDngBSYKQklcKlvA7iuQlmIKbzvmxcOE9CQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"@types/destroy": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/destroy/-/destroy-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-nE3ePJLWPRu/qFHN8mj3fWnkr9K9ezwoiG4yOis2DuLeAawlnOOT/pM29JQkityrwfEvkblU5O9iS1bsiMqtDw==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@types/node": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"@types/electron-window-state": {
|
"@types/electron-window-state": {
|
||||||
"version": "2.0.33",
|
"version": "2.0.33",
|
||||||
"resolved": "https://registry.npmjs.org/@types/electron-window-state/-/electron-window-state-2.0.33.tgz",
|
"resolved": "https://registry.npmjs.org/@types/electron-window-state/-/electron-window-state-2.0.33.tgz",
|
||||||
@@ -5423,8 +5432,7 @@
|
|||||||
"destroy": {
|
"destroy": {
|
||||||
"version": "1.0.4",
|
"version": "1.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
|
||||||
"integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=",
|
"integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"detect-file": {
|
"detect-file": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
|
|||||||
@@ -36,6 +36,7 @@
|
|||||||
"@angular/router": "~9.1.4",
|
"@angular/router": "~9.1.4",
|
||||||
"cli-color": "^2.0.0",
|
"cli-color": "^2.0.0",
|
||||||
"comparators": "^3.0.2",
|
"comparators": "^3.0.2",
|
||||||
|
"destroy": "^1.0.4",
|
||||||
"electron-window-state": "^5.0.3",
|
"electron-window-state": "^5.0.3",
|
||||||
"fomantic-ui": "^2.8.3",
|
"fomantic-ui": "^2.8.3",
|
||||||
"jquery": "^3.4.1",
|
"jquery": "^3.4.1",
|
||||||
@@ -56,6 +57,7 @@
|
|||||||
"@angular/compiler-cli": "~9.1.4",
|
"@angular/compiler-cli": "~9.1.4",
|
||||||
"@angular/language-service": "~9.1.4",
|
"@angular/language-service": "~9.1.4",
|
||||||
"@types/cli-color": "^2.0.0",
|
"@types/cli-color": "^2.0.0",
|
||||||
|
"@types/destroy": "^1.0.0",
|
||||||
"@types/electron-window-state": "^2.0.33",
|
"@types/electron-window-state": "^2.0.33",
|
||||||
"@types/mv": "^2.1.0",
|
"@types/mv": "^2.1.0",
|
||||||
"@types/needle": "^2.0.4",
|
"@types/needle": "^2.0.4",
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { Component, ChangeDetectorRef } from '@angular/core'
|
import { Component, ChangeDetectorRef } from '@angular/core'
|
||||||
import { DownloadProgress } from '../../../../../electron/shared/interfaces/download.interface'
|
import { DownloadProgress } from '../../../../../electron/shared/interfaces/download.interface'
|
||||||
import { DownloadService } from '../../../../core/services/download.service'
|
import { DownloadService } from '../../../../core/services/download.service'
|
||||||
import { ElectronService } from 'src/app/core/services/electron.service'
|
import { ElectronService } from '../../../../core/services/electron.service'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-downloads-modal',
|
selector: 'app-downloads-modal',
|
||||||
@@ -13,6 +13,10 @@ export class DownloadsModalComponent {
|
|||||||
downloads: DownloadProgress[] = []
|
downloads: DownloadProgress[] = []
|
||||||
|
|
||||||
constructor(private electronService: ElectronService, private downloadService: DownloadService, ref: ChangeDetectorRef) {
|
constructor(private electronService: ElectronService, private downloadService: DownloadService, ref: ChangeDetectorRef) {
|
||||||
|
electronService.receiveIPC('queue-updated', (order) => {
|
||||||
|
this.downloads.sort((a, b) => order.indexOf(a.versionID) - order.indexOf(b.versionID))
|
||||||
|
})
|
||||||
|
|
||||||
downloadService.onDownloadUpdated(download => {
|
downloadService.onDownloadUpdated(download => {
|
||||||
const index = this.downloads.findIndex(thisDownload => thisDownload.versionID == download.versionID)
|
const index = this.downloads.findIndex(thisDownload => thisDownload.versionID == download.versionID)
|
||||||
if (index == -1) {
|
if (index == -1) {
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import { Injectable, EventEmitter } from '@angular/core'
|
import { Injectable, EventEmitter } from '@angular/core'
|
||||||
import { ElectronService } from './electron.service'
|
import { ElectronService } from './electron.service'
|
||||||
import { NewDownload, DownloadProgress } from '../../../electron/shared/interfaces/download.interface'
|
import { NewDownload, DownloadProgress } from '../../../electron/shared/interfaces/download.interface'
|
||||||
import * as _ from 'underscore'
|
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
@@ -46,14 +45,7 @@ export class DownloadService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onDownloadUpdated(callback: (download: DownloadProgress) => void) {
|
onDownloadUpdated(callback: (download: DownloadProgress) => void) {
|
||||||
const debouncedCallback = _.throttle(callback, 30, { trailing: false })
|
this.downloadUpdatedEmitter.subscribe(callback)
|
||||||
this.downloadUpdatedEmitter.subscribe((download: DownloadProgress) => {
|
|
||||||
if (download.type == 'fastUpdate') { // 'good' updates can happen so frequently that the UI doesn't update correctly
|
|
||||||
debouncedCallback(download)
|
|
||||||
} else {
|
|
||||||
callback(download)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cancelDownload(versionID: number) {
|
cancelDownload(versionID: number) {
|
||||||
|
|||||||
@@ -10,9 +10,11 @@ import { mkdir as _mkdir } from 'fs'
|
|||||||
import { ProgressType, NewDownload } from 'src/electron/shared/interfaces/download.interface'
|
import { ProgressType, NewDownload } from 'src/electron/shared/interfaces/download.interface'
|
||||||
import { DriveFile } from 'src/electron/shared/interfaces/songDetails.interface'
|
import { DriveFile } from 'src/electron/shared/interfaces/songDetails.interface'
|
||||||
import { FileTransfer } from './FileTransfer'
|
import { FileTransfer } from './FileTransfer'
|
||||||
|
import * as _rimraf from 'rimraf'
|
||||||
|
|
||||||
const randomBytes = promisify(_randomBytes)
|
const randomBytes = promisify(_randomBytes)
|
||||||
const mkdir = promisify(_mkdir)
|
const mkdir = promisify(_mkdir)
|
||||||
|
const rimraf = promisify(_rimraf)
|
||||||
|
|
||||||
type EventCallback = {
|
type EventCallback = {
|
||||||
/** Note: this will not be the last event if `retry()` is called. */
|
/** Note: this will not be the last event if `retry()` is called. */
|
||||||
@@ -31,6 +33,8 @@ export class ChartDownload {
|
|||||||
private callbacks = {} as Callbacks
|
private callbacks = {} as Callbacks
|
||||||
private files: DriveFile[]
|
private files: DriveFile[]
|
||||||
private percent = 0 // Needs to be stored here because errors won't know the exact percent
|
private percent = 0 // Needs to be stored here because errors won't know the exact percent
|
||||||
|
private chartPath: string
|
||||||
|
private dropFastUpdate = false
|
||||||
|
|
||||||
private readonly individualFileProgressPortion: number
|
private readonly individualFileProgressPortion: number
|
||||||
private readonly destinationFolderName: string
|
private readonly destinationFolderName: string
|
||||||
@@ -68,6 +72,13 @@ export class ChartDownload {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the GUI to indicate that a retry will be attempted.
|
||||||
|
*/
|
||||||
|
displayRetrying() {
|
||||||
|
this.updateGUI('', 'Waiting for other downloads to finish to retry...', 'good')
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cancels the download if it is running.
|
* Cancels the download if it is running.
|
||||||
*/
|
*/
|
||||||
@@ -76,6 +87,7 @@ export class ChartDownload {
|
|||||||
const cancelFn = this.cancelFn
|
const cancelFn = this.cancelFn
|
||||||
this.cancelFn = undefined
|
this.cancelFn = undefined
|
||||||
cancelFn()
|
cancelFn()
|
||||||
|
rimraf(this.chartPath) // Delete temp folder
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -83,6 +95,15 @@ export class ChartDownload {
|
|||||||
* Updates the GUI with new information about this chart download.
|
* Updates the GUI with new information about this chart download.
|
||||||
*/
|
*/
|
||||||
private updateGUI(header: string, description: string, type: ProgressType) {
|
private updateGUI(header: string, description: string, type: ProgressType) {
|
||||||
|
if (type == 'fastUpdate') {
|
||||||
|
if (this.dropFastUpdate) {
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
this.dropFastUpdate = true
|
||||||
|
setTimeout(() => this.dropFastUpdate = false, 30)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
emitIPCEvent('download-updated', {
|
emitIPCEvent('download-updated', {
|
||||||
versionID: this.versionID,
|
versionID: this.versionID,
|
||||||
title: `${this.data.avTagName} - ${this.data.artist}`,
|
title: `${this.data.avTagName} - ${this.data.artist}`,
|
||||||
@@ -108,9 +129,8 @@ export class ChartDownload {
|
|||||||
*/
|
*/
|
||||||
async beginDownload() {
|
async beginDownload() {
|
||||||
// CREATE DOWNLOAD DIRECTORY
|
// CREATE DOWNLOAD DIRECTORY
|
||||||
let chartPath: string
|
|
||||||
try {
|
try {
|
||||||
chartPath = await this.createDownloadFolder()
|
this.chartPath = await this.createDownloadFolder()
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
this.retryFn = () => this.beginDownload()
|
this.retryFn = () => this.beginDownload()
|
||||||
this.updateGUI('Access Error', err.message, 'error')
|
this.updateGUI('Access Error', err.message, 'error')
|
||||||
@@ -119,7 +139,7 @@ export class ChartDownload {
|
|||||||
|
|
||||||
// DOWNLOAD FILES
|
// DOWNLOAD FILES
|
||||||
for (let i = 0; i < this.files.length; i++) {
|
for (let i = 0; i < this.files.length; i++) {
|
||||||
const downloader = new FileDownloader(this.files[i].webContentLink, join(chartPath, this.files[i].name))
|
const downloader = new FileDownloader(this.files[i].webContentLink, join(this.chartPath, this.files[i].name))
|
||||||
this.cancelFn = () => downloader.cancelDownload()
|
this.cancelFn = () => downloader.cancelDownload()
|
||||||
|
|
||||||
const downloadComplete = this.addDownloadEventListeners(downloader, i)
|
const downloadComplete = this.addDownloadEventListeners(downloader, i)
|
||||||
@@ -129,7 +149,7 @@ export class ChartDownload {
|
|||||||
|
|
||||||
// EXTRACT FILES
|
// EXTRACT FILES
|
||||||
if (this.isArchive) {
|
if (this.isArchive) {
|
||||||
const extractor = new FileExtractor(chartPath)
|
const extractor = new FileExtractor(this.chartPath)
|
||||||
this.cancelFn = () => extractor.cancelExtract()
|
this.cancelFn = () => extractor.cancelExtract()
|
||||||
|
|
||||||
const extractComplete = this.addExtractorEventListeners(extractor)
|
const extractComplete = this.addExtractorEventListeners(extractor)
|
||||||
@@ -138,7 +158,7 @@ export class ChartDownload {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TRANSFER FILES
|
// TRANSFER FILES
|
||||||
const transfer = new FileTransfer(chartPath, this.destinationFolderName)
|
const transfer = new FileTransfer(this.chartPath, this.destinationFolderName)
|
||||||
this.cancelFn = () => transfer.cancelTransfer()
|
this.cancelFn = () => transfer.cancelTransfer()
|
||||||
|
|
||||||
const transferComplete = this.addTransferEventListeners(transfer)
|
const transferComplete = this.addTransferEventListeners(transfer)
|
||||||
|
|||||||
@@ -29,10 +29,11 @@ class DownloadHandler implements IPCEmitHandler<'download'> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private retryDownload(data: Download) { // TODO: cause this to send a GUI update that says waiting for download to finish...
|
private retryDownload(data: Download) {
|
||||||
const index = this.retryWaiting.findIndex(download => download.versionID == data.versionID)
|
const index = this.retryWaiting.findIndex(download => download.versionID == data.versionID)
|
||||||
if (index != -1) {
|
if (index != -1) {
|
||||||
const retryDownload = this.retryWaiting.splice(index, 1)[0]
|
const retryDownload = this.retryWaiting.splice(index, 1)[0]
|
||||||
|
retryDownload.displayRetrying()
|
||||||
if (this.currentDownload == undefined) {
|
if (this.currentDownload == undefined) {
|
||||||
this.currentDownload = retryDownload
|
this.currentDownload = retryDownload
|
||||||
retryDownload.retry()
|
retryDownload.retry()
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import Comparators from 'comparators'
|
import Comparators from 'comparators'
|
||||||
import { ChartDownload } from './ChartDownload'
|
import { ChartDownload } from './ChartDownload'
|
||||||
|
import { emitIPCEvent } from '../../main'
|
||||||
|
|
||||||
export class DownloadQueue {
|
export class DownloadQueue {
|
||||||
|
|
||||||
@@ -15,7 +16,7 @@ export class DownloadQueue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pop() {
|
pop() {
|
||||||
return this.downloadQueue.pop()
|
return this.downloadQueue.shift()
|
||||||
}
|
}
|
||||||
|
|
||||||
get(versionID: number) {
|
get(versionID: number) {
|
||||||
@@ -27,6 +28,7 @@ export class DownloadQueue {
|
|||||||
if (index != -1) {
|
if (index != -1) {
|
||||||
this.downloadQueue[index].cancel()
|
this.downloadQueue[index].cancel()
|
||||||
this.downloadQueue.splice(index, 1)
|
this.downloadQueue.splice(index, 1)
|
||||||
|
emitIPCEvent('queue-updated', this.downloadQueue.map(download => download.versionID))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -39,5 +41,6 @@ export class DownloadQueue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.downloadQueue.sort(comparator)
|
this.downloadQueue.sort(comparator)
|
||||||
|
emitIPCEvent('queue-updated', this.downloadQueue.map(download => download.versionID))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2,6 +2,7 @@ import { AnyFunction } from '../../shared/UtilFunctions'
|
|||||||
import { createWriteStream } from 'fs'
|
import { createWriteStream } from 'fs'
|
||||||
import * as needle from 'needle'
|
import * as needle from 'needle'
|
||||||
// TODO: replace needle with got (for cancel() method) (if before-headers event is possible?)
|
// TODO: replace needle with got (for cancel() method) (if before-headers event is possible?)
|
||||||
|
// TODO: add download throttle library and setting
|
||||||
import { getSettings } from '../SettingsHandler.ipc'
|
import { getSettings } from '../SettingsHandler.ipc'
|
||||||
import { googleTimer } from './GoogleTimer'
|
import { googleTimer } from './GoogleTimer'
|
||||||
import { DownloadError } from './ChartDownload'
|
import { DownloadError } from './ChartDownload'
|
||||||
@@ -37,6 +38,7 @@ export class FileDownloader {
|
|||||||
private callbacks = {} as Callbacks
|
private callbacks = {} as Callbacks
|
||||||
private retryCount: number
|
private retryCount: number
|
||||||
private wasCanceled = false
|
private wasCanceled = false
|
||||||
|
private req: NodeJS.ReadableStream
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param url The download link.
|
* @param url The download link.
|
||||||
@@ -55,7 +57,6 @@ export class FileDownloader {
|
|||||||
* Download the file after waiting for the google rate limit.
|
* Download the file after waiting for the google rate limit.
|
||||||
*/
|
*/
|
||||||
beginDownload() {
|
beginDownload() {
|
||||||
console.log('Begin download...')
|
|
||||||
if (getSettings().libraryPath == undefined) {
|
if (getSettings().libraryPath == undefined) {
|
||||||
this.failDownload(downloadErrors.libraryFolder())
|
this.failDownload(downloadErrors.libraryFolder())
|
||||||
} else {
|
} else {
|
||||||
@@ -75,7 +76,7 @@ export class FileDownloader {
|
|||||||
*/
|
*/
|
||||||
private requestDownload(cookieHeader?: string) {
|
private requestDownload(cookieHeader?: string) {
|
||||||
this.callbacks.requestSent()
|
this.callbacks.requestSent()
|
||||||
const req = needle.get(this.url, {
|
this.req = needle.get(this.url, {
|
||||||
'follow_max': 10,
|
'follow_max': 10,
|
||||||
'open_timeout': 5000,
|
'open_timeout': 5000,
|
||||||
'headers': Object.assign({
|
'headers': Object.assign({
|
||||||
@@ -86,7 +87,7 @@ export class FileDownloader {
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
req.on('timeout', this.cancelable((type: string) => {
|
this.req.on('timeout', this.cancelable((type: string) => {
|
||||||
this.retryCount++
|
this.retryCount++
|
||||||
if (this.retryCount <= this.RETRY_MAX) {
|
if (this.retryCount <= this.RETRY_MAX) {
|
||||||
console.log(`TIMEOUT: Retry attempt ${this.retryCount}...`)
|
console.log(`TIMEOUT: Retry attempt ${this.retryCount}...`)
|
||||||
@@ -96,20 +97,20 @@ export class FileDownloader {
|
|||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
|
|
||||||
req.on('err', this.cancelable((err: Error) => {
|
this.req.on('err', this.cancelable((err: Error) => {
|
||||||
this.failDownload(downloadErrors.connectionError(err))
|
this.failDownload(downloadErrors.connectionError(err))
|
||||||
}))
|
}))
|
||||||
|
|
||||||
req.on('header', this.cancelable((statusCode, headers: Headers) => {
|
this.req.on('header', this.cancelable((statusCode, headers: Headers) => {
|
||||||
if (statusCode != 200) {
|
if (statusCode != 200) {
|
||||||
this.failDownload(downloadErrors.responseError(statusCode))
|
this.failDownload(downloadErrors.responseError(statusCode))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (headers['content-type'].startsWith('text/html')) {
|
if (headers['content-type'].startsWith('text/html')) {
|
||||||
this.handleHTMLResponse(req, headers['set-cookie'])
|
this.handleHTMLResponse(headers['set-cookie'])
|
||||||
} else {
|
} else {
|
||||||
this.handleDownloadResponse(req)
|
this.handleDownloadResponse()
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
@@ -117,14 +118,12 @@ export class FileDownloader {
|
|||||||
/**
|
/**
|
||||||
* A Google Drive HTML response to a download request usually means this is the "file too large to scan for viruses" warning.
|
* A Google Drive HTML response to a download request usually means this is the "file too large to scan for viruses" warning.
|
||||||
* This function sends the request that results from clicking "download anyway", or generates an error if it can't be found.
|
* This function sends the request that results from clicking "download anyway", or generates an error if it can't be found.
|
||||||
* @param req The download request.
|
|
||||||
* @param cookieHeader The "cookie=" header of this request.
|
* @param cookieHeader The "cookie=" header of this request.
|
||||||
*/
|
*/
|
||||||
private handleHTMLResponse(req: NodeJS.ReadableStream, cookieHeader: string) {
|
private handleHTMLResponse(cookieHeader: string) {
|
||||||
console.log('HTML Response...')
|
|
||||||
let virusScanHTML = ''
|
let virusScanHTML = ''
|
||||||
req.on('data', this.cancelable(data => virusScanHTML += data))
|
this.req.on('data', this.cancelable(data => virusScanHTML += data))
|
||||||
req.on('done', this.cancelable((err: Error) => {
|
this.req.on('done', this.cancelable((err: Error) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
this.failDownload(downloadErrors.connectionError(err))
|
this.failDownload(downloadErrors.connectionError(err))
|
||||||
} else {
|
} else {
|
||||||
@@ -149,21 +148,20 @@ export class FileDownloader {
|
|||||||
* Pipes the data from a download response to `this.fullPath`.
|
* Pipes the data from a download response to `this.fullPath`.
|
||||||
* @param req The download request.
|
* @param req The download request.
|
||||||
*/
|
*/
|
||||||
private handleDownloadResponse(req: NodeJS.ReadableStream) {
|
private handleDownloadResponse() {
|
||||||
console.log('Download response...')
|
|
||||||
this.callbacks.downloadProgress(0)
|
this.callbacks.downloadProgress(0)
|
||||||
let downloadedSize = 0
|
let downloadedSize = 0
|
||||||
req.pipe(createWriteStream(this.fullPath))
|
this.req.pipe(createWriteStream(this.fullPath))
|
||||||
req.on('data', this.cancelable((data) => {
|
this.req.on('data', this.cancelable((data) => {
|
||||||
downloadedSize += data.length
|
downloadedSize += data.length
|
||||||
this.callbacks.downloadProgress(downloadedSize)
|
this.callbacks.downloadProgress(downloadedSize)
|
||||||
}))
|
}))
|
||||||
|
|
||||||
req.on('err', this.cancelable((err: Error) => {
|
this.req.on('err', this.cancelable((err: Error) => {
|
||||||
this.failDownload(downloadErrors.connectionError(err))
|
this.failDownload(downloadErrors.connectionError(err))
|
||||||
}))
|
}))
|
||||||
|
|
||||||
req.on('end', this.cancelable(() => {
|
this.req.on('end', this.cancelable(() => {
|
||||||
this.callbacks.complete()
|
this.callbacks.complete()
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
@@ -181,6 +179,9 @@ export class FileDownloader {
|
|||||||
cancelDownload() {
|
cancelDownload() {
|
||||||
this.wasCanceled = true
|
this.wasCanceled = true
|
||||||
googleTimer.cancelTimer() // Prevents timer from trying to activate a download and resetting
|
googleTimer.cancelTimer() // Prevents timer from trying to activate a download and resetting
|
||||||
|
if (this.req) {
|
||||||
|
// TODO: destroy request
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -17,14 +17,14 @@ type EventCallback = {
|
|||||||
type Callbacks = { [E in keyof EventCallback]: EventCallback[E] }
|
type Callbacks = { [E in keyof EventCallback]: EventCallback[E] }
|
||||||
|
|
||||||
const transferErrors = {
|
const transferErrors = {
|
||||||
readError: (err: NodeJS.ErrnoException) => fsError(err, 'Failed to read file'),
|
readError: (err: NodeJS.ErrnoException) => fsError(err, 'Failed to read file.'),
|
||||||
deleteError: (err: NodeJS.ErrnoException) => fsError(err, 'Failed to delete file'),
|
deleteError: (err: NodeJS.ErrnoException) => fsError(err, 'Failed to delete file.'),
|
||||||
rimrafError: (err: NodeJS.ErrnoException) => fsError(err, 'Failed to delete folder'),
|
rimrafError: (err: NodeJS.ErrnoException) => fsError(err, 'Failed to delete folder.'),
|
||||||
mvError: (err: NodeJS.ErrnoException) => fsError(err, 'Failed to move folder to library')
|
mvError: (err: NodeJS.ErrnoException) => fsError(err, `Failed to move folder to library.${err.code == 'EPERM' ? ' (does the chart already exist?)' : ''}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
function fsError(err: NodeJS.ErrnoException, description: string) {
|
function fsError(err: NodeJS.ErrnoException, description: string) {
|
||||||
return { header: `${description} (${err.code})`, body: `${err.name}: ${err.message}` }
|
return { header: description, body: `${err.name}: ${err.message}` }
|
||||||
}
|
}
|
||||||
|
|
||||||
export class FileTransfer {
|
export class FileTransfer {
|
||||||
|
|||||||
@@ -76,6 +76,7 @@ export type IPCEmitEvents = {
|
|||||||
'download': Download
|
'download': Download
|
||||||
'download-updated': DownloadProgress
|
'download-updated': DownloadProgress
|
||||||
'set-settings': Settings
|
'set-settings': Settings
|
||||||
|
'queue-updated': number[]
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user