Skip to content

Commit

Permalink
@uppy/core: refactor to TS
Browse files Browse the repository at this point in the history
Co-authored-by: Antoine du Hamel <antoine@transloadit.com>
  • Loading branch information
Murderlon and aduh95 committed Dec 14, 2023
1 parent d0cc5b4 commit c48aa82
Show file tree
Hide file tree
Showing 41 changed files with 2,200 additions and 1,113 deletions.
2 changes: 1 addition & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -469,7 +469,7 @@ module.exports = {
},
{
files: ['packages/@uppy/*/src/**/*.ts', 'packages/@uppy/*/src/**/*.tsx'],
excludedFiles: ['packages/@uppy/**/*.test.ts'],
excludedFiles: ['packages/@uppy/**/*.test.ts', 'packages/@uppy/core/src/mocks/*.ts'],
rules: {
'@typescript-eslint/explicit-function-return-type': 'error',
},
Expand Down
85 changes: 0 additions & 85 deletions packages/@uppy/core/src/BasePlugin.js

This file was deleted.

106 changes: 106 additions & 0 deletions packages/@uppy/core/src/BasePlugin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
/* eslint-disable class-methods-use-this */
/* eslint-disable @typescript-eslint/no-empty-function */

/**
* Core plugin logic that all plugins share.
*
* BasePlugin does not contain DOM rendering so it can be used for plugins
* without a user interface.
*
* See `Plugin` for the extended version with Preact rendering for interfaces.
*/

import Translator from '@uppy/utils/lib/Translator'
import type { I18n, Locale } from '@uppy/utils/lib/Translator'
import type { Body, Meta } from '@uppy/utils/lib/UppyFile'
import type { Uppy } from '.'

export type PluginOpts = { locale?: Locale; [key: string]: unknown }

export default class BasePlugin<
Opts extends PluginOpts,
M extends Meta,
B extends Body,
> {
uppy: Uppy<M, B>

opts: Opts

id: string

defaultLocale: Locale

i18n: I18n

i18nArray: Translator['translateArray']

type: string

VERSION: string

constructor(uppy: Uppy<M, B>, opts: Opts) {
this.uppy = uppy
this.opts = opts ?? {}
}

getPluginState(): Record<string, unknown> {
const { plugins } = this.uppy.getState()
return plugins?.[this.id] || {}
}

setPluginState(update: unknown): void {
if (!update) return
const { plugins } = this.uppy.getState()

this.uppy.setState({
plugins: {
...plugins,
[this.id]: {
...plugins[this.id],
...update,
},
},
})
}

setOptions(newOpts: Partial<Opts>): void {
this.opts = { ...this.opts, ...newOpts }
this.setPluginState(undefined) // so that UI re-renders with new options
this.i18nInit()
}

i18nInit(): void {
const translator = new Translator([
this.defaultLocale,
this.uppy.locale,
this.opts.locale,
])
this.i18n = translator.translate.bind(translator)
this.i18nArray = translator.translateArray.bind(translator)
this.setPluginState(undefined) // so that UI re-renders and we see the updated locale
}

/**
* Extendable methods
* ==================
* These methods are here to serve as an overview of the extendable methods as well as
* making them not conditional in use, such as `if (this.afterUpdate)`.
*/

// eslint-disable-next-line @typescript-eslint/no-unused-vars
addTarget(plugin: unknown): HTMLElement {
throw new Error(
"Extend the addTarget method to add your plugin to another plugin's target",
)
}

install(): void {}

uninstall(): void {}

// eslint-disable-next-line @typescript-eslint/no-unused-vars
update(state: any): void {}

// Called after every state update, after everything's mounted. Debounced.
afterUpdate(): void {}
}
114 changes: 114 additions & 0 deletions packages/@uppy/core/src/EventManager.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
import type { Meta, Body, UppyFile } from '@uppy/utils/lib/UppyFile'
import type {
DeprecatedUppyEventMap,
Uppy,
UppyEventMap,
_UppyEventMap,
} from './Uppy'

/**
* Create a wrapper around an event emitter with a `remove` method to remove
* all events that were added using the wrapped emitter.
*/
export default class EventManager<M extends Meta, B extends Body> {
#uppy: Uppy<M, B>

#events: Array<[keyof UppyEventMap<M, B>, (...args: any[]) => void]> = []

constructor(uppy: Uppy<M, B>) {
this.#uppy = uppy
}

on<K extends keyof _UppyEventMap<M, B>>(
event: K,
fn: _UppyEventMap<M, B>[K],
): Uppy<M, B>

/** @deprecated */
on<K extends keyof DeprecatedUppyEventMap<M, B>>(
event: K,
fn: DeprecatedUppyEventMap<M, B>[K],
): Uppy<M, B>

on<K extends keyof UppyEventMap<M, B>>(
event: K,
fn: UppyEventMap<M, B>[K],
): Uppy<M, B> {
this.#events.push([event, fn])
return this.#uppy.on(event as keyof _UppyEventMap<M, B>, fn)
}

remove(): void {
for (const [event, fn] of this.#events.splice(0)) {
this.#uppy.off(event, fn)
}
}

onFilePause(
fileID: UppyFile<M, B>['id'],
cb: (isPaused: boolean) => void,
): void {
this.on('upload-pause', (targetFileID, isPaused) => {
if (fileID === targetFileID) {
cb(isPaused)
}
})
}

onFileRemove(
fileID: UppyFile<M, B>['id'],
cb: (isPaused: UppyFile<M, B>['id']) => void,
): void {
this.on('file-removed', (file) => {
if (fileID === file.id) cb(file.id)
})
}

onPause(fileID: UppyFile<M, B>['id'], cb: (isPaused: boolean) => void): void {
this.on('upload-pause', (targetFileID, isPaused) => {
if (fileID === targetFileID) {
// const isPaused = this.#uppy.pauseResume(fileID)
cb(isPaused)
}
})
}

onRetry(fileID: UppyFile<M, B>['id'], cb: () => void): void {
this.on('upload-retry', (targetFileID) => {
if (fileID === targetFileID) {
cb()
}
})
}

onRetryAll(fileID: UppyFile<M, B>['id'], cb: () => void): void {
this.on('retry-all', () => {
if (!this.#uppy.getFile(fileID)) return
cb()
})
}

onPauseAll(fileID: UppyFile<M, B>['id'], cb: () => void): void {
this.on('pause-all', () => {
if (!this.#uppy.getFile(fileID)) return
cb()
})
}

onCancelAll(
fileID: UppyFile<M, B>['id'],
eventHandler: UppyEventMap<M, B>['cancel-all'],
): void {
this.on('cancel-all', (...args) => {
if (!this.#uppy.getFile(fileID)) return
eventHandler(...args)
})
}

onResumeAll(fileID: UppyFile<M, B>['id'], cb: () => void): void {
this.on('resume-all', () => {
if (!this.#uppy.getFile(fileID)) return
cb()
})
}
}
Loading

0 comments on commit c48aa82

Please sign in to comment.