mirror of
https://github.com/Myxelium/Bridge-Multi.git
synced 2026-04-11 14:19:38 +00:00
Cancel, Retry, and Warning download UI
This commit is contained in:
247
package-lock.json
generated
247
package-lock.json
generated
@@ -10,33 +10,33 @@
|
|||||||
"integrity": "sha512-GLyWIFBbGvpKPGo55JyRZAo4lVbnBiD52cKlw/0Vt+wnmKvWJkpZvsjVoaIolyBXDeAQKSicRtqFNPem9w0WYA=="
|
"integrity": "sha512-GLyWIFBbGvpKPGo55JyRZAo4lVbnBiD52cKlw/0Vt+wnmKvWJkpZvsjVoaIolyBXDeAQKSicRtqFNPem9w0WYA=="
|
||||||
},
|
},
|
||||||
"@angular-devkit/architect": {
|
"@angular-devkit/architect": {
|
||||||
"version": "0.803.24",
|
"version": "0.803.25",
|
||||||
"resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.803.24.tgz",
|
"resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.803.25.tgz",
|
||||||
"integrity": "sha512-ONY/Ppzyvtb0tqgwnzQvlGlexb5nTyy58ljgL1aQLTO3cNTkpl4IQYUCTdvn61gGA+FWPAXMCCbNqOPZMsOZCQ==",
|
"integrity": "sha512-usV/zEncKCKQuF6AD3pRU6N5i5fbaAux/qZb+nbOz9/2G5jrXwe5sH+y3vxbgqB83e3LqusEQCTu7/tfg6LwZg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@angular-devkit/core": "8.3.24",
|
"@angular-devkit/core": "8.3.25",
|
||||||
"rxjs": "6.4.0"
|
"rxjs": "6.4.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@angular-devkit/build-angular": {
|
"@angular-devkit/build-angular": {
|
||||||
"version": "0.803.24",
|
"version": "0.803.25",
|
||||||
"resolved": "https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-0.803.24.tgz",
|
"resolved": "https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-0.803.25.tgz",
|
||||||
"integrity": "sha512-uA789spMVghXehwAhl5zK0loY/wfxblUiL+y21T24LMCJc15a9QX5dwbXH72ioHz7qdzb/agXk7AK+foc2/0Hw==",
|
"integrity": "sha512-WY0E7NgXuog3phhz5ZdutZPWQ9nbOr+omGN5KI1e8MZs1sJO4xkyaGRT8zOulkogkqJ2NboTBq3j9uSbZkcYeg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@angular-devkit/architect": "0.803.24",
|
"@angular-devkit/architect": "0.803.25",
|
||||||
"@angular-devkit/build-optimizer": "0.803.24",
|
"@angular-devkit/build-optimizer": "0.803.25",
|
||||||
"@angular-devkit/build-webpack": "0.803.24",
|
"@angular-devkit/build-webpack": "0.803.25",
|
||||||
"@angular-devkit/core": "8.3.24",
|
"@angular-devkit/core": "8.3.25",
|
||||||
"@babel/core": "7.8.3",
|
"@babel/core": "7.8.3",
|
||||||
"@babel/preset-env": "7.8.3",
|
"@babel/preset-env": "7.8.3",
|
||||||
"@ngtools/webpack": "8.3.24",
|
"@ngtools/webpack": "8.3.25",
|
||||||
"ajv": "6.10.2",
|
"ajv": "6.10.2",
|
||||||
"autoprefixer": "9.6.1",
|
"autoprefixer": "9.6.1",
|
||||||
"browserslist": "4.8.3",
|
"browserslist": "4.8.6",
|
||||||
"cacache": "12.0.2",
|
"cacache": "12.0.2",
|
||||||
"caniuse-lite": "1.0.30001019",
|
"caniuse-lite": "1.0.30001024",
|
||||||
"circular-dependency-plugin": "5.2.0",
|
"circular-dependency-plugin": "5.2.0",
|
||||||
"clean-css": "4.2.1",
|
"clean-css": "4.2.1",
|
||||||
"copy-webpack-plugin": "5.1.1",
|
"copy-webpack-plugin": "5.1.1",
|
||||||
@@ -81,12 +81,31 @@
|
|||||||
"webpack-sources": "1.4.3",
|
"webpack-sources": "1.4.3",
|
||||||
"webpack-subresource-integrity": "1.1.0-rc.6",
|
"webpack-subresource-integrity": "1.1.0-rc.6",
|
||||||
"worker-plugin": "3.2.0"
|
"worker-plugin": "3.2.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"browserslist": {
|
||||||
|
"version": "4.8.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.8.6.tgz",
|
||||||
|
"integrity": "sha512-ZHao85gf0eZ0ESxLfCp73GG9O/VTytYDIkIiZDlURppLTI9wErSM/5yAKEq6rcUdxBLjMELmrYUJGg5sxGKMHg==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"caniuse-lite": "^1.0.30001023",
|
||||||
|
"electron-to-chromium": "^1.3.341",
|
||||||
|
"node-releases": "^1.1.47"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"caniuse-lite": {
|
||||||
|
"version": "1.0.30001024",
|
||||||
|
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001024.tgz",
|
||||||
|
"integrity": "sha512-LubRSEPpOlKlhZw9wGlLHo8ZVj6ugGU3xGUfLPneNBledSd9lIM5cCGZ9Mz/mMCJUhEt4jZpYteZNVRdJw5FRA==",
|
||||||
|
"dev": true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@angular-devkit/build-optimizer": {
|
"@angular-devkit/build-optimizer": {
|
||||||
"version": "0.803.24",
|
"version": "0.803.25",
|
||||||
"resolved": "https://registry.npmjs.org/@angular-devkit/build-optimizer/-/build-optimizer-0.803.24.tgz",
|
"resolved": "https://registry.npmjs.org/@angular-devkit/build-optimizer/-/build-optimizer-0.803.25.tgz",
|
||||||
"integrity": "sha512-Z+d7M+WpBq7AWWRwbxzb1l9O9qkylxnDRKxXvq3Tzjn43g+2WyspE91dMyrg1ISc+p8jgX6xKSblRLvtWqpA8w==",
|
"integrity": "sha512-MiQimuEs8QeM3xo7bR3Yk1OWHHlp2pGCc2GLUMIcWhKqM+QjoRky0HoGoBazbznx292l+xjFjANvPEKbqJ2v7Q==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"loader-utils": "1.2.3",
|
"loader-utils": "1.2.3",
|
||||||
@@ -94,31 +113,23 @@
|
|||||||
"tslib": "1.10.0",
|
"tslib": "1.10.0",
|
||||||
"typescript": "3.5.3",
|
"typescript": "3.5.3",
|
||||||
"webpack-sources": "1.4.3"
|
"webpack-sources": "1.4.3"
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"typescript": {
|
|
||||||
"version": "3.5.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-3.5.3.tgz",
|
|
||||||
"integrity": "sha512-ACzBtm/PhXBDId6a6sDJfroT2pOWt/oOnk4/dElG5G33ZL776N3Y6/6bKZJBFpd+b05F3Ct9qDjMeJmRWtE2/g==",
|
|
||||||
"dev": true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@angular-devkit/build-webpack": {
|
"@angular-devkit/build-webpack": {
|
||||||
"version": "0.803.24",
|
"version": "0.803.25",
|
||||||
"resolved": "https://registry.npmjs.org/@angular-devkit/build-webpack/-/build-webpack-0.803.24.tgz",
|
"resolved": "https://registry.npmjs.org/@angular-devkit/build-webpack/-/build-webpack-0.803.25.tgz",
|
||||||
"integrity": "sha512-Bbd5KUGaE+edN0sp8K3azuqS/JTBmeWXIumdBEtqWyL6VsohX7fL+toJlSvRkj8lg02LVyozAFetXKnyaBkfCQ==",
|
"integrity": "sha512-WR7HWJIWL6TB3WHG7ZFn8s0z3WlojeQlod75UIKl5i+f4OU90kp8kxcoH5G6OCXu56x5w40oIi1ve5ljjWSJkw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@angular-devkit/architect": "0.803.24",
|
"@angular-devkit/architect": "0.803.25",
|
||||||
"@angular-devkit/core": "8.3.24",
|
"@angular-devkit/core": "8.3.25",
|
||||||
"rxjs": "6.4.0"
|
"rxjs": "6.4.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@angular-devkit/core": {
|
"@angular-devkit/core": {
|
||||||
"version": "8.3.24",
|
"version": "8.3.25",
|
||||||
"resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-8.3.24.tgz",
|
"resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-8.3.25.tgz",
|
||||||
"integrity": "sha512-xpT5yg+ddGDnifryBv2sRSYtq5F3iZIS+lN/K2AhhEa50B7Z+QaCVlEzoV/IfrGd6sLArdnKYwjLHFZ0LElUuw==",
|
"integrity": "sha512-l7Gqy1tMrTpRmPVlovcFX8UA3mtXRlgO8kcSsbJ9MKRKNTCcxlfsWEYY5igyDBUVh6ADkgSIu0nuk31ZGTe0lw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"ajv": "6.10.2",
|
"ajv": "6.10.2",
|
||||||
@@ -129,12 +140,12 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@angular-devkit/schematics": {
|
"@angular-devkit/schematics": {
|
||||||
"version": "8.3.24",
|
"version": "8.3.25",
|
||||||
"resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-8.3.24.tgz",
|
"resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-8.3.25.tgz",
|
||||||
"integrity": "sha512-HrwDCgw7i3GrNns0Ce5zStWkxBqlcLuDkMcLY6981jpvVzgXMIQ+YqDrJ2kD46xHh979ev7hhw1d6jwPXh85Xw==",
|
"integrity": "sha512-/p1MkfursfLy+JRGXlJGPEmX55lrFCsR/2khWAVXZcMaFR3QlR/b6/zvB8I2pHFfr0/XWnYTT/BsF7rJjO3RmA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@angular-devkit/core": "8.3.24",
|
"@angular-devkit/core": "8.3.25",
|
||||||
"rxjs": "6.4.0"
|
"rxjs": "6.4.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -153,16 +164,16 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@angular/cli": {
|
"@angular/cli": {
|
||||||
"version": "8.3.24",
|
"version": "8.3.25",
|
||||||
"resolved": "https://registry.npmjs.org/@angular/cli/-/cli-8.3.24.tgz",
|
"resolved": "https://registry.npmjs.org/@angular/cli/-/cli-8.3.25.tgz",
|
||||||
"integrity": "sha512-cUB6H+BAISMdaFsstcyvC+17hOV3ET4MaVgcmgT2cL7A4vMBRBxJ0cW4r3D9c6e7m4wipyJzOUESYoIHu0cp4A==",
|
"integrity": "sha512-CPJI5nnbBvvyBUFwOHfRXy/KVwsiYlcbDAeIk1klcjQjbVFYZbnY0iAhNupy9j7rPQhb7jle5oslU3TLfbqOTQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@angular-devkit/architect": "0.803.24",
|
"@angular-devkit/architect": "0.803.25",
|
||||||
"@angular-devkit/core": "8.3.24",
|
"@angular-devkit/core": "8.3.25",
|
||||||
"@angular-devkit/schematics": "8.3.24",
|
"@angular-devkit/schematics": "8.3.25",
|
||||||
"@schematics/angular": "8.3.24",
|
"@schematics/angular": "8.3.25",
|
||||||
"@schematics/update": "0.803.24",
|
"@schematics/update": "0.803.25",
|
||||||
"@yarnpkg/lockfile": "1.1.0",
|
"@yarnpkg/lockfile": "1.1.0",
|
||||||
"ansi-colors": "4.1.1",
|
"ansi-colors": "4.1.1",
|
||||||
"debug": "^4.1.1",
|
"debug": "^4.1.1",
|
||||||
@@ -1082,9 +1093,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"caniuse-lite": {
|
"caniuse-lite": {
|
||||||
"version": "1.0.30001023",
|
"version": "1.0.30001027",
|
||||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001023.tgz",
|
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001027.tgz",
|
||||||
"integrity": "sha512-C5TDMiYG11EOhVOA62W1p3UsJ2z4DsHtMBQtjzp3ZsUglcQn62WOUgW0y795c7A5uZ+GCEIvzkMatLIlAsbNTA==",
|
"integrity": "sha512-7xvKeErvXZFtUItTHgNtLgS9RJpVnwBlWX8jSo/BO8VsF6deszemZSkJJJA1KOKrXuzZH4WALpAJdq5EyfgMLg==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"semver": {
|
"semver": {
|
||||||
@@ -1216,9 +1227,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"caniuse-lite": {
|
"caniuse-lite": {
|
||||||
"version": "1.0.30001023",
|
"version": "1.0.30001027",
|
||||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001023.tgz",
|
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001027.tgz",
|
||||||
"integrity": "sha512-C5TDMiYG11EOhVOA62W1p3UsJ2z4DsHtMBQtjzp3ZsUglcQn62WOUgW0y795c7A5uZ+GCEIvzkMatLIlAsbNTA==",
|
"integrity": "sha512-7xvKeErvXZFtUItTHgNtLgS9RJpVnwBlWX8jSo/BO8VsF6deszemZSkJJJA1KOKrXuzZH4WALpAJdq5EyfgMLg==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"semver": {
|
"semver": {
|
||||||
@@ -2012,9 +2023,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@electron/get": {
|
"@electron/get": {
|
||||||
"version": "1.7.2",
|
"version": "1.7.6",
|
||||||
"resolved": "https://registry.npmjs.org/@electron/get/-/get-1.7.2.tgz",
|
"resolved": "https://registry.npmjs.org/@electron/get/-/get-1.7.6.tgz",
|
||||||
"integrity": "sha512-LSE4LZGMjGS9TloDx0yO44D2UTbaeKRk+QjlhWLiQlikV6J4spgDCjb6z4YIcqmPAwNzlNCnWF4dubytwI+ATA==",
|
"integrity": "sha512-zlNikt6ziVLNcm4lly1L4y62fJd/eYpEBjF5DiV/VAQq2vdPjH4sbUphXt9upmHz86lAhAj8g9lTnWrxJ/KBZw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"debug": "^4.1.1",
|
"debug": "^4.1.1",
|
||||||
@@ -2080,12 +2091,12 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"@ngtools/webpack": {
|
"@ngtools/webpack": {
|
||||||
"version": "8.3.24",
|
"version": "8.3.25",
|
||||||
"resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-8.3.24.tgz",
|
"resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-8.3.25.tgz",
|
||||||
"integrity": "sha512-OpR7t/99qNOpADayCuM67agBVdYkdbFyEEcOLaDFYh3LsefHOSSxtAGv8M77e7dguvtaljHTiVkMxgcXFsZM0Q==",
|
"integrity": "sha512-yHvgxXUXlgdWijtzcRjTaUqzK+6TVK/8p7PreBR00GsLxhl4U1jQSC6yDaZUCjOaEkiczFWl4hEuC4wTU/hLdg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@angular-devkit/core": "8.3.24",
|
"@angular-devkit/core": "8.3.25",
|
||||||
"enhanced-resolve": "4.1.0",
|
"enhanced-resolve": "4.1.0",
|
||||||
"rxjs": "6.4.0",
|
"rxjs": "6.4.0",
|
||||||
"tree-kill": "1.2.2",
|
"tree-kill": "1.2.2",
|
||||||
@@ -2219,23 +2230,23 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@schematics/angular": {
|
"@schematics/angular": {
|
||||||
"version": "8.3.24",
|
"version": "8.3.25",
|
||||||
"resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-8.3.24.tgz",
|
"resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-8.3.25.tgz",
|
||||||
"integrity": "sha512-0nf/LgMHAvhjWS97Pl3JGMqS9/4PI+C0+vJoAo6D7ax8Fb+wuY5uD6Pb7ZqaZALlEnqTgE+FBQ1K8VBVbuwKbA==",
|
"integrity": "sha512-/vEPtE+fvgsWPml/MVqzmlGPBujadPPNwaTuuj5Uz1aVcKeEYzLkbN8YQOpml4vxZHCF8RDwNdGiU4SZg63Jfg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@angular-devkit/core": "8.3.24",
|
"@angular-devkit/core": "8.3.25",
|
||||||
"@angular-devkit/schematics": "8.3.24"
|
"@angular-devkit/schematics": "8.3.25"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@schematics/update": {
|
"@schematics/update": {
|
||||||
"version": "0.803.24",
|
"version": "0.803.25",
|
||||||
"resolved": "https://registry.npmjs.org/@schematics/update/-/update-0.803.24.tgz",
|
"resolved": "https://registry.npmjs.org/@schematics/update/-/update-0.803.25.tgz",
|
||||||
"integrity": "sha512-NvCKn3QfpRjx1EzL56q9IC9fRtDXZP4bMGs/2tj+wtdBNHgm6ZJMJ9qc4mGeztKGbDFLmnX3Xz0XawAl+KeYzQ==",
|
"integrity": "sha512-VIlqhJsCStA3aO4llxZ7lAOvQUqppyZdrEO7f/ApIJmuofPQTkO5Hx21tnv0dyExwoqPCSIHzEu4Tmc0/TWM1A==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@angular-devkit/core": "8.3.24",
|
"@angular-devkit/core": "8.3.25",
|
||||||
"@angular-devkit/schematics": "8.3.24",
|
"@angular-devkit/schematics": "8.3.25",
|
||||||
"@yarnpkg/lockfile": "1.1.0",
|
"@yarnpkg/lockfile": "1.1.0",
|
||||||
"ini": "1.3.5",
|
"ini": "1.3.5",
|
||||||
"pacote": "9.5.5",
|
"pacote": "9.5.5",
|
||||||
@@ -2328,9 +2339,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@types/node": {
|
"@types/node": {
|
||||||
"version": "8.9.5",
|
"version": "11.15.0",
|
||||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-8.9.5.tgz",
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-11.15.0.tgz",
|
||||||
"integrity": "sha512-jRHfWsvyMtXdbhnz5CVHxaBgnV6duZnPlQuRSo/dm/GnmikNcmZhxIES4E9OZjUmQ8C+HCl4KJux+cXN/ErGDQ=="
|
"integrity": "sha512-JRq4kw1GQZrF90YRrp3C1kIoioAEj9PweNF2Qgp/6XZYVgXPl7OWKdggFNtRxlBPyl40Fz/bOhCnXuKMFaJ06w=="
|
||||||
},
|
},
|
||||||
"@types/source-list-map": {
|
"@types/source-list-map": {
|
||||||
"version": "0.1.2",
|
"version": "0.1.2",
|
||||||
@@ -2363,12 +2374,12 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@typescript-eslint/eslint-plugin": {
|
"@typescript-eslint/eslint-plugin": {
|
||||||
"version": "2.19.0",
|
"version": "2.19.2",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-2.19.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-2.19.2.tgz",
|
||||||
"integrity": "sha512-u7IcQ9qwsB6U806LupZmINRnQjC+RJyv36sV/ugaFWMHTbFm/hlLTRx3gGYJgHisxcGSTnf+I/fPDieRMhPSQQ==",
|
"integrity": "sha512-HX2qOq2GOV04HNrmKnTpSIpHjfl7iwdXe3u/Nvt+/cpmdvzYvY0NHSiTkYN257jHnq4OM/yo+OsFgati+7LqJA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@typescript-eslint/experimental-utils": "2.19.0",
|
"@typescript-eslint/experimental-utils": "2.19.2",
|
||||||
"eslint-utils": "^1.4.3",
|
"eslint-utils": "^1.4.3",
|
||||||
"functional-red-black-tree": "^1.0.1",
|
"functional-red-black-tree": "^1.0.1",
|
||||||
"regexpp": "^3.0.0",
|
"regexpp": "^3.0.0",
|
||||||
@@ -2387,13 +2398,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@typescript-eslint/experimental-utils": {
|
"@typescript-eslint/experimental-utils": {
|
||||||
"version": "2.19.0",
|
"version": "2.19.2",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-2.19.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-2.19.2.tgz",
|
||||||
"integrity": "sha512-zwpg6zEOPbhB3+GaQfufzlMUOO6GXCNZq6skk+b2ZkZAIoBhVoanWK255BS1g5x9bMwHpLhX0Rpn5Fc3NdCZdg==",
|
"integrity": "sha512-B88QuwT1wMJR750YvTJBNjMZwmiPpbmKYLm1yI7PCc3x0NariqPwqaPsoJRwU9DmUi0cd9dkhz1IqEnwfD+P1A==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@types/json-schema": "^7.0.3",
|
"@types/json-schema": "^7.0.3",
|
||||||
"@typescript-eslint/typescript-estree": "2.19.0",
|
"@typescript-eslint/typescript-estree": "2.19.2",
|
||||||
"eslint-scope": "^5.0.0"
|
"eslint-scope": "^5.0.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -2410,21 +2421,21 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@typescript-eslint/parser": {
|
"@typescript-eslint/parser": {
|
||||||
"version": "2.19.0",
|
"version": "2.19.2",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-2.19.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-2.19.2.tgz",
|
||||||
"integrity": "sha512-s0jZoxAWjHnuidbbN7aA+BFVXn4TCcxEVGPV8lWMxZglSs3NRnFFAlL+aIENNmzB2/1jUJuySi6GiM6uACPmpg==",
|
"integrity": "sha512-8uwnYGKqX9wWHGPGdLB9sk9+12sjcdqEEYKGgbS8A0IvYX59h01o8os5qXUHMq2na8vpDRaV0suTLM7S8wraTA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@types/eslint-visitor-keys": "^1.0.0",
|
"@types/eslint-visitor-keys": "^1.0.0",
|
||||||
"@typescript-eslint/experimental-utils": "2.19.0",
|
"@typescript-eslint/experimental-utils": "2.19.2",
|
||||||
"@typescript-eslint/typescript-estree": "2.19.0",
|
"@typescript-eslint/typescript-estree": "2.19.2",
|
||||||
"eslint-visitor-keys": "^1.1.0"
|
"eslint-visitor-keys": "^1.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@typescript-eslint/typescript-estree": {
|
"@typescript-eslint/typescript-estree": {
|
||||||
"version": "2.19.0",
|
"version": "2.19.2",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-2.19.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-2.19.2.tgz",
|
||||||
"integrity": "sha512-n6/Xa37k0jQdwpUszffi19AlNbVCR0sdvCs3DmSKMD7wBttKY31lhD2fug5kMD91B2qW4mQldaTEc1PEzvGu8w==",
|
"integrity": "sha512-Xu/qa0MDk6upQWqE4Qy2X16Xg8Vi32tQS2PR0AvnT/ZYS4YGDvtn2MStOh5y8Zy2mg4NuL06KUHlvCh95j9C6Q==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"debug": "^4.1.1",
|
"debug": "^4.1.1",
|
||||||
@@ -3572,9 +3583,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"boolean": {
|
"boolean": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/boolean/-/boolean-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/boolean/-/boolean-3.0.1.tgz",
|
||||||
"integrity": "sha512-OElxJ1lUSinuoUnkpOgLmxp0DC4ytEhODEL6QJU0NpxE/mI4rUSh8h1P1Wkvfi3xQEBcxXR2gBIPNYNuaFcAbQ==",
|
"integrity": "sha512-HRZPIjPcbwAVQvOTxR4YE3o8Xs98NqbbL1iEZDCz7CL8ql0Lt5iOyJFxfnAB0oFs8Oh02F/lLlg30Mexv46LjA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
@@ -4645,17 +4656,6 @@
|
|||||||
"ssri": "^6.0.1",
|
"ssri": "^6.0.1",
|
||||||
"unique-filename": "^1.1.1",
|
"unique-filename": "^1.1.1",
|
||||||
"y18n": "^4.0.0"
|
"y18n": "^4.0.0"
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"rimraf": {
|
|
||||||
"version": "2.7.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
|
|
||||||
"integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"glob": "^7.1.3"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"find-cache-dir": {
|
"find-cache-dir": {
|
||||||
@@ -4668,6 +4668,15 @@
|
|||||||
"make-dir": "^2.0.0",
|
"make-dir": "^2.0.0",
|
||||||
"pkg-dir": "^3.0.0"
|
"pkg-dir": "^3.0.0"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"rimraf": {
|
||||||
|
"version": "2.7.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
|
||||||
|
"integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"glob": "^7.1.3"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -5370,9 +5379,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"electron": {
|
"electron": {
|
||||||
"version": "7.1.11",
|
"version": "7.1.12",
|
||||||
"resolved": "https://registry.npmjs.org/electron/-/electron-7.1.11.tgz",
|
"resolved": "https://registry.npmjs.org/electron/-/electron-7.1.12.tgz",
|
||||||
"integrity": "sha512-YDXfnovKY+8iZ5ISQh1kRqYIRKbpOSxGXCx2WVxPFPutEQ7Q/Xzr3h4GePEY25/NXMytMfhKaAZAYjtWUm3r9Q==",
|
"integrity": "sha512-gOJxAlJX2UyCRRncKzKzHSZStDI6MdoDzsustTCzudoZx3vlst1kkIP0n5t3TWTNoKNY/ihRsYIpeu63ar1m/g==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@electron/get": "^1.0.1",
|
"@electron/get": "^1.0.1",
|
||||||
@@ -5381,9 +5390,9 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/node": {
|
"@types/node": {
|
||||||
"version": "12.12.26",
|
"version": "12.12.27",
|
||||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.26.tgz",
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.27.tgz",
|
||||||
"integrity": "sha512-UmUm94/QZvU5xLcUlNR8hA7Ac+fGpO1EG/a8bcWVz0P0LqtxFmun9Y2bbtuckwGboWJIT70DoWq1r3hb56n3DA==",
|
"integrity": "sha512-odQFl/+B9idbdS0e8IxDl2ia/LP8KZLXhV3BUeI98TrZp0uoIzQPhGd+5EtzHmT0SMOIaPd7jfz6pOHLWTtl7A==",
|
||||||
"dev": true
|
"dev": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -7782,9 +7791,9 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"semver": {
|
"semver": {
|
||||||
"version": "7.1.2",
|
"version": "7.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/semver/-/semver-7.1.3.tgz",
|
||||||
"integrity": "sha512-BJs9T/H8sEVHbeigqzIEo57Iu/3DG6c4QoqTfbQB3BPA4zgzAomh/Fk9E7QtjWQ8mx2dgA9YCfSF4y9k9bHNpQ==",
|
"integrity": "sha512-ekM0zfiA9SCBlsKa2X1hxyxiI4L3B6EbVJkkdgQXnSEEaHlGdvyodMruTiulSRWMMB4NeIuYNMC9rTKTz97GxA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"optional": true
|
"optional": true
|
||||||
}
|
}
|
||||||
@@ -9832,9 +9841,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"istanbul-lib-instrument": {
|
"istanbul-lib-instrument": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.1.tgz",
|
||||||
"integrity": "sha512-Nm4wVHdo7ZXSG30KjZ2Wl5SU/Bw7bDx1PdaiIFzEStdjs0H12mOTncn1GVYuqQSaZxpg87VGBRsVRPGD2cD1AQ==",
|
"integrity": "sha512-imIchxnodll7pvQBYOqUu88EufLCU56LMeFPZZM/fJZ1irYcYdqroaV+ACK1Ila8ls09iEYArp+nqyC6lW1Vfg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@babel/core": "^7.7.5",
|
"@babel/core": "^7.7.5",
|
||||||
@@ -10438,9 +10447,9 @@
|
|||||||
"integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M="
|
"integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M="
|
||||||
},
|
},
|
||||||
"loglevel": {
|
"loglevel": {
|
||||||
"version": "1.6.6",
|
"version": "1.6.7",
|
||||||
"resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.6.6.tgz",
|
"resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.6.7.tgz",
|
||||||
"integrity": "sha512-Sgr5lbboAUBo3eXCSPL4/KoVz3ROKquOjcctxmHIt+vol2DrqTQe3SwkKKuYhEiWB5kYa13YyopJ69deJ1irzQ==",
|
"integrity": "sha512-cY2eLFrQSAfVPhCgH1s7JI73tMbg9YC3v3+ZHVW67sBS7UxWzNEk/ZBbSfLykBWHp33dqqtOv82gjhKEi81T/A==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"longest": {
|
"longest": {
|
||||||
@@ -13127,9 +13136,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"rimraf": {
|
"rimraf": {
|
||||||
"version": "3.0.1",
|
"version": "3.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
|
||||||
"integrity": "sha512-IQ4ikL8SjBiEDZfk+DFVwqRK8md24RWMEJkdSlgNLkyyAImcjf8SWvU1qFMDOb4igBClbTQ/ugPqXcRwdFTxZw==",
|
"integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"glob": "^7.1.3"
|
"glob": "^7.1.3"
|
||||||
|
|||||||
18
package.json
18
package.json
@@ -16,13 +16,13 @@
|
|||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "run-p serve:angular serve:electron",
|
"start": "run-p serve:angular serve:electron",
|
||||||
|
"serve:electron": "wait-on http-get://localhost:4200/ && tsc -p tsconfig.electron.json && electron . --dev",
|
||||||
"lint": "ng lint",
|
"lint": "ng lint",
|
||||||
"clean": "rimraf dist release",
|
"clean": "rimraf dist release",
|
||||||
"build:windows": "ng build -c production && tsc -p tsconfig.electron.json && electron-builder build --windows",
|
"build:windows": "ng build -c production && tsc -p tsconfig.electron.json && electron-builder build --windows",
|
||||||
"build:mac": "ng build -c production && tsc -p tsconfig.electron.json && electron-builder build --mac",
|
"build:mac": "ng build -c production && tsc -p tsconfig.electron.json && electron-builder build --mac",
|
||||||
"build:linux": "ng build -c production && tsc -p tsconfig.electron.json && electron-builder build --linux",
|
"build:linux": "ng build -c production && tsc -p tsconfig.electron.json && electron-builder build --linux",
|
||||||
"serve:angular": "ng serve",
|
"serve:angular": "ng serve"
|
||||||
"serve:electron": "wait-on http-get://localhost:4200/ && tsc -p tsconfig.electron.json && electron . --dev"
|
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"7zip-bin": "^5.0.3",
|
"7zip-bin": "^5.0.3",
|
||||||
@@ -52,20 +52,20 @@
|
|||||||
"zone.js": "~0.9.1"
|
"zone.js": "~0.9.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@angular-devkit/build-angular": "~0.803.24",
|
"@angular-devkit/build-angular": "^0.803.25",
|
||||||
"@angular-eslint/builder": "0.0.1-alpha.18",
|
"@angular-eslint/builder": "0.0.1-alpha.18",
|
||||||
"@angular/cli": "~8.3.24",
|
"@angular/cli": "^8.3.25",
|
||||||
"@angular/compiler-cli": "~8.2.14",
|
"@angular/compiler-cli": "~8.2.14",
|
||||||
"@angular/language-service": "~8.2.14",
|
"@angular/language-service": "~8.2.14",
|
||||||
"@types/node": "~8.9.4",
|
"@types/node": "11.15.0",
|
||||||
"@typescript-eslint/eslint-plugin": "^2.19.0",
|
"@typescript-eslint/eslint-plugin": "^2.19.2",
|
||||||
"@typescript-eslint/parser": "^2.19.0",
|
"@typescript-eslint/parser": "^2.19.2",
|
||||||
"electron": "^7.1.11",
|
"electron": "^7.1.12",
|
||||||
"electron-builder": "^22.3.2",
|
"electron-builder": "^22.3.2",
|
||||||
"electron-reload": "^1.5.0",
|
"electron-reload": "^1.5.0",
|
||||||
"eslint": "^6.8.0",
|
"eslint": "^6.8.0",
|
||||||
"npm-run-all": "^4.1.5",
|
"npm-run-all": "^4.1.5",
|
||||||
"rimraf": "^3.0.1",
|
"rimraf": "^3.0.2",
|
||||||
"ts-node": "~7.0.0",
|
"ts-node": "~7.0.0",
|
||||||
"tslint": "~5.15.0",
|
"tslint": "~5.15.0",
|
||||||
"typescript": "~3.5.3",
|
"typescript": "~3.5.3",
|
||||||
|
|||||||
@@ -128,8 +128,8 @@ export class ChartSidebarComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onDownloadClicked() {
|
onDownloadClicked() {
|
||||||
this.downloadService.addDownload({
|
this.downloadService.addDownload(
|
||||||
versionID: this.selectedVersion.versionID,
|
this.selectedVersion.versionID, {
|
||||||
avTagName: this.selectedVersion.avTagName,
|
avTagName: this.selectedVersion.avTagName,
|
||||||
artist: this.songResult.artist,
|
artist: this.songResult.artist,
|
||||||
charter: this.selectedVersion.charters,
|
charter: this.selectedVersion.charters,
|
||||||
|
|||||||
@@ -1,9 +1,24 @@
|
|||||||
<div class="ui cards">
|
<div class="ui cards">
|
||||||
<div *ngFor="let download of downloads; trackBy:trackByVersionID" class="card">
|
<div *ngFor="let download of downloads; trackBy:trackByVersionID" class="card" [style.background-color]="getBackgroundColor(download)">
|
||||||
<div class="content">
|
<div class="content">
|
||||||
|
<i class="inside right floated close icon" (click)="cancelDownload(download.versionID)"></i>
|
||||||
<div class="header">{{download.title}}</div>
|
<div class="header">{{download.title}}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="content">
|
<div class="content">
|
||||||
|
<button
|
||||||
|
*ngIf="download.type == 'error'"
|
||||||
|
class="ui right floated labeled icon button"
|
||||||
|
(click)="retryDownload(download.versionID)">
|
||||||
|
<i class="redo icon"></i>
|
||||||
|
Retry
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
*ngIf="download.type == 'warning'"
|
||||||
|
class="ui right floated labeled icon button"
|
||||||
|
(click)="continueDownload(download.versionID)">
|
||||||
|
<i class="exclamation triangle icon"></i>
|
||||||
|
Download Anyway
|
||||||
|
</button>
|
||||||
<div class="header">{{download.header}}</div>
|
<div class="header">{{download.header}}</div>
|
||||||
<div class="description">{{download.description}}</div>
|
<div class="description">{{download.description}}</div>
|
||||||
<div appProgressBar [percent]="download.percent" class="ui progress">
|
<div appProgressBar [percent]="download.percent" class="ui progress">
|
||||||
|
|||||||
@@ -4,4 +4,8 @@
|
|||||||
|
|
||||||
.ui.progress {
|
.ui.progress {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
i.close.icon {
|
||||||
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import { Component, ChangeDetectorRef } from '@angular/core'
|
import { Component, ChangeDetectorRef } from '@angular/core'
|
||||||
import { Download } 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'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@@ -9,13 +9,15 @@ import { DownloadService } from '../../../../core/services/download.service'
|
|||||||
})
|
})
|
||||||
export class DownloadsModalComponent {
|
export class DownloadsModalComponent {
|
||||||
|
|
||||||
downloads: Download[] = []
|
downloads: DownloadProgress[] = []
|
||||||
|
|
||||||
constructor(downloadService: DownloadService, ref: ChangeDetectorRef) {
|
constructor(private downloadService: DownloadService, ref: ChangeDetectorRef) {
|
||||||
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) {
|
||||||
this.downloads.push(download)
|
this.downloads.push(download)
|
||||||
|
} else if (download.type == 'cancel') {
|
||||||
|
this.downloads.splice(index, 1)
|
||||||
} else {
|
} else {
|
||||||
this.downloads[index] = download
|
this.downloads[index] = download
|
||||||
}
|
}
|
||||||
@@ -23,7 +25,28 @@ export class DownloadsModalComponent {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
trackByVersionID(_index: number, item: Download) {
|
trackByVersionID(_index: number, item: DownloadProgress) {
|
||||||
return item.versionID
|
return item.versionID
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cancelDownload(versionID: number) {
|
||||||
|
this.downloadService.cancelDownload(versionID)
|
||||||
|
}
|
||||||
|
|
||||||
|
retryDownload(versionID: number) {
|
||||||
|
this.downloadService.retryDownload(versionID)
|
||||||
|
}
|
||||||
|
|
||||||
|
continueDownload(versionID: number) {
|
||||||
|
// TODO: test this
|
||||||
|
this.downloadService.continueDownload(versionID)
|
||||||
|
}
|
||||||
|
|
||||||
|
getBackgroundColor(download: DownloadProgress) {
|
||||||
|
switch(download.type) {
|
||||||
|
case 'good': return 'unset'
|
||||||
|
case 'warning': return 'yellow'
|
||||||
|
case 'error': return 'indianred'
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,6 +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 { Download, NewDownload } from '../../../electron/shared/interfaces/download.interface'
|
import { NewDownload, DownloadProgress } from '../../../electron/shared/interfaces/download.interface'
|
||||||
import * as _ from 'underscore'
|
import * as _ from 'underscore'
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
@@ -8,12 +8,24 @@ import * as _ from 'underscore'
|
|||||||
})
|
})
|
||||||
export class DownloadService {
|
export class DownloadService {
|
||||||
|
|
||||||
private downloadUpdatedEmitter = new EventEmitter<Download>()
|
private downloadUpdatedEmitter = new EventEmitter<DownloadProgress>()
|
||||||
private downloads: Download[] = []
|
private downloads: DownloadProgress[] = []
|
||||||
|
|
||||||
constructor(private electronService: ElectronService) { }
|
constructor(private electronService: ElectronService) { }
|
||||||
|
|
||||||
addDownload(newDownload: NewDownload) {
|
get downloadCount() {
|
||||||
|
return this.downloads.length
|
||||||
|
}
|
||||||
|
|
||||||
|
get totalPercent() {
|
||||||
|
let total = 0
|
||||||
|
for (const download of this.downloads) {
|
||||||
|
total += download.percent
|
||||||
|
}
|
||||||
|
return total / this.downloads.length
|
||||||
|
}
|
||||||
|
|
||||||
|
addDownload(versionID: number, newDownload: NewDownload) {
|
||||||
this.electronService.receiveIPC('download-updated', result => {
|
this.electronService.receiveIPC('download-updated', result => {
|
||||||
this.downloadUpdatedEmitter.emit(result)
|
this.downloadUpdatedEmitter.emit(result)
|
||||||
|
|
||||||
@@ -25,28 +37,26 @@ export class DownloadService {
|
|||||||
this.downloads[thisDownloadIndex] = result
|
this.downloads[thisDownloadIndex] = result
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
this.electronService.sendIPC('add-download', newDownload)
|
this.electronService.sendIPC('download', { action: 'add', versionID, data: newDownload })
|
||||||
}
|
}
|
||||||
|
|
||||||
onDownloadUpdated(callback: (download: Download) => void) {
|
onDownloadUpdated(callback: (download: DownloadProgress) => void) {
|
||||||
this.downloadUpdatedEmitter.subscribe(_.throttle(callback, 30))
|
this.downloadUpdatedEmitter.subscribe(_.throttle(callback, 30))
|
||||||
}
|
}
|
||||||
|
|
||||||
get downloadCount() {
|
cancelDownload(versionID: number) {
|
||||||
return this.downloads.length
|
|
||||||
}
|
|
||||||
|
|
||||||
removeDownload(versionID: number) {
|
|
||||||
const removedDownload = this.downloads.find(download => download.versionID == versionID)
|
const removedDownload = this.downloads.find(download => download.versionID == versionID)
|
||||||
this.downloads = this.downloads.filter(download => download.versionID != versionID)
|
this.downloads = this.downloads.filter(download => download.versionID != versionID)
|
||||||
|
removedDownload.type = 'cancel'
|
||||||
this.downloadUpdatedEmitter.emit(removedDownload)
|
this.downloadUpdatedEmitter.emit(removedDownload)
|
||||||
|
this.electronService.sendIPC('download', { action: 'cancel', versionID })
|
||||||
}
|
}
|
||||||
|
|
||||||
get totalPercent() {
|
retryDownload(versionID: number) {
|
||||||
let total = 0
|
this.electronService.sendIPC('download', { action: 'retry', versionID })
|
||||||
for (const download of this.downloads) {
|
}
|
||||||
total += download.percent
|
|
||||||
}
|
continueDownload(versionID: number) {
|
||||||
return total / this.downloads.length
|
this.electronService.sendIPC('download', { action: 'continue', versionID })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4,7 +4,7 @@ import { createHash, randomBytes as _randomBytes } from 'crypto'
|
|||||||
import { tempPath } from '../../shared/Paths'
|
import { tempPath } from '../../shared/Paths'
|
||||||
import { promisify } from 'util'
|
import { promisify } from 'util'
|
||||||
import { join } from 'path'
|
import { join } from 'path'
|
||||||
import { Download, NewDownload } from '../../shared/interfaces/download.interface'
|
import { Download, NewDownload, DownloadProgress } from '../../shared/interfaces/download.interface'
|
||||||
import { emitIPCEvent } from '../../main'
|
import { emitIPCEvent } from '../../main'
|
||||||
import { mkdir as _mkdir } from 'fs'
|
import { mkdir as _mkdir } from 'fs'
|
||||||
import { FileExtractor } from './FileExtractor'
|
import { FileExtractor } from './FileExtractor'
|
||||||
@@ -13,16 +13,29 @@ import { sanitizeFilename, interpolate } from '../../shared/UtilFunctions'
|
|||||||
const randomBytes = promisify(_randomBytes)
|
const randomBytes = promisify(_randomBytes)
|
||||||
const mkdir = promisify(_mkdir)
|
const mkdir = promisify(_mkdir)
|
||||||
|
|
||||||
export class AddDownloadHandler implements IPCEmitHandler<'add-download'> {
|
export class DownloadHandler implements IPCEmitHandler<'download'> {
|
||||||
event: 'add-download' = 'add-download'
|
event: 'download' = 'download'
|
||||||
|
|
||||||
async handler(data: NewDownload) {
|
// TODO: replace needle with got (for cancel() method) (if before-headers event is possible?)
|
||||||
const download: Download = {
|
|
||||||
|
downloadCallbacks: { [versionID: number]: { cancel: () => void, retry: () => void, continue: () => void } } = {}
|
||||||
|
|
||||||
|
async handler(data: Download) {
|
||||||
|
switch (data.action) {
|
||||||
|
case 'cancel': this.downloadCallbacks[data.versionID].cancel(); return
|
||||||
|
case 'retry': this.downloadCallbacks[data.versionID].retry(); return
|
||||||
|
case 'continue': this.downloadCallbacks[data.versionID].continue(); return
|
||||||
|
case 'add': this.downloadCallbacks[data.versionID] = { cancel: () => { }, retry: () => { }, continue: () => { } }
|
||||||
|
}
|
||||||
|
|
||||||
|
// data.action == add; data.data should be defined
|
||||||
|
const download: DownloadProgress = {
|
||||||
versionID: data.versionID,
|
versionID: data.versionID,
|
||||||
title: `${data.avTagName} - ${data.artist}`,
|
title: `${data.data.avTagName} - ${data.data.artist}`,
|
||||||
header: '',
|
header: '',
|
||||||
description: '',
|
description: '',
|
||||||
percent: 0
|
percent: 0,
|
||||||
|
type: 'good'
|
||||||
}
|
}
|
||||||
const randomString = (await randomBytes(5)).toString('hex')
|
const randomString = (await randomBytes(5)).toString('hex')
|
||||||
const chartPath = join(tempPath, `chart_${randomString}`)
|
const chartPath = join(tempPath, `chart_${randomString}`)
|
||||||
@@ -30,17 +43,19 @@ export class AddDownloadHandler implements IPCEmitHandler<'add-download'> {
|
|||||||
|
|
||||||
let allFilesProgress = 0
|
let allFilesProgress = 0
|
||||||
// Only iterate over the keys in data.links that have link values (not hashes)
|
// Only iterate over the keys in data.links that have link values (not hashes)
|
||||||
const fileKeys = Object.keys(data.links).filter(link => data.links[link].includes('.'))
|
const fileKeys = Object.keys(data.data.links).filter(link => data.data.links[link].includes('.'))
|
||||||
const individualFileProgressPortion = 80 / fileKeys.length
|
const individualFileProgressPortion = 80 / fileKeys.length
|
||||||
for (let i = 0; i < fileKeys.length; i++) {
|
for (let i = 0; i < fileKeys.length; i++) {
|
||||||
const typeHash = createHash('md5').update(data.links[fileKeys[i]]).digest('hex')
|
const typeHash = createHash('md5').update(data.data.links[fileKeys[i]]).digest('hex')
|
||||||
const downloader = new FileDownloader(data.links[fileKeys[i]], chartPath, data.links[typeHash])
|
const downloader = new FileDownloader(data.data.links[fileKeys[i]], chartPath, data.data.links[typeHash])
|
||||||
|
this.downloadCallbacks[data.versionID].cancel = () => downloader.cancelDownload() // Make cancel button cancel this download
|
||||||
let fileProgress = 0
|
let fileProgress = 0
|
||||||
|
|
||||||
let waitTime: number
|
let waitTime: number
|
||||||
downloader.on('wait', (_waitTime) => {
|
downloader.on('wait', (_waitTime) => {
|
||||||
download.header = `[${fileKeys[i]}] (file ${i + 1}/${fileKeys.length})`
|
download.header = `[${fileKeys[i]}] (file ${i + 1}/${fileKeys.length})`
|
||||||
download.description = `Waiting for Google rate limit... (${_waitTime}s)`
|
download.description = `Waiting for Google rate limit... (${_waitTime}s)`
|
||||||
|
download.type = 'good'
|
||||||
waitTime = _waitTime
|
waitTime = _waitTime
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -48,6 +63,7 @@ export class AddDownloadHandler implements IPCEmitHandler<'add-download'> {
|
|||||||
download.description = `Waiting for Google rate limit... (${secondsRemaining}s)`
|
download.description = `Waiting for Google rate limit... (${secondsRemaining}s)`
|
||||||
fileProgress = interpolate(secondsRemaining, waitTime, 0, 0, individualFileProgressPortion / 2)
|
fileProgress = interpolate(secondsRemaining, waitTime, 0, 0, individualFileProgressPortion / 2)
|
||||||
download.percent = allFilesProgress + fileProgress
|
download.percent = allFilesProgress + fileProgress
|
||||||
|
download.type = 'good'
|
||||||
emitIPCEvent('download-updated', download)
|
emitIPCEvent('download-updated', download)
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -55,13 +71,15 @@ export class AddDownloadHandler implements IPCEmitHandler<'add-download'> {
|
|||||||
download.description = `Sending request...`
|
download.description = `Sending request...`
|
||||||
fileProgress = individualFileProgressPortion / 2
|
fileProgress = individualFileProgressPortion / 2
|
||||||
download.percent = allFilesProgress + fileProgress
|
download.percent = allFilesProgress + fileProgress
|
||||||
|
download.type = 'good'
|
||||||
emitIPCEvent('download-updated', download)
|
emitIPCEvent('download-updated', download)
|
||||||
})
|
})
|
||||||
|
|
||||||
downloader.on('warning', (continueAnyway) => {
|
downloader.on('warning', (continueAnyway) => {
|
||||||
download.description = 'WARNING'
|
download.description = 'WARNING'
|
||||||
|
this.downloadCallbacks[data.versionID].continue = continueAnyway
|
||||||
|
download.type = 'warning'
|
||||||
emitIPCEvent('download-updated', download)
|
emitIPCEvent('download-updated', download)
|
||||||
//TODO: continue anyway
|
|
||||||
})
|
})
|
||||||
|
|
||||||
let filesize = -1
|
let filesize = -1
|
||||||
@@ -73,6 +91,7 @@ export class AddDownloadHandler implements IPCEmitHandler<'add-download'> {
|
|||||||
} else {
|
} else {
|
||||||
download.description = `Downloading... (0 MB)`
|
download.description = `Downloading... (0 MB)`
|
||||||
}
|
}
|
||||||
|
download.type = 'good'
|
||||||
emitIPCEvent('download-updated', download)
|
emitIPCEvent('download-updated', download)
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -85,14 +104,16 @@ export class AddDownloadHandler implements IPCEmitHandler<'add-download'> {
|
|||||||
download.description = `Downloading... (${Math.round(bytesDownloaded / 1e+5) / 10} MB)`
|
download.description = `Downloading... (${Math.round(bytesDownloaded / 1e+5) / 10} MB)`
|
||||||
download.percent = allFilesProgress + fileProgress
|
download.percent = allFilesProgress + fileProgress
|
||||||
}
|
}
|
||||||
|
download.type = 'good'
|
||||||
emitIPCEvent('download-updated', download)
|
emitIPCEvent('download-updated', download)
|
||||||
})
|
})
|
||||||
|
|
||||||
downloader.on('error', (error, retry) => {
|
downloader.on('error', (error, retry) => {
|
||||||
download.header = error.header
|
download.header = error.header
|
||||||
download.description = error.body
|
download.description = error.body
|
||||||
|
download.type = 'error'
|
||||||
|
this.downloadCallbacks[data.versionID].retry = retry
|
||||||
emitIPCEvent('download-updated', download)
|
emitIPCEvent('download-updated', download)
|
||||||
// TODO: retry
|
|
||||||
})
|
})
|
||||||
|
|
||||||
// Wait for the 'complete' event before moving on to another file download
|
// Wait for the 'complete' event before moving on to another file download
|
||||||
@@ -107,14 +128,16 @@ export class AddDownloadHandler implements IPCEmitHandler<'add-download'> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const destinationFolderName = sanitizeFilename(`${data.artist} - ${data.avTagName} (${data.charter})`)
|
const destinationFolderName = sanitizeFilename(`${data.data.artist} - ${data.data.avTagName} (${data.data.charter})`)
|
||||||
const extractor = new FileExtractor(chartPath, fileKeys.includes('archive'), destinationFolderName)
|
const extractor = new FileExtractor(chartPath, fileKeys.includes('archive'), destinationFolderName)
|
||||||
|
this.downloadCallbacks[data.versionID].cancel = () => extractor.cancelExtract()
|
||||||
|
|
||||||
let archive = ''
|
let archive = ''
|
||||||
extractor.on('extract', (filename) => {
|
extractor.on('extract', (filename) => {
|
||||||
archive = filename
|
archive = filename
|
||||||
download.header = `[${archive}]`
|
download.header = `[${archive}]`
|
||||||
download.description = `Extracting...`
|
download.description = `Extracting...`
|
||||||
|
download.type = 'good'
|
||||||
emitIPCEvent('download-updated', download)
|
emitIPCEvent('download-updated', download)
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -122,6 +145,7 @@ export class AddDownloadHandler implements IPCEmitHandler<'add-download'> {
|
|||||||
download.header = `[${archive}] (${filecount} file${filecount == 1 ? '' : 's'} extracted)`
|
download.header = `[${archive}] (${filecount} file${filecount == 1 ? '' : 's'} extracted)`
|
||||||
download.description = `Extracting... (${percent}%)`
|
download.description = `Extracting... (${percent}%)`
|
||||||
download.percent = interpolate(percent, 0, 100, 80, 95)
|
download.percent = interpolate(percent, 0, 100, 80, 95)
|
||||||
|
download.type = 'good'
|
||||||
emitIPCEvent('download-updated', download)
|
emitIPCEvent('download-updated', download)
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -129,6 +153,7 @@ export class AddDownloadHandler implements IPCEmitHandler<'add-download'> {
|
|||||||
download.header = `Moving files to library folder...`
|
download.header = `Moving files to library folder...`
|
||||||
download.description = filepath
|
download.description = filepath
|
||||||
download.percent = 95
|
download.percent = 95
|
||||||
|
download.type = 'good'
|
||||||
emitIPCEvent('download-updated', download)
|
emitIPCEvent('download-updated', download)
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -136,14 +161,16 @@ export class AddDownloadHandler implements IPCEmitHandler<'add-download'> {
|
|||||||
download.header = `Download complete.`
|
download.header = `Download complete.`
|
||||||
download.description = filepath
|
download.description = filepath
|
||||||
download.percent = 100
|
download.percent = 100
|
||||||
|
download.type = 'good'
|
||||||
emitIPCEvent('download-updated', download)
|
emitIPCEvent('download-updated', download)
|
||||||
})
|
})
|
||||||
|
|
||||||
extractor.on('error', (error, retry) => {
|
extractor.on('error', (error, retry) => {
|
||||||
download.header = error.header
|
download.header = error.header
|
||||||
download.description = error.body
|
download.description = error.body
|
||||||
|
download.type = 'error'
|
||||||
|
this.downloadCallbacks[data.versionID].retry = retry
|
||||||
emitIPCEvent('download-updated', download)
|
emitIPCEvent('download-updated', download)
|
||||||
// TODO: retry
|
|
||||||
})
|
})
|
||||||
|
|
||||||
extractor.beginExtract()
|
extractor.beginExtract()
|
||||||
@@ -19,12 +19,13 @@ export type DownloadError = { header: string, body: string }
|
|||||||
|
|
||||||
export class FileDownloader {
|
export class FileDownloader {
|
||||||
private RATE_LIMIT_DELAY: number
|
private RATE_LIMIT_DELAY: number
|
||||||
private readonly RETRY_MAX = 3
|
private readonly RETRY_MAX = 2
|
||||||
private static waitTime = 0
|
private static waitTime = 0
|
||||||
private static clock: NodeJS.Timer
|
private static clock: NodeJS.Timer
|
||||||
|
|
||||||
private callbacks = {} as Callbacks
|
private callbacks = {} as Callbacks
|
||||||
private retryCount: number
|
private retryCount: number
|
||||||
|
private wasCanceled = false
|
||||||
|
|
||||||
constructor(private url: string, private destinationFolder: string, private expectedHash?: string) {
|
constructor(private url: string, private destinationFolder: string, private expectedHash?: string) {
|
||||||
if (FileDownloader.clock == undefined) {
|
if (FileDownloader.clock == undefined) {
|
||||||
@@ -60,6 +61,7 @@ export class FileDownloader {
|
|||||||
}
|
}
|
||||||
this.callbacks.wait(waitTime)
|
this.callbacks.wait(waitTime)
|
||||||
const clock = setInterval(() => {
|
const clock = setInterval(() => {
|
||||||
|
if (this.wasCanceled) { clearInterval(clock); return } // CANCEL POINT
|
||||||
waitTime--
|
waitTime--
|
||||||
this.callbacks.waitProgress(waitTime)
|
this.callbacks.waitProgress(waitTime)
|
||||||
if (waitTime <= 0) {
|
if (waitTime <= 0) {
|
||||||
@@ -75,10 +77,12 @@ export class FileDownloader {
|
|||||||
* @param cookieHeader the "cookie=" header to include this request.
|
* @param cookieHeader the "cookie=" header to include this request.
|
||||||
*/
|
*/
|
||||||
private requestDownload(cookieHeader?: string) {
|
private requestDownload(cookieHeader?: string) {
|
||||||
|
if (this.wasCanceled) { return } // CANCEL POINT
|
||||||
this.callbacks.request()
|
this.callbacks.request()
|
||||||
let uuid = generateUUID()
|
let uuid = generateUUID()
|
||||||
const req = needle.get(this.url, {
|
const req = needle.get(this.url, {
|
||||||
follow_max: 10,
|
follow_max: 10,
|
||||||
|
open_timeout: 5000,
|
||||||
headers: Object.assign({
|
headers: Object.assign({
|
||||||
'User-Agent': 'PostmanRuntime/7.22.0',
|
'User-Agent': 'PostmanRuntime/7.22.0',
|
||||||
'Referer': this.url,
|
'Referer': this.url,
|
||||||
@@ -99,12 +103,12 @@ export class FileDownloader {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
req.on('err', (err) => {
|
req.on('err', (err: Error) => {
|
||||||
// TODO: this is called on timeout; if there are other cases where this can fail, they should be printed correctly
|
this.callbacks.error({ header: 'Connection Error', body: `${err.name}: ${err.message}` }, () => this.beginDownload())
|
||||||
// this.callbacks.error({ header: 'Error', description: `${err}` }, () => this.beginDownload())
|
|
||||||
})
|
})
|
||||||
|
|
||||||
req.on('header', (statusCode, headers: Headers) => {
|
req.on('header', (statusCode, headers: Headers) => {
|
||||||
|
if (this.wasCanceled) { return } // CANCEL POINT
|
||||||
if (statusCode != 200) {
|
if (statusCode != 200) {
|
||||||
this.callbacks.error({ header: 'Connection failed', body: `Server returned status code: ${statusCode}` }, () => this.beginDownload())
|
this.callbacks.error({ header: 'Connection failed', body: `Server returned status code: ${statusCode}` }, () => this.beginDownload())
|
||||||
return
|
return
|
||||||
@@ -117,10 +121,10 @@ export class FileDownloader {
|
|||||||
const fileName = this.getDownloadFileName(headers)
|
const fileName = this.getDownloadFileName(headers)
|
||||||
const downloadHash = this.getDownloadHash(headers)
|
const downloadHash = this.getDownloadHash(headers)
|
||||||
if (this.expectedHash !== undefined && downloadHash !== this.expectedHash) {
|
if (this.expectedHash !== undefined && downloadHash !== this.expectedHash) {
|
||||||
|
req.pause()
|
||||||
this.callbacks.warning(() => {
|
this.callbacks.warning(() => {
|
||||||
//TODO: check if this will actually work (or will the data get lost in the time before the button is clicked?)
|
|
||||||
// Maybe show the message at the end, and ask if they want to keep it.
|
|
||||||
this.handleDownloadResponse(req, fileName, headers['content-length'])
|
this.handleDownloadResponse(req, fileName, headers['content-length'])
|
||||||
|
req.resume()
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
this.handleDownloadResponse(req, fileName, headers['content-length'])
|
this.handleDownloadResponse(req, fileName, headers['content-length'])
|
||||||
@@ -220,4 +224,8 @@ export class FileDownloader {
|
|||||||
return headers['x-goog-hash']
|
return headers['x-goog-hash']
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cancelDownload() {
|
||||||
|
this.wasCanceled = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -29,6 +29,7 @@ export class FileExtractor {
|
|||||||
|
|
||||||
private callbacks = {} as Callbacks
|
private callbacks = {} as Callbacks
|
||||||
private libraryFolder: string
|
private libraryFolder: string
|
||||||
|
private wasCanceled = false
|
||||||
constructor(private sourceFolder: string, private isArchive: boolean, private destinationFolderName: string) { }
|
constructor(private sourceFolder: string, private isArchive: boolean, private destinationFolderName: string) { }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -58,6 +59,7 @@ export class FileExtractor {
|
|||||||
* @param filename The name of the archive file.
|
* @param filename The name of the archive file.
|
||||||
*/
|
*/
|
||||||
private extract(filename: string) {
|
private extract(filename: string) {
|
||||||
|
if (this.wasCanceled) { return } // CANCEL POINT
|
||||||
this.callbacks.extract(filename)
|
this.callbacks.extract(filename)
|
||||||
const source = join(this.sourceFolder, filename)
|
const source = join(this.sourceFolder, filename)
|
||||||
|
|
||||||
@@ -93,6 +95,7 @@ export class FileExtractor {
|
|||||||
* Deletes the archive at <archiveFilepath>, then transfers the extracted chart to <this.libraryFolder>.
|
* Deletes the archive at <archiveFilepath>, then transfers the extracted chart to <this.libraryFolder>.
|
||||||
*/
|
*/
|
||||||
private async transfer(archiveFilepath?: string) {
|
private async transfer(archiveFilepath?: string) {
|
||||||
|
if (this.wasCanceled) { return } // CANCEL POINT
|
||||||
try {
|
try {
|
||||||
|
|
||||||
// Create destiniation folder if it doesn't exist
|
// Create destiniation folder if it doesn't exist
|
||||||
@@ -117,6 +120,8 @@ export class FileExtractor {
|
|||||||
files = await readdir(this.sourceFolder)
|
files = await readdir(this.sourceFolder)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.wasCanceled) { return } // CANCEL POINT
|
||||||
|
|
||||||
// Copy the files from the temporary directory to the destination
|
// Copy the files from the temporary directory to the destination
|
||||||
for (const file of files) {
|
for (const file of files) {
|
||||||
await copyFile(join(this.sourceFolder, file), join(destinationFolder, file))
|
await copyFile(join(this.sourceFolder, file), join(destinationFolder, file))
|
||||||
@@ -133,4 +138,8 @@ export class FileExtractor {
|
|||||||
this.callbacks.error({ header: 'Transfer Failed', body: `Unable to transfer downloaded files to the library folder: ${e.name}` }, undefined)
|
this.callbacks.error({ header: 'Transfer Failed', body: `Unable to transfer downloaded files to the library folder: ${e.name}` }, undefined)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cancelExtract() {
|
||||||
|
this.wasCanceled = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -37,6 +37,7 @@ export default class Database {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// TODO: make this error message more user-friendly (retry option?)
|
||||||
return new Promise<void>((resolve, reject) => {
|
return new Promise<void>((resolve, reject) => {
|
||||||
this.conn.connect(err => {
|
this.conn.connect(err => {
|
||||||
if (err) {
|
if (err) {
|
||||||
|
|||||||
@@ -3,8 +3,8 @@ import { VersionResult, AlbumArtResult } from './interfaces/songDetails.interfac
|
|||||||
import SearchHandler from '../ipc/SearchHandler.ipc'
|
import SearchHandler from '../ipc/SearchHandler.ipc'
|
||||||
import SongDetailsHandler from '../ipc/SongDetailsHandler.ipc'
|
import SongDetailsHandler from '../ipc/SongDetailsHandler.ipc'
|
||||||
import AlbumArtHandler from '../ipc/AlbumArtHandler.ipc'
|
import AlbumArtHandler from '../ipc/AlbumArtHandler.ipc'
|
||||||
import { Download, NewDownload } from './interfaces/download.interface'
|
import { Download, NewDownload, DownloadProgress } from './interfaces/download.interface'
|
||||||
import { AddDownloadHandler } from '../ipc/download/AddDownloadHandler'
|
import { DownloadHandler } from '../ipc/download/DownloadHandler'
|
||||||
import { Settings } from './Settings'
|
import { Settings } from './Settings'
|
||||||
import InitSettingsHandler from '../ipc/InitSettingsHandler.ipc'
|
import InitSettingsHandler from '../ipc/InitSettingsHandler.ipc'
|
||||||
|
|
||||||
@@ -51,13 +51,13 @@ export interface IPCInvokeHandler<E extends keyof IPCInvokeEvents> {
|
|||||||
|
|
||||||
export function getIPCEmitHandlers(): IPCEmitHandler<keyof IPCEmitEvents>[]{
|
export function getIPCEmitHandlers(): IPCEmitHandler<keyof IPCEmitEvents>[]{
|
||||||
return [
|
return [
|
||||||
new AddDownloadHandler()
|
new DownloadHandler()
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
export type IPCEmitEvents = {
|
export type IPCEmitEvents = {
|
||||||
'add-download': NewDownload
|
'download': Download
|
||||||
'download-updated': Download
|
'download-updated': DownloadProgress
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IPCEmitHandler<E extends keyof IPCEmitEvents> {
|
export interface IPCEmitHandler<E extends keyof IPCEmitEvents> {
|
||||||
|
|||||||
@@ -1,8 +1,13 @@
|
|||||||
|
export interface Download {
|
||||||
|
action: 'add' | 'retry' | 'continue' | 'cancel'
|
||||||
|
versionID: number
|
||||||
|
data ?: NewDownload
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Contains the data required to start downloading a single chart
|
* Contains the data required to start downloading a single chart
|
||||||
*/
|
*/
|
||||||
export interface NewDownload {
|
export interface NewDownload {
|
||||||
versionID: number
|
|
||||||
avTagName: string
|
avTagName: string
|
||||||
artist: string
|
artist: string
|
||||||
charter: string
|
charter: string
|
||||||
@@ -12,10 +17,11 @@ export interface NewDownload {
|
|||||||
/**
|
/**
|
||||||
* Represents the download progress of a single chart
|
* Represents the download progress of a single chart
|
||||||
*/
|
*/
|
||||||
export interface Download {
|
export interface DownloadProgress {
|
||||||
versionID: number
|
versionID: number
|
||||||
title: string
|
title: string
|
||||||
header: string
|
header: string
|
||||||
description: string
|
description: string
|
||||||
percent: number
|
percent: number
|
||||||
|
type: 'good' | 'warning' | 'error' | 'cancel'
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user