diff options
author | Dorra <dorra.jaoued7@gmail.com> | 2024-06-20 11:24:33 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-06-20 11:24:33 +0200 |
commit | 38bfcad79113a110084789db21e93cbaed668627 (patch) | |
tree | cc9600016476cc42fae14e99e588cc1435ae0bff /src | |
parent | 9c4bd461dd772907b02928c1aee360bc9ae36101 (diff) | |
parent | c39ebd20e8f481d393a26dcd4c6df412c786e2b0 (diff) |
Merge pull request #12549 from nextcloud/fix/file-preview-binding
Fix: replace v-bind with object prop passing
Diffstat (limited to 'src')
7 files changed, 93 insertions, 188 deletions
diff --git a/src/components/MessagesList/MessagesGroup/Message/Message.spec.js b/src/components/MessagesList/MessagesGroup/Message/Message.spec.js index a2446de3d..f5089ddb9 100644 --- a/src/components/MessagesList/MessagesGroup/Message/Message.spec.js +++ b/src/components/MessagesList/MessagesGroup/Message/Message.spec.js @@ -395,7 +395,7 @@ describe('Message.vue', () => { }, file: { component: FilePreview, - props: params.file, + props: { file: params.file }, }, } ) @@ -423,7 +423,7 @@ describe('Message.vue', () => { }, file: { component: FilePreview, - props: params.file, + props: { file: params.file }, }, } ) diff --git a/src/components/MessagesList/MessagesGroup/Message/Message.vue b/src/components/MessagesList/MessagesGroup/Message/Message.vue index 7e49ff5f9..fcc3a2542 100644 --- a/src/components/MessagesList/MessagesGroup/Message/Message.vue +++ b/src/components/MessagesList/MessagesGroup/Message/Message.vue @@ -268,11 +268,12 @@ export default { } else if (type === 'file' && mimetype !== 'text/vcard') { richParameters[p] = { component: FilePreview, - props: Object.assign({ + props: { token: this.message.token, itemType, referenceId: this.message.referenceId, - }, this.message.messageParameters[p]), + file: this.message.messageParameters[p], + }, } } else if (type === 'deck-card') { richParameters[p] = { diff --git a/src/components/MessagesList/MessagesGroup/Message/MessagePart/FilePreview.spec.js b/src/components/MessagesList/MessagesGroup/Message/MessagePart/FilePreview.spec.js index aaa056fa2..6bb541226 100644 --- a/src/components/MessagesList/MessagesGroup/Message/MessagePart/FilePreview.spec.js +++ b/src/components/MessagesList/MessagesGroup/Message/MessagePart/FilePreview.spec.js @@ -51,14 +51,16 @@ describe('FilePreview.vue', () => { propsData = { token: 'TOKEN', - id: '123', - name: 'test.jpg', - path: 'path/to/test.jpg', - size: '128', - etag: '1872ade88f3013edeb33decd74a4f947', - permissions: '15', - mimetype: 'image/jpeg', - previewAvailable: 'yes', + file: { + id: '123', + name: 'test.jpg', + path: 'path/to/test.jpg', + size: '128', + etag: '1872ade88f3013edeb33decd74a4f947', + permissions: '15', + mimetype: 'image/jpeg', + 'preview-available': 'yes', + }, } }) @@ -96,7 +98,7 @@ describe('FilePreview.vue', () => { }) test('renders file preview for guests', async () => { - propsData.link = 'https://localhost/nc-webroot/s/xtokenx' + propsData.file.link = 'https://localhost/nc-webroot/s/xtokenx' getUserIdMock.mockClear().mockReturnValue(null) const wrapper = shallowMount(FilePreview, { @@ -172,10 +174,10 @@ describe('FilePreview.vue', () => { }], })) - propsData.id = 'temp-123' - propsData.index = 'index-1' - propsData.uploadId = 1000 - propsData.localUrl = 'blob:XYZ' + propsData.file.id = 'temp-123' + propsData.file.index = 'index-1' + propsData.file.uploadId = 1000 + propsData.file.localUrl = 'blob:XYZ' const wrapper = shallowMount(FilePreview, { localVue, @@ -224,7 +226,7 @@ describe('FilePreview.vue', () => { }) test('renders generic mime type icon for unknown mime types', async () => { - propsData.previewAvailable = 'no' + propsData.file['preview-available'] = 'no' OC.MimeType.getIconUrl.mockReturnValueOnce(imagePath('core', 'image/jpeg')) const wrapper = shallowMount(FilePreview, { @@ -244,12 +246,12 @@ describe('FilePreview.vue', () => { describe('gif rendering', () => { beforeEach(() => { - propsData.mimetype = 'image/gif' - propsData.name = 'test %20.gif' - propsData.path = 'path/to/test %20.gif' + propsData.file.mimetype = 'image/gif' + propsData.file.name = 'test %20.gif' + propsData.file.path = 'path/to/test %20.gif' }) test('directly renders small GIF files', async () => { - propsData.size = '128' + propsData.file.size = '128' const wrapper = shallowMount(FilePreview, { localVue, @@ -265,8 +267,8 @@ describe('FilePreview.vue', () => { }) test('directly renders small GIF files (absolute path)', async () => { - propsData.size = '128' - propsData.path = '/path/to/test %20.gif' + propsData.file.size = '128' + propsData.file.path = '/path/to/test %20.gif' const wrapper = shallowMount(FilePreview, { localVue, @@ -282,8 +284,8 @@ describe('FilePreview.vue', () => { }) test('directly renders small GIF files for guests', async () => { - propsData.size = '128' - propsData.link = 'https://localhost/nc-webroot/s/xtokenx' + propsData.file.size = '128' + propsData.file.link = 'https://localhost/nc-webroot/s/xtokenx' getUserIdMock.mockClear().mockReturnValue(null) const wrapper = shallowMount(FilePreview, { @@ -296,12 +298,12 @@ describe('FilePreview.vue', () => { expect(wrapper.element.tagName).toBe('A') expect(wrapper.find('img').attributes('src')) - .toBe(propsData.link + '/download/test%20%2520.gif') + .toBe(propsData.file.link + '/download/test%20%2520.gif') }) test('renders static preview for big GIF files', async () => { // 4 MB, bigger than max from capability (3 MB) - propsData.size = '4194304' + propsData.file.size = '4194304' const wrapper = shallowMount(FilePreview, { localVue, @@ -425,9 +427,9 @@ describe('FilePreview.vue', () => { describe('play icon for video', () => { beforeEach(() => { - propsData.mimetype = 'video/mp4' - propsData.name = 'test.mp4' - propsData.path = 'path/to/test.mp4' + propsData.file.mimetype = 'video/mp4' + propsData.file.name = 'test.mp4' + propsData.file.path = 'path/to/test.mp4' // viewer needs to be available OCA.Viewer = { @@ -460,19 +462,19 @@ describe('FilePreview.vue', () => { test('does not render play icon for direct renders', async () => { // gif is directly rendered - propsData.mimetype = 'image/gif' - propsData.name = 'test.gif' - propsData.path = 'path/to/test.gif' + propsData.file.mimetype = 'image/gif' + propsData.file.name = 'test.gif' + propsData.file.path = 'path/to/test.gif' await testPlayButtonVisible(false) }) test('render play icon gif previews with big size', async () => { // gif is directly rendered - propsData.mimetype = 'image/gif' - propsData.name = 'test.gif' - propsData.path = 'path/to/test.gif' - propsData.size = '10000000' // bigger than default max + propsData.file.mimetype = 'image/gif' + propsData.file.name = 'test.gif' + propsData.file.path = 'path/to/test.gif' + propsData.file.size = '10000000' // bigger than default max await testPlayButtonVisible(true) }) @@ -502,9 +504,9 @@ describe('FilePreview.vue', () => { test('does not render play icon for non-videos', async () => { // viewer supported, but not a video - propsData.mimetype = 'image/png' - propsData.name = 'test.png' - propsData.path = 'path/to/test.png' + propsData.file.mimetype = 'image/png' + propsData.file.name = 'test.png' + propsData.file.path = 'path/to/test.png' await testPlayButtonVisible(false) }) }) diff --git a/src/components/MessagesList/MessagesGroup/Message/MessagePart/FilePreview.vue b/src/components/MessagesList/MessagesGroup/Message/MessagePart/FilePreview.vue index 086b0cf35..b7bb7447e 100644 --- a/src/components/MessagesList/MessagesGroup/Message/MessagePart/FilePreview.vue +++ b/src/components/MessagesList/MessagesGroup/Message/MessagePart/FilePreview.vue @@ -46,7 +46,7 @@ tabindex="1" type="primary" :aria-label="removeAriaLabel" - @click="$emit('remove-file', id)"> + @click="$emit('remove-file', file.id)"> <template #icon> <Close /> </template> @@ -103,13 +103,15 @@ export default { type: String, required: true, }, + /** - * File id + * File object */ - id: { - type: String, + file: { + type: Object, required: true, }, + /** * Reference id from the message */ @@ -117,81 +119,6 @@ export default { type: String, default: '', }, - /** - * File name - */ - name: { - type: String, - required: true, - }, - /** - * File path relative to the user's home storage, - * or link share root, includes the file name. - */ - path: { - type: String, - default: '', - }, - /** - * File size in bytes - */ - size: { - type: String, - default: '-1', - }, - /** - * Download link - */ - link: { - type: String, - default: '', - }, - /** - * Mime type - */ - mimetype: { - type: String, - default: '', - }, - /** - * File ETag - */ - etag: { - type: String, - default: '', - }, - /** - * File ETag - */ - permissions: { - type: String, - default: '0', - }, - /** - * Whether a preview is available, string "yes" for yes - * otherwise the string "no" - */ - // FIXME: use booleans here - previewAvailable: { - type: String, - default: 'no', - }, - - /** - * If preview and metadata are available, return width - */ - width: { - type: String, - default: null, - }, - - /** - * If preview and metadata are available, return height - */ - height: { - type: String, - default: null, - }, /** * Whether to render a small preview to embed in replies @@ -200,26 +127,7 @@ export default { type: Boolean, default: false, }, - /** - * Upload id from the file upload store. - * - * In case this component is used to display a file that is being uploaded - * this parameter is used to access the file upload status in the store - */ - uploadId: { - type: Number, - default: null, - }, - /** - * File upload index from the file upload store. - * - * In case this component is used to display a file that is being uploaded - * this parameter is used to access the file upload status in the store - */ - index: { - type: String, - default: '', - }, + /** * Whether the container is the upload editor. * True if this component is used in the upload editor. @@ -229,13 +137,6 @@ export default { type: Boolean, default: false, }, - /** - * The link to the file for displaying it in the preview - */ - localUrl: { - type: String, - default: '', - }, rowLayout: { type: Boolean, @@ -281,9 +182,9 @@ export default { // is not easily recognizable, when: return ( // the file is not an image - !this.mimetype.startsWith('image/') + !this.file.mimetype.startsWith('image/') // the image has no preview (ex: disabled on server) - || (this.previewAvailable !== 'yes' && !this.localUrl) + || (this.file['preview-available'] !== 'yes' && !this.file.localUrl) // the preview failed loading || this.failed // always show in upload editor @@ -292,11 +193,11 @@ export default { }, fileDetail() { - return this.name + return this.file.name }, fallbackLocalUrl() { - if (!this.mimetype.startsWith('image/') && !this.mimetype.startsWith('video/')) { + if (!this.file.mimetype.startsWith('image/') && !this.file.mimetype.startsWith('video/')) { return undefined } return this.$store.getters.getLocalUrl(this.referenceId) @@ -308,7 +209,7 @@ export default { return null } return { - content: this.name, + content: this.file.name, delay: { show: 500 }, placement: 'left', } @@ -329,24 +230,24 @@ export default { return } else if (this.isVoiceMessage && !this.isSharedItems) { return { - name: this.name, - path: this.path, - link: this.link, + name: this.file.name, + path: this.file.path, + link: this.file.link, } } return { - href: this.link, + href: this.file.link, target: '_blank', rel: 'noopener noreferrer', } }, defaultIconUrl() { - return OC.MimeType.getIconUrl(this.mimetype) || imagePath('core', 'filetypes/file') + return OC.MimeType.getIconUrl(this.file.mimetype) || imagePath('core', 'filetypes/file') }, mediumPreview() { - return !this.mimetype.startsWith('image/') && !this.mimetype.startsWith('video/') + return !this.file.mimetype.startsWith('image/') && !this.file.mimetype.startsWith('video/') }, previewImageClass() { @@ -361,7 +262,7 @@ export default { if (this.failed || this.previewType === PREVIEW_TYPE.MIME_ICON || this.rowLayout) { classes += 'mimeicon' - } else if (this.previewAvailable === 'yes') { + } else if (this.file['preview-available'] === 'yes') { classes += 'media' } @@ -370,7 +271,7 @@ export default { imageContainerStyle() { // Fallback for loading mimeicons (preview for audio files is not provided) - if (this.previewAvailable !== 'yes' || this.mimetype.startsWith('audio/')) { + if (this.file['preview-available'] !== 'yes' || this.file.mimetype.startsWith('audio/')) { return { width: this.smallPreview ? '32px' : '128px', height: this.smallPreview ? '32px' : '128px', @@ -381,7 +282,7 @@ export default { const heightConstraint = this.smallPreview ? 32 : (this.mediumPreview ? 192 : 384) // Fallback when no metadata available - if (!this.width || !this.height) { + if (!this.file.width || !this.file.height) { return { width: widthConstraint + 'px', height: heightConstraint + 'px', @@ -389,13 +290,13 @@ export default { } const sizeMultiplicator = Math.min( - (heightConstraint > parseInt(this.height, 10) ? 1 : (heightConstraint / parseInt(this.height, 10))), - (widthConstraint > parseInt(this.width, 10) ? 1 : (widthConstraint / parseInt(this.width, 10))) + (heightConstraint > parseInt(this.file.height, 10) ? 1 : (heightConstraint / parseInt(this.file.height, 10))), + (widthConstraint > parseInt(this.file.width, 10) ? 1 : (widthConstraint / parseInt(this.file.width, 10))) ) return { - width: parseInt(this.width, 10) * sizeMultiplicator + 'px', - aspectRatio: this.width + '/' + this.height, + width: parseInt(this.file.width, 10) * sizeMultiplicator + 'px', + aspectRatio: this.file.width + '/' + this.file.height, } }, @@ -408,10 +309,10 @@ export default { return PREVIEW_TYPE.TEMPORARY } - if (this.previewAvailable !== 'yes') { + if (this.file['preview-available'] !== 'yes') { return PREVIEW_TYPE.MIME_ICON } - if (this.mimetype === 'image/gif' && parseInt(this.size, 10) <= this.maxGifSize) { + if (this.file.mimetype === 'image/gif' && parseInt(this.file.size, 10) <= this.maxGifSize) { return PREVIEW_TYPE.DIRECT } @@ -422,20 +323,20 @@ export default { const userId = this.$store.getters.getUserId() if (this.previewType === PREVIEW_TYPE.TEMPORARY) { - return this.localUrl + return this.file.localUrl } if (this.fallbackLocalUrl) { return this.fallbackLocalUrl } if (this.previewType === PREVIEW_TYPE.MIME_ICON || this.rowLayout) { - return OC.MimeType.getIconUrl(this.mimetype) + return OC.MimeType.getIconUrl(this.file.mimetype) } // whether to embed/render the file directly if (this.previewType === PREVIEW_TYPE.DIRECT) { // return direct image if (userId === null) { // guest mode, use public link download URL - return this.link + '/download/' + encodePath(this.name) + return this.file.link + '/download/' + encodePath(this.file.name) } else { // use direct DAV URL return generateRemoteUrl(`dav/files/${userId}`) + encodePath(this.internalAbsolutePath) @@ -451,14 +352,14 @@ export default { if (userId === null) { // guest mode: grab token from the link URL // FIXME: use a cleaner way... - const token = this.link.slice(this.link.lastIndexOf('/') + 1) + const token = this.file.link.slice(this.file.link.lastIndexOf('/') + 1) return generateUrl('/apps/files_sharing/publicpreview/{token}?x=-1&y={height}&a=1', { token, height: previewSize, }) } else { return generateUrl('/core/preview?fileId={fileId}&x=-1&y={height}&a=1', { - fileId: this.id, + fileId: this.file.id, height: previewSize, }) } @@ -471,7 +372,7 @@ export default { const availableHandlers = OCA.Viewer.availableHandlers for (let i = 0; i < availableHandlers.length; i++) { - if (availableHandlers[i]?.mimes?.includes && availableHandlers[i].mimes.includes(this.mimetype)) { + if (availableHandlers[i]?.mimes?.includes && availableHandlers[i].mimes.includes(this.file.mimetype)) { return true } } @@ -490,23 +391,23 @@ export default { } // videos only display a preview, so always show a button if playable - return this.mimetype === 'image/gif' || this.mimetype.startsWith('video/') + return this.file.mimetype === 'image/gif' || this.file.mimetype.startsWith('video/') }, internalAbsolutePath() { - return this.path.startsWith('/') ? this.path : '/' + this.path + return this.file.path.startsWith('/') ? this.file.path : '/' + this.file.path }, isTemporaryUpload() { - return this.id.startsWith('temp') && this.index && this.uploadId + return this.file.id.startsWith('temp') && this.file.index && this.file.uploadId }, uploadFile() { - return this.$store.getters.getUploadFile(this.uploadId, this.index) + return this.$store.getters.getUploadFile(this.file.uploadId, this.file.index) }, upload() { - return this.uploadManager?.queue.find(item => item._source.includes(this.uploadFile.sharePath)) + return this.uploadManager?.queue.find(item => item._source.includes(this.uploadFile?.sharePath)) }, uploadProgress() { @@ -528,11 +429,11 @@ export default { showUploadProgress() { return this.isTemporaryUpload && !this.isUploadEditor - && ['shared', 'sharing', 'successUpload', 'uploading'].includes(this.uploadFile?.status) + && ['shared', 'sharing', 'successUpload', 'uploading', 'failedUpload'].includes(this.uploadFile?.status) |