* core: add an addFiles() method that only updates state once
Previously, adding 1300-ish files took around 260ms, and looked like
this in Firefox's performance tab:

All of the downward peaks are `setState()` calls and GC.
Now it takes around 60ms, and looks like this:

Here, most of the time is spent generating file IDs and guessing file
types. Those would be areas to look at next.
* dashboard: prevent frequent state update if nothing changed
After the last commit, `addFiles()` still spends a lot of time in
`emit()` and `hideAllPanels()`. The reason is that `addFiles()` still
emits all the hundreds of file-added events, and the Dashboard responds
to each with `hideAllPanels()`, which does a state update. But this all
happens synchronously, and the state almost certainly did not change
since the last `file-added` event that fired a millisecond ago.
This adds a check to avoid the state update if it is not necessary.

Adding 1300 files takes about 40ms now.
With this change, the `addFiles()` call is no longer the slowest
part—now preact rendering all the items is!
* utils: optimize generateFileID and getFileNameAndExtension
Replaces some clever things with more mundane and faster things!
Now, generateFileID is a bunch of string concatenations.
Now, getFileNameAndExtension uses `lastIndexOf()` instead of a regex.

Adding 1300 files takes about 25ms.
* dashboard: use preact-virtual-list
* thumbnail-generator: add `lazy` option
* dashboard: request thumbnails once file item renders the first time
* dashboard: fork preact-virtual-list
* core: add removeFiles() to remove files in bulk
* Implement removeFile() in terms of removeFiles()
* thumbnail-generator: only queue files that can be previewed
* rename size constants to accommodate WIDTH/HEIGHT
* Use new uppy.addFiles in DragDrop and FileInput
* utils: fix getFileNameAndExtension() type
* Rip out the lazy thumbnail generation
* Rip out virtualization.
* Remove virtualization leftovers
* tell future people that this is intentionally verbose
* Update package-lock.json
* henlo i am spell
* Make `addFiles()` respect maxNumberOfFiles
* core: show an informer error if some files fail in bulk add
* locales: fix quotes to make build:locale-pack happy
Co-authored-by: Artur Paikin <artur@arturpaikin.com>
* Add a method to update options in Core
* Add a method to update options in Plugin (for any plugins)
* Allow re-initializing i18n locales after they’ve been updated with .setOptions
* use rest spread instead of Object.assign
* override setOptions in plugins to include i18nInit
* merge restrictions object in setOptions
* check that newOpts exists
* add spread ...
* don’t double merge
* add i18nInit to all plugins that use translation strings
* add setOptions tests to Core and Dashboard
* add setOptions docs for Core and Plugins
* fix tests for thumbnail-generator by adding plugins: {} to mock core
cause ThumbnailGenerator now calls this.setPluginState, which expects `core.state.plugins`
* also update meta with setOptions if it’s passed, change the way this.opts is set in core
@goto-bus-stop does this look ok? merging restrictions opts in core
* if locale was passed to setOptions(), call plugin.setOptions() on all plugins, so that i18n updates
* add Dashboard test that checks if locale is updated from Core via setOptions()
* Reafactor website Dashboard example to use setOptions and allow selecting a locale
🎉
* Update eslint
* Do eslint --fix
* Do not access Object.prototype method 'hasOwnProperty' from target object
* utils: add hasProperty
* eslint --fix
* Disable quote-props for locale files
* add back quotes in locale files
* revert locale files to state on master
* Update react-scripts
* lerna link convert
* ci: use npm ci
* update lockfile
* companion: set `bin` to source file
Since typescript doesn't actually transform anything, we can just use
this.
In a next major version we could set `noEmit: true` in the tsconfig and
stop publishing `lib`.
* companion: do chmod +x on start-server.js
* build: remove obsolete lerna config
* build: explicitly install latest versions when building e2e tests for ci
* Remove versions from private packages
* fix regex
* try fix
* ci: force npm to install to endtoend folder
* ci: fold up e2e build output
* Update netlify deploy preview command
* Remove mentions of npm run bootstrap
* Edit .github/CONTRIBUTING.md instead
* companion: add proxy executable
* companion: fix publish
* Downgrade jest to appease create-react-app
* Log error in uppy.addFile try/catch
* Add `.isRestriction` to a custom RestrictionError, check for that before logging
* keep throwing for robodog.upload
//cc @goto-bus-stop
Webpack likes to pick the ES module versions of modules over CJS
versions. So, if we do `require('preact')`, we can get the ES module
version of it. preact in version 8.3.0 switched its file extension
from `.esm.js` to `.mjs`, which in webpack's default configuration meant
the module implementation became much stricter. The result is that we
get a different value in `require('preact')`.
This older version of preact doesn't use `.mjs` yet so we can safely
`require('preact')` it in webpack. It still picks the ESM version, but
now it uses the looser implementation which is interchangeable for our
purposes.
* first swing at building locale pack
* expose default locale on the plugin instance
* write a pretty en_US locale to a file, using stringify-object and template.js
* generated locale pack
* start adding a script that checks for unused locale strings
Co-Authored-By: Kevin van Zonneveld <kevin@transloadit.com>
* Update bin/build-locale-pack.js
* Console output improvements
* Also sort plugin locale keys
* Support dependencies when digging up sources
because e.g. 'emptyFolderAdded' is used in provider-views but set in Dashboard's defaultLocale
* More complex matching
So can can support cases like: `uppy.i18n(error.isAuthError ? 'companionAuthError' : 'companionError')`
* Remaining const defaultLocale -> this.defaultLocale
* Update packages/@uppy/locales/en_US.js
* Mock browser environment so all plugins can be instantiated
* Clean up output a bit
* Update bin/build-locale-pack.js
* Add all remaining plugin's locales to en_US bundle
* Update packages/@uppy/dashboard/src/index.js
* Update en_US.js
Co-Authored-By: Kevin van Zonneveld <kevin@transloadit.com>
* remove unused strings
Co-Authored-By: Kevin van Zonneveld <kevin@transloadit.com>
* Also write csv because that makes it real easy to import to friendlier places for translators /cc @arturi
* don’t set locale: this.defaultLocale — it overrides the lang pack
Co-Authored-By: Kevin van Zonneveld <kevin@transloadit.com>
* Add 'russian plural' for english, for consistency
Allows us to signal that this is possible in new target languages, and also run better linting
* Cleanup
* No longer write csv
* WIP for NL
* Create package.json
Co-Authored-By: Kevin van Zonneveld <kevin@transloadit.com>
* move locales to /src
Co-Authored-By: Kevin van Zonneveld <kevin@transloadit.com>
* ignore locales themselves
Co-Authored-By: Kevin van Zonneveld <kevin@transloadit.com>
* build minified locale packs
Co-Authored-By: Kevin van Zonneveld <kevin@transloadit.com>
* expose Uppy.locale = {} placeholder object
Co-Authored-By: Kevin van Zonneveld <kevin@transloadit.com>
* Update ru_RU.js
Co-Authored-By: Kevin van Zonneveld <kevin@transloadit.com>
* add locale bundles to example
Co-Authored-By: Kevin van Zonneveld <kevin@transloadit.com>
* Upload locales to cdn
* Allow to run tests with upload-to-cdn by setting a versionSuffix
* Move locale build to function, to make room for test()
* Bring ru_RU in sync with English
now that we've added 3 plural types across the board
* Document using locales as a consuming dev, and plugin dev
* Add linting for missing/excess locale strings
* Add the locales we had to remove to the legacy folder
and explain why they cannot make it back
* Move legacy outside of src so they are definitely not transpiled, etc
* Update packages/@uppy/locales/src/nl_NL.js
* Update website/src/docs/uppy.md