Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
theogravity committed Mar 20, 2024
1 parent 0a0913d commit edf9704
Show file tree
Hide file tree
Showing 11 changed files with 6,046 additions and 3,535 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -115,3 +115,4 @@ dist
.yarn/build-state.yml
.yarn/install-state.gz
.pnp.*
.idea/
2 changes: 1 addition & 1 deletion .prettierrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@ module.exports = {
singleQuote: true,
trailingComma: 'es5',
arrowParens: 'always',
printWidth: 80,
printWidth: 120,
}
1 change: 1 addition & 0 deletions config/webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ const path = require('path')

module.exports = {
mode: 'production',
target: 'node',
entry: './src/index.ts',
output: {
path: path.resolve(__dirname, '../dist/umd'),
Expand Down
9,152 changes: 5,829 additions & 3,323 deletions package-lock.json

Large diffs are not rendered by default.

33 changes: 18 additions & 15 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "example-typescript-package",
"version": "0.2.2",
"name": "electron-multi-downloader",
"version": "0.0.1",
"description": "",
"main": "dist/cjs/index.js",
"module": "dist/esm/index.js",
Expand Down Expand Up @@ -51,22 +51,25 @@
"url": "https://github.com/tomchen/example-typescript-package/issues"
},
"dependencies": {},
"peerDependencies": {
"electron": ">=26"
},
"devDependencies": {
"@commitlint/cli": "^13.1.0",
"@commitlint/config-conventional": "^13.1.0",
"@types/jest": "^27.0.1",
"@typescript-eslint/eslint-plugin": "^4.31.1",
"@typescript-eslint/parser": "^4.31.1",
"eslint": "^7.32.0",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-prettier": "^4.0.0",
"@commitlint/cli": "^19.2.1",
"@commitlint/config-conventional": "^19.1.0",
"@types/jest": "^29.5.12",
"@typescript-eslint/eslint-plugin": "^7.3.1",
"@typescript-eslint/parser": "^7.3.1",
"eslint": "^8.57.0",
"eslint-config-prettier": "^8.10.0",
"eslint-plugin-prettier": "^5.1.3",
"husky": "^7.0.2",
"jest": "^27.2.0",
"jest": "^29.7.0",
"pinst": "^2.1.6",
"prettier": "^2.4.0",
"ts-jest": "^27.0.5",
"ts-loader": "^9.2.5",
"typescript": "^4.4.3",
"prettier": "^3.2.5",
"ts-jest": "^29.1.2",
"ts-loader": "^9.5.1",
"typescript": "^5.4.2",
"webpack": "^5.52.1",
"webpack-cli": "^4.8.0"
}
Expand Down
148 changes: 148 additions & 0 deletions src/DownloadManager.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
import crypto from 'crypto'
import type { DownloadItem, DownloadURLOptions, Event, WebContents } from 'electron'
import { DownloadManagerConfig, DownloadManagerItem } from './types'

type DoneEventFn = (_event: Event, state: 'completed' | 'cancelled' | 'interrupted') => Promise<void>
type UpdatedEventFn = (_event: Event, state: 'progressing' | 'interrupted') => Promise<void>

/**
* Enables download handling for a BrowserWindow.
*/
export class DownloadManager {
protected config: DownloadManagerConfig
protected downloadItems: WeakMap<DownloadItem, DownloadManagerItem>
protected listeners: WeakMap<
DownloadItem,
{
done: DoneEventFn
updated: UpdatedEventFn
}
>

constructor(config: DownloadManagerConfig) {
this.downloadItems = new WeakMap()
this.listeners = new WeakMap()
this.config = config

config.window.webContents.session.on('will-download', this.onWillDownload)
}

/**
* Starts a download. If saveDialogOptions has been defined in the config,
* the saveAs dialog will show up first.
*/
download(url: string, options?: DownloadURLOptions) {
this.config.window.webContents.downloadURL(url, options)
}

protected onWillDownload = async (
_event: Event,
item: DownloadItem,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
_webContents: WebContents
): Promise<void> => {
if (this.config.saveDialogOptions) {
item.setSaveDialogOptions(this.config.saveDialogOptions)
}

const id = this.calculateId(item)

this.downloadItems.set(item, {
id,
percentCompleted: 0,
})

if (this.config.onDownloadStarted && this.downloadItems.has(item)) {
await this.config.onDownloadStarted({
...this.downloadItems.get(item)!,
item,
})
}

const updatedHandler = this.itemOnUpdated(item)
const doneHandler = this.itemOnDone(item)

this.listeners.set(item, {
done: doneHandler,
updated: updatedHandler,
})

item.on('updated', updatedHandler)
item.once('done', doneHandler)
}

protected itemOnUpdated = (item: DownloadItem) => {
return async (_event: Event, state: 'progressing' | 'interrupted') => {
switch (state) {
case 'progressing': {
this.updateProgress(item)
if (this.config.onDownloadProgress && this.downloadItems.has(item)) {
await this.config.onDownloadProgress({
...this.downloadItems.get(item)!,
item,
})
}
break
}
case 'interrupted': {
console.log('interrupted A')
break
}
}
}
}

protected itemOnDone = (item: DownloadItem) => {
return async (_event: Event, state: 'completed' | 'cancelled' | 'interrupted') => {
switch (state) {
case 'completed': {
if (this.config.onDownloadCompleted && this.downloadItems.has(item)) {
await this.config.onDownloadCompleted({
...this.downloadItems.get(item)!,
item,
})
}
break
}
case 'cancelled':
if (this.config.onDownloadCancelled && this.downloadItems.has(item)) {
await this.config.onDownloadCancelled({
...this.downloadItems.get(item)!,
item,
})
}
break
case 'interrupted':
console.log('interrupted B')
break
}

this.cleanup(item)
}
}

protected updateProgress(item: DownloadItem): void {
const data = this.downloadItems.get(item)

if (data) {
data.percentCompleted = parseFloat(((item.getReceivedBytes() / item.getTotalBytes()) * 100).toFixed(2))
}
}

protected calculateId(item: DownloadItem): string {
const toHash = item.getURL() + item.getETag() + item.getFilename() + item.getSavePath()

return crypto.createHash('sha256').update(toHash).digest('hex')
}

protected cleanup(item: DownloadItem) {
const listeners = this.listeners.get(item)

if (listeners) {
item.removeListener('updated', listeners.updated)
item.removeListener('done', listeners.done)
this.listeners.delete(item)
this.downloadItems.delete(item)
}
}
}
177 changes: 0 additions & 177 deletions src/Num.ts

This file was deleted.

Loading

0 comments on commit edf9704

Please sign in to comment.