logo

pleroma-fe

My custom branche(s) on git.pleroma.social/pleroma/pleroma-fe git clone https://anongit.hacktivis.me/git/pleroma-fe.git/

media_upload.js (5113B)


  1. /* eslint-env browser */
  2. import statusPosterService from '../../services/status_poster/status_poster.service.js'
  3. import fileSizeFormatService from '../../services/file_size_format/file_size_format.js'
  4. import { library } from '@fortawesome/fontawesome-svg-core'
  5. import { faUpload, faCircleNotch } from '@fortawesome/free-solid-svg-icons'
  6. library.add(
  7. faUpload,
  8. faCircleNotch
  9. )
  10. const mediaUpload = {
  11. data () {
  12. return {
  13. uploadCount: 0,
  14. uploadReady: true
  15. }
  16. },
  17. computed: {
  18. uploading () {
  19. return this.uploadCount > 0
  20. }
  21. },
  22. methods: {
  23. onClick () {
  24. if (this.uploadReady) {
  25. this.$refs.input.click()
  26. }
  27. },
  28. async resizeImage (file) {
  29. // Skip if not an image or if it's a GIF
  30. if (!file.type.startsWith('image/') || file.type === 'image/gif') {
  31. return file
  32. }
  33. // Skip if image compression is disabled
  34. if (!this.$store.getters.mergedConfig.imageCompression) {
  35. return file
  36. }
  37. // For PNGs, check if animated
  38. if (file.type === 'image/png') {
  39. const isAnimated = await this.isAnimatedPng(file)
  40. if (isAnimated) {
  41. return file
  42. }
  43. }
  44. return new Promise((resolve) => {
  45. const img = new Image()
  46. img.onload = () => {
  47. // Calculate new dimensions
  48. let width = img.width
  49. let height = img.height
  50. const maxSize = 2048
  51. if (width > maxSize || height > maxSize) {
  52. if (width > height) {
  53. height = Math.round((height * maxSize) / width)
  54. width = maxSize
  55. } else {
  56. width = Math.round((width * maxSize) / height)
  57. height = maxSize
  58. }
  59. }
  60. // Create canvas and resize
  61. const canvas = document.createElement('canvas')
  62. canvas.width = width
  63. canvas.height = height
  64. const ctx = canvas.getContext('2d')
  65. ctx.drawImage(img, 0, 0, width, height)
  66. // Check WebP support by trying to create a WebP canvas
  67. const testCanvas = document.createElement('canvas')
  68. const supportsWebP = testCanvas.toDataURL('image/webp').startsWith('data:image/webp')
  69. // Convert to WebP if supported, otherwise JPEG
  70. const type = supportsWebP ? 'image/webp' : 'image/jpeg'
  71. const extension = supportsWebP ? '.webp' : '.jpg'
  72. // Remove the original extension and add new one
  73. const newFileName = file.name.replace(/\.[^/.]+$/, '') + extension
  74. canvas.toBlob((blob) => {
  75. resolve(new File([blob], newFileName, {
  76. type,
  77. lastModified: Date.now()
  78. }))
  79. }, type, 0.85)
  80. }
  81. img.src = URL.createObjectURL(file)
  82. })
  83. },
  84. async isAnimatedPng (file) {
  85. const buffer = await file.arrayBuffer()
  86. const view = new Uint8Array(buffer)
  87. // Look for animated PNG chunks (acTL)
  88. for (let i = 0; i < view.length - 8; i++) {
  89. if (view[i] === 0x61 && // a
  90. view[i + 1] === 0x63 && // c
  91. view[i + 2] === 0x54 && // T
  92. view[i + 3] === 0x4C) { // L
  93. return true
  94. }
  95. }
  96. return false
  97. },
  98. async uploadFile (file) {
  99. const self = this
  100. const store = this.$store
  101. if (file.size > store.state.instance.uploadlimit) {
  102. const filesize = fileSizeFormatService.fileSizeFormat(file.size)
  103. const allowedsize = fileSizeFormatService.fileSizeFormat(store.state.instance.uploadlimit)
  104. self.$emit('upload-failed', 'file_too_big', { filesize: filesize.num, filesizeunit: filesize.unit, allowedsize: allowedsize.num, allowedsizeunit: allowedsize.unit })
  105. return
  106. }
  107. // Resize image if needed
  108. const processedFile = await this.resizeImage(file)
  109. const formData = new FormData()
  110. formData.append('file', processedFile)
  111. self.$emit('uploading')
  112. self.uploadCount++
  113. statusPosterService.uploadMedia({ store, formData })
  114. .then((fileData) => {
  115. self.$emit('uploaded', fileData)
  116. self.decreaseUploadCount()
  117. }, (error) => {
  118. console.error('Error uploading file', error)
  119. self.$emit('upload-failed', 'default')
  120. self.decreaseUploadCount()
  121. })
  122. },
  123. decreaseUploadCount () {
  124. this.uploadCount--
  125. if (this.uploadCount === 0) {
  126. this.$emit('all-uploaded')
  127. }
  128. },
  129. clearFile () {
  130. this.uploadReady = false
  131. this.$nextTick(() => {
  132. this.uploadReady = true
  133. })
  134. },
  135. multiUpload (files) {
  136. for (const file of files) {
  137. this.uploadFile(file)
  138. }
  139. },
  140. change ({ target }) {
  141. this.multiUpload(target.files)
  142. }
  143. },
  144. props: {
  145. dropFiles: Object,
  146. disabled: Boolean,
  147. normalButton: Boolean,
  148. acceptTypes: {
  149. type: String,
  150. default: '*/*'
  151. }
  152. },
  153. watch: {
  154. dropFiles: function (fileInfos) {
  155. if (!this.uploading) {
  156. this.multiUpload(fileInfos)
  157. }
  158. }
  159. }
  160. }
  161. export default mediaUpload