Skip to content

Commit

Permalink
1.1.0
Browse files Browse the repository at this point in the history
  • Loading branch information
theogravity committed Mar 21, 2024
1 parent bc29fcb commit a5db7df
Show file tree
Hide file tree
Showing 8 changed files with 186 additions and 68 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
# 1.1.0 (2024-03-21)

- Add `ElectronDownloadManagerMock` for use in tests
- Add `getActiveDownloadCount()` to get the number of active downloads
- Add `showBadge` option to `download()` to show a badge on the dock icon

# 1.0.2 (2024-03-21)

`download()` now returns the `id` of the download
Expand Down
24 changes: 24 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ manager.resumeDownload(id);
+ [`cancelDownload()`](#-canceldownload---)
+ [`pauseDownload()`](#-pausedownload---)
+ [`resumeDownload()`](#-resumedownload---)
+ [`getActiveDownloadCount()`](#-getactivedownloadcount---)
- [Acknowledgments](#acknowledgments)

# Installation
Expand Down Expand Up @@ -212,6 +213,13 @@ interface DownloadParams {
* @default false
*/
overwrite?: boolean
/**
* If true, will show a badge on the dock icon when the download is in progress
* under MacOS and linux.
*
* @default false
*/
showBadge?: boolean
}
```

Expand Down Expand Up @@ -287,6 +295,22 @@ Resumes a download.
resumeDownload(id: string): void
```

### `getActiveDownloadCount()`

Returns the number of active downloads.

```typescript
getActiveDownloadCount(): number
```

# Mock class

If you need to mock out `ElectronDownloadManager` in your tests, you can use the `ElectronDownloadManagerMock` class.

`import { ElectronDownloadManagerMock } from 'electron-dl-manager'`

```typescript

# Acknowledgments

This code uses small portions from [`electron-dl`](https://github.com/sindresorhus/electron-dl) and is noted in the
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "electron-dl-manager",
"version": "1.0.2",
"version": "1.1.0",
"description": "A library for implementing file downloads in Electron with 'save as' dialog and id support.",
"main": "dist/cjs/index.js",
"module": "dist/esm/index.js",
Expand Down
57 changes: 40 additions & 17 deletions src/ElectronDownloadManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
DownloadManagerConstructorParams,
DownloadManagerItem,
DownloadParams,
IElectronDownloadManager,
} from './types'
import * as path from 'path'
import { unusedFilenameSync } from 'unused-filename'
Expand All @@ -21,6 +22,7 @@ interface ItemHandlerParams {
item: DownloadItem
webContents: WebContents
callbacks: DownloadManagerCallbacks
showBadge?: boolean
}

function tId(id: string) {
Expand All @@ -35,15 +37,14 @@ function tUrl(url: string) {
}

function generateRandomId() {
const currentTime = new Date().getTime() // Get the current timestamp
const randomNum = Math.floor(Math.random() * 1000) // Generate a random number between 0 and 999
const currentTime = new Date().getTime()
const randomNum = Math.floor(Math.random() * 1000)
const combinedValue = currentTime.toString() + randomNum.toString()

const hash = crypto.createHash('sha256')
hash.update(combinedValue)
const randomId = hash.digest('hex').substring(0, 12) // Get the first 12 characters of the hashed value

return randomId
return hash.digest('hex').substring(0, 12)
}

// Copied from https://github.com/sindresorhus/electron-dl/blob/main/index.js#L10
Expand All @@ -60,7 +61,7 @@ const getFilenameFromMime = (name: string, mime: string) => {
/**
* Enables handling downloads in Electron.
*/
export class ElectronDownloadManager {
export class ElectronDownloadManager implements IElectronDownloadManager {
// WeakMap for auto-cleanup when the download is done
protected downloadItems: WeakMap<DownloadItem, DownloadManagerItem>
// Reverse lookup for download items. Mainly used for operations like item cancellation
Expand Down Expand Up @@ -149,6 +150,13 @@ export class ElectronDownloadManager {
}
}

/**
* Returns the number of active downloads
*/
getActiveDownloadCount() {
return Object.values(this.idToDownloadItems).filter((item) => item.getState() === 'progressing').length
}

protected handleError(
callbacks: DownloadManagerCallbacks,
error: Error,
Expand Down Expand Up @@ -202,13 +210,19 @@ export class ElectronDownloadManager {
dbg.detach()
}

protected updateBadgeCount() {
if (process.platform === 'darwin' || process.platform === 'linux') {
app.setBadgeCount(this.getActiveDownloadCount())
}
}

/**
* Handles when the user initiates a download action by adding the developer-defined
* listeners to the download item events. Attaches to the session `will-download` event.
*/
protected onWillDownload(
id: string,
{ window, directory, overwrite, saveAsFilename, callbacks, saveDialogOptions }: DownloadParams
{ window, directory, overwrite, saveAsFilename, callbacks, saveDialogOptions, showBadge }: DownloadParams
) {
return async (event: Event, item: DownloadItem, webContents: WebContents): Promise<void> => {
// Begin adapted code from
Expand Down Expand Up @@ -289,18 +303,20 @@ export class ElectronDownloadManager {

const updatedHandler = this.itemOnUpdated({
id,
event: event,
item: item,
webContents: webContents,
callbacks: callbacks,
event,
item,
webContents,
callbacks,
showBadge,
})

const doneHandler = this.itemOnDone({
id,
event: event,
item: item,
webContents: webContents,
callbacks: callbacks,
event,
item,
webContents,
callbacks,
showBadge,
})

this.listeners.set(item, {
Expand All @@ -314,14 +330,13 @@ export class ElectronDownloadManager {
}
}

protected itemOnUpdated({ id, event, item, webContents, callbacks }: ItemHandlerParams) {
protected itemOnUpdated({ id, event, item, webContents, callbacks, showBadge }: ItemHandlerParams) {
return async (_event: Event, state: 'progressing' | 'interrupted') => {
switch (state) {
case 'progressing': {
this.updateProgress(item)
if (callbacks.onDownloadProgress && this.downloadItems.has(item)) {
const data = this.downloadItems.get(item)!

this.log(`[${tId(id)}] Calling onDownloadProgress ${data.percentCompleted}%`)

try {
Expand Down Expand Up @@ -357,10 +372,14 @@ export class ElectronDownloadManager {
break
}
}

if (showBadge) {
this.updateBadgeCount()
}
}
}

protected itemOnDone({ id, event, item, webContents, callbacks }: ItemHandlerParams) {
protected itemOnDone({ id, event, item, webContents, callbacks, showBadge }: ItemHandlerParams) {
return async (_event: Event, state: 'completed' | 'cancelled' | 'interrupted') => {
switch (state) {
case 'completed': {
Expand Down Expand Up @@ -400,6 +419,10 @@ export class ElectronDownloadManager {
break
}

if (showBadge) {
this.updateBadgeCount()
}

this.cleanup(item)
}
}
Expand Down
23 changes: 23 additions & 0 deletions src/ElectronDownloadManagerMock.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/* eslint-disable @typescript-eslint/no-unused-vars */

import { DownloadParams, IElectronDownloadManager } from './types'

/**
* Mock version of ElectronDownloadManager
* that can be used for testing purposes
*/
export class ElectronDownloadManagerMock implements IElectronDownloadManager {
download(_params: DownloadParams): string {
return 'mock-download-id'
}

cancelDownload(_id: string): void {}

pauseDownload(_id: string): void {}

resumeDownload(_id: string): void {}

getActiveDownloadCount(): number {
return 0
}
}
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export * from './types'
export * from './ElectronDownloadManager'
export * from './ElectronDownloadManagerMock'
33 changes: 33 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -136,4 +136,37 @@ export interface DownloadParams {
* @default false
*/
overwrite?: boolean
/**
* If true, will show a badge on the dock icon when the download is in progress
* under MacOS and linux.
*
* @default false
*/
showBadge?: boolean
}

export interface IElectronDownloadManager {
/**
* Starts a download. If saveDialogOptions has been defined in the config,
* the saveAs dialog will show up first.
*
* Returns the id of the download.
*/
download(params: DownloadParams): string
/**
* Cancels a download
*/
cancelDownload(id: string): void
/**
* Pauses a download
*/
pauseDownload(id: string): void
/**
* Resumes a download
*/
resumeDownload(id: string): void
/**
* Returns the number of active downloads
*/
getActiveDownloadCount(): number
}
Loading

0 comments on commit a5db7df

Please sign in to comment.