Skip to content

Commit 8ae54d5

Browse files
committed
chore(build): load VueCropper asynchronously
- used only on new conversation creation and opening conversation settings, which might not happen depending on user role Signed-off-by: Maksim Sukharev <antreesy.web@gmail.com>
1 parent 0f60852 commit 8ae54d5

1 file changed

Lines changed: 27 additions & 5 deletions

File tree

src/components/ConversationSettings/ConversationAvatarEditor.vue

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@
2121
hideUserStatus />
2222
<div v-else class="icon-loading" />
2323
</div>
24-
<VueCropper
24+
<component
25+
:is="cropperComponent"
2526
v-show="showCropper"
2627
ref="cropper"
2728
class="avatar__cropper"
@@ -114,7 +115,7 @@ import { getFilePickerBuilder } from '@nextcloud/dialogs'
114115
import { t } from '@nextcloud/l10n'
115116
import { generateUrl } from '@nextcloud/router'
116117
import { useIsDarkTheme } from '@nextcloud/vue/composables/useIsDarkTheme'
117-
import VueCropper from 'vue-cropperjs'
118+
import { markRaw } from 'vue'
118119
import NcButton from '@nextcloud/vue/components/NcButton'
119120
import NcColorPicker from '@nextcloud/vue/components/NcColorPicker'
120121
import NcEmojiPicker from '@nextcloud/vue/components/NcEmojiPicker'
@@ -127,7 +128,15 @@ import ConversationIcon from '../ConversationIcon.vue'
127128
import IconFileUpload from '../../../img/material-icons/file-upload.svg?raw'
128129
import { AVATAR } from '../../constants.ts'
129130
130-
import 'cropperjs/dist/cropper.css'
131+
// Asynchronous loader for VueCropper component
132+
let vueCropper = null
133+
function getCropperAsyncComponent() {
134+
vueCropper ??= Promise.all([
135+
import('vue-cropperjs'),
136+
import('cropperjs/dist/cropper.css'),
137+
]).then(([module]) => module.default)
138+
return vueCropper
139+
}
131140
132141
const validMimeTypes = ['image/png', 'image/jpeg']
133142
@@ -140,7 +149,6 @@ export default {
140149
NcColorPicker,
141150
NcEmojiPicker,
142151
NcIconSvgWrapper,
143-
VueCropper,
144152
// Icons
145153
IconTrashCanOutline,
146154
IconEmoticonOutline,
@@ -187,6 +195,7 @@ export default {
187195
188196
data() {
189197
return {
198+
cropperComponent: null,
190199
showCropper: false,
191200
loading: false,
192201
cropperOptions: {
@@ -239,7 +248,14 @@ export default {
239248
240249
methods: {
241250
t,
251+
252+
async waitForCropper() {
253+
this.cropperComponent ??= markRaw(await getCropperAsyncComponent())
254+
},
255+
242256
activateLocalFilePicker() {
257+
// Async request to load and set up component, while user picks the file
258+
getCropperAsyncComponent()
243259
// Set to null so that selecting the same file will trigger the change event
244260
this.$refs.input.value = null
245261
this.$refs.input.click()
@@ -255,14 +271,17 @@ export default {
255271
}
256272
257273
const reader = new FileReader()
258-
reader.onload = (e) => {
274+
reader.onload = async (e) => {
275+
await this.waitForCropper()
259276
this.$refs.cropper.replace(e.target.result)
260277
this.showCropper = true
261278
}
262279
reader.readAsDataURL(file)
263280
},
264281
265282
async showFilePicker() {
283+
// Async request to load and set up component, while user picks the file
284+
getCropperAsyncComponent()
266285
const filePicker = getFilePickerBuilder(t('spreed', 'Choose your conversation picture'))
267286
.setContainer('#vue-avatar-section')
268287
.setMultiSelect(false)
@@ -284,6 +303,7 @@ export default {
284303
}
285304
286305
try {
306+
await this.waitForCropper()
287307
const tempAvatar = generateUrl(`/core/preview?fileId=${fileid}&x=512&y=512&a=1`)
288308
this.$refs.cropper.replace(tempAvatar)
289309
this.showCropper = true
@@ -325,6 +345,8 @@ export default {
325345
},
326346
327347
async getPictureFormData() {
348+
// Cropper should be ready by this moment, so just a safeguard
349+
await this.waitForCropper()
328350
const canvasData = this.$refs.cropper.getCroppedCanvas()
329351
const scaleFactor = canvasData.width > 512 ? 512 / canvasData.width : 1
330352

0 commit comments

Comments
 (0)