index.js 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. const { UIPlugin } = require('@uppy/core')
  2. const Translator = require('@uppy/utils/lib/Translator')
  3. const { h } = require('preact')
  4. const Editor = require('./Editor')
  5. module.exports = class ImageEditor extends UIPlugin {
  6. // eslint-disable-next-line global-require
  7. static VERSION = require('../package.json').version
  8. constructor (uppy, opts) {
  9. super(uppy, opts)
  10. this.id = this.opts.id || 'ImageEditor'
  11. this.title = 'Image Editor'
  12. this.type = 'editor'
  13. this.defaultLocale = {
  14. strings: {
  15. revert: 'Revert',
  16. rotate: 'Rotate',
  17. zoomIn: 'Zoom in',
  18. zoomOut: 'Zoom out',
  19. flipHorizontal: 'Flip horizontal',
  20. aspectRatioSquare: 'Crop square',
  21. aspectRatioLandscape: 'Crop landscape (16:9)',
  22. aspectRatioPortrait: 'Crop portrait (9:16)',
  23. },
  24. }
  25. const defaultCropperOptions = {
  26. viewMode: 1,
  27. background: false,
  28. autoCropArea: 1,
  29. responsive: true,
  30. croppedCanvasOptions: {},
  31. }
  32. const defaultActions = {
  33. revert: true,
  34. rotate: true,
  35. granularRotate: true,
  36. flip: true,
  37. zoomIn: true,
  38. zoomOut: true,
  39. cropSquare: true,
  40. cropWidescreen: true,
  41. cropWidescreenVertical: true,
  42. }
  43. const defaultOptions = {
  44. quality: 0.8,
  45. }
  46. this.opts = {
  47. ...defaultOptions,
  48. ...opts,
  49. actions: {
  50. ...defaultActions,
  51. ...opts.actions,
  52. },
  53. cropperOptions: {
  54. ...defaultCropperOptions,
  55. ...opts.cropperOptions,
  56. },
  57. }
  58. this.i18nInit()
  59. }
  60. // eslint-disable-next-line class-methods-use-this
  61. canEditFile (file) {
  62. if (!file.type || file.isRemote) {
  63. return false
  64. }
  65. const fileTypeSpecific = file.type.split('/')[1]
  66. if (/^(jpe?g|gif|png|bmp|webp)$/.test(fileTypeSpecific)) {
  67. return true
  68. }
  69. return false
  70. }
  71. save = () => {
  72. const saveBlobCallback = (blob) => {
  73. const { currentImage } = this.getPluginState()
  74. this.uppy.setFileState(currentImage.id, {
  75. data: blob,
  76. size: blob.size,
  77. preview: null,
  78. })
  79. const updatedFile = this.uppy.getFile(currentImage.id)
  80. this.uppy.emit('thumbnail:request', updatedFile)
  81. this.setPluginState({
  82. currentImage: updatedFile,
  83. })
  84. this.uppy.emit('file-editor:complete', updatedFile)
  85. }
  86. const { currentImage } = this.getPluginState()
  87. this.cropper.getCroppedCanvas().toBlob(
  88. saveBlobCallback,
  89. currentImage.type,
  90. this.opts.quality
  91. )
  92. }
  93. storeCropperInstance = (cropper) => {
  94. this.cropper = cropper
  95. }
  96. selectFile = (file) => {
  97. this.uppy.emit('file-editor:start', file)
  98. this.setPluginState({
  99. currentImage: file,
  100. })
  101. }
  102. install () {
  103. this.setPluginState({
  104. currentImage: null,
  105. })
  106. const { target } = this.opts
  107. if (target) {
  108. this.mount(target, this)
  109. }
  110. }
  111. uninstall () {
  112. this.unmount()
  113. }
  114. render () {
  115. const { currentImage } = this.getPluginState()
  116. if (currentImage === null || currentImage.isRemote) {
  117. return null
  118. }
  119. return (
  120. <Editor
  121. currentImage={currentImage}
  122. storeCropperInstance={this.storeCropperInstance}
  123. save={this.save}
  124. opts={this.opts}
  125. i18n={this.i18n}
  126. />
  127. )
  128. }
  129. }