SharedHandler.js 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. import remoteFileObjToLocal from '@uppy/utils/lib/remoteFileObjToLocal'
  2. export default class SharedHandler {
  3. constructor (plugin) {
  4. this.plugin = plugin
  5. this.filterItems = this.filterItems.bind(this)
  6. this.toggleCheckbox = this.toggleCheckbox.bind(this)
  7. this.recordShiftKeyPress = this.recordShiftKeyPress.bind(this)
  8. this.isChecked = this.isChecked.bind(this)
  9. this.loaderWrapper = this.loaderWrapper.bind(this)
  10. }
  11. filterItems (items) {
  12. const state = this.plugin.getPluginState()
  13. if (!state.filterInput || state.filterInput === '') {
  14. return items
  15. }
  16. return items.filter((folder) => {
  17. return folder.name.toLowerCase().indexOf(state.filterInput.toLowerCase()) !== -1
  18. })
  19. }
  20. recordShiftKeyPress (e) {
  21. this.isShiftKeyPressed = e.shiftKey
  22. }
  23. /**
  24. * Toggles file/folder checkbox to on/off state while updating files list.
  25. *
  26. * Note that some extra complexity comes from supporting shift+click to
  27. * toggle multiple checkboxes at once, which is done by getting all files
  28. * in between last checked file and current one.
  29. */
  30. toggleCheckbox (e, file) {
  31. e.stopPropagation()
  32. e.preventDefault()
  33. e.currentTarget.focus()
  34. const { folders, files } = this.plugin.getPluginState()
  35. const items = this.filterItems(folders.concat(files))
  36. // Shift-clicking selects a single consecutive list of items
  37. // starting at the previous click and deselects everything else.
  38. if (this.lastCheckbox && this.isShiftKeyPressed) {
  39. const prevIndex = items.indexOf(this.lastCheckbox)
  40. const currentIndex = items.indexOf(file)
  41. const currentSelection = (prevIndex < currentIndex)
  42. ? items.slice(prevIndex, currentIndex + 1)
  43. : items.slice(currentIndex, prevIndex + 1)
  44. const reducedCurrentSelection = []
  45. // Check restrictions on each file in currentSelection,
  46. // reduce it to only contain files that pass restrictions
  47. for (const item of currentSelection) {
  48. const { uppy } = this.plugin
  49. const validatedRestrictions = uppy.validateRestrictions(
  50. remoteFileObjToLocal(item),
  51. [...uppy.getFiles(), ...reducedCurrentSelection],
  52. )
  53. if (validatedRestrictions.result) {
  54. reducedCurrentSelection.push(item)
  55. } else {
  56. uppy.info({ message: validatedRestrictions.reason }, 'error', uppy.opts.infoTimeout)
  57. }
  58. }
  59. this.plugin.setPluginState({ currentSelection: reducedCurrentSelection })
  60. return
  61. }
  62. this.lastCheckbox = file
  63. const { currentSelection } = this.plugin.getPluginState()
  64. if (this.isChecked(file)) {
  65. this.plugin.setPluginState({
  66. currentSelection: currentSelection.filter((item) => item.id !== file.id),
  67. })
  68. } else {
  69. this.plugin.setPluginState({
  70. currentSelection: currentSelection.concat([file]),
  71. })
  72. }
  73. }
  74. isChecked (file) {
  75. const { currentSelection } = this.plugin.getPluginState()
  76. // comparing id instead of the file object, because the reference to the object
  77. // changes when we switch folders, and the file list is updated
  78. return currentSelection.some((item) => item.id === file.id)
  79. }
  80. loaderWrapper (promise, then, catch_) {
  81. promise
  82. .then((result) => {
  83. this.plugin.setPluginState({ loading: false })
  84. then(result)
  85. }).catch((err) => {
  86. this.plugin.setPluginState({ loading: false })
  87. catch_(err)
  88. })
  89. this.plugin.setPluginState({ loading: true })
  90. }
  91. }