summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorDorra <dorra.jaoued7@gmail.com>2024-06-20 11:24:33 +0200
committerGitHub <noreply@github.com>2024-06-20 11:24:33 +0200
commit38bfcad79113a110084789db21e93cbaed668627 (patch)
treecc9600016476cc42fae14e99e588cc1435ae0bff /src
parent9c4bd461dd772907b02928c1aee360bc9ae36101 (diff)
parentc39ebd20e8f481d393a26dcd4c6df412c786e2b0 (diff)
Merge pull request #12549 from nextcloud/fix/file-preview-binding
Fix: replace v-bind with object prop passing
Diffstat (limited to 'src')
-rw-r--r--src/components/MessagesList/MessagesGroup/Message/Message.spec.js4
-rw-r--r--src/components/MessagesList/MessagesGroup/Message/Message.vue5
-rw-r--r--src/components/MessagesList/MessagesGroup/Message/MessagePart/FilePreview.spec.js76
-rw-r--r--src/components/MessagesList/MessagesGroup/Message/MessagePart/FilePreview.vue187
-rw-r--r--src/components/NewMessage/NewMessageUploadEditor.vue2
-rw-r--r--src/components/Quote.vue5
-rw-r--r--src/components/RightSidebar/SharedItems/SharedItems.vue2
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)