Skip to content

Commit

Permalink
Merge pull request #3955 from nextcloud/backport/3909/stable26
Browse files Browse the repository at this point in the history
[stable26] Get mimeIconUrl for media attachments without a session
  • Loading branch information
mejo- authored Mar 23, 2023
2 parents fb2db17 + b1e7486 commit 8676bc6
Show file tree
Hide file tree
Showing 21 changed files with 218 additions and 63 deletions.
4 changes: 2 additions & 2 deletions js/editor.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion js/editor.js.map

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions js/text-editors.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion js/text-editors.js.map

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions js/text-files.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion js/text-files.js.map

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions js/text-public.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion js/text-public.js.map

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions js/text-text.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion js/text-text.js.map

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions js/text-viewer.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion js/text-viewer.js.map

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions js/vendors.js

Large diffs are not rendered by default.

89 changes: 89 additions & 0 deletions js/vendors.js.LICENSE.txt
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,51 @@

/*! ieee754. BSD-3-Clause License. Feross Aboukhadijeh <https://feross.org/opensource> */

/**
* @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
*
* @author Christoph Wurst <christoph@winzerhof-wurst.at>
*
* @license AGPL-3.0-or-later
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

/**
* @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
*
* @author Christoph Wurst <christoph@winzerhof-wurst.at>
* @author John Molakvoæ <skjnldsv@protonmail.com>
*
* @license AGPL-3.0-or-later
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

/**
* @copyright Copyright (c) 2019 Georg Ehrke
*
Expand Down Expand Up @@ -132,6 +177,50 @@
*
*/

/**
* @copyright Copyright (c) 2021 John Molakvoæ <skjnldsv@protonmail.com>
*
* @author John Molakvoæ <skjnldsv@protonmail.com>
*
* @license AGPL-3.0-or-later
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

/**
* @copyright Copyright (c) 2022 John Molakvoæ <skjnldsv@protonmail.com>
*
* @author John Molakvoæ <skjnldsv@protonmail.com>
*
* @license AGPL-3.0-or-later
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

//! authors : Tim Wood, Iskren Chernev, Moment.js contributors

//! license : MIT
Expand Down
2 changes: 1 addition & 1 deletion js/vendors.js.map

Large diffs are not rendered by default.

25 changes: 25 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
"@nextcloud/browser-storage": "^0.2.0",
"@nextcloud/dialogs": "^4.0.1",
"@nextcloud/event-bus": "^3.0.2",
"@nextcloud/files": "^3.0.0-beta.7",
"@nextcloud/initial-state": "^2.0.0",
"@nextcloud/l10n": "^2.1.0",
"@nextcloud/logger": "^2.5.0",
Expand Down
4 changes: 2 additions & 2 deletions src/components/ImageView/ShowImageModal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
:has-next="true"
:has-previous="true"
:close-button-contained="false"
dark="true"
:dark="true"
@next="showNextImage"
@previous="showPreviousImage"
@close="$emit('close')">
Expand All @@ -33,7 +33,7 @@ export default {
validator(imagesList) {
return (imagesList.length === 0)
? true
: imagesList.findIndex(({ basename, source }) => !(basename && source)) !== -1
: imagesList.every(image => image.basename && image.source)
},
},
startIndex: {
Expand Down
19 changes: 11 additions & 8 deletions src/nodes/ImageView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -280,28 +280,30 @@ export default {
},
methods: {
async init() {
const candidates = this.$attachmentResolver.resolve(this.src)
const candidates = await this.$attachmentResolver.resolve(this.src)
return this.load(candidates)
},
async load(candidates) {
const [candidate, ...fallbacks] = candidates
return this.loadImage(candidate.url, candidate.type, candidate.name).catch((e) => {
return this.loadImage(candidate.url, candidate.type, candidate.name, candidate.metadata).catch((e) => {
if (fallbacks.length > 0) {
return this.load(fallbacks)
// TODO if fallback works, rewrite the url with correct document ID
}
return Promise.reject(e)
})
},
async loadImage(imageUrl, attachmentType, name = null) {
async loadImage(imageUrl, attachmentType, name = null, metadata = null) {
return new Promise((resolve, reject) => {
const img = new Image()
img.onload = async () => {
this.imageUrl = imageUrl
this.imageLoaded = true
this.loaded = true
this.attachmentType = attachmentType
if (attachmentType === this.$attachmentResolver.ATTACHMENT_TYPE_MEDIA) {
if (attachmentType === this.$attachmentResolver.ATTACHMENT_TYPE_MEDIA && metadata) {
this.attachmentMetadata = metadata
} else if (attachmentType === this.$attachmentResolver.ATTACHMENT_TYPE_MEDIA) {
await this.loadMediaMetadata(name)
}
resolve(imageUrl)
Expand Down Expand Up @@ -340,20 +342,21 @@ export default {
onLoaded() {
this.loaded = true
},
handleImageClick(src) {
async handleImageClick(src) {
const imageViews = Array.from(document.querySelectorAll('figure[data-component="image-view"].image-view'))
let basename, relativePath

imageViews.forEach(imgv => {
for (const imgv of imageViews) {
relativePath = imgv.getAttribute('data-src')
basename = relativePath.split('/').slice(-1).join()
const { url: source } = this.$attachmentResolver.resolve(relativePath, true).shift()
const response = await this.$attachmentResolver.resolve(relativePath, true)
const { url: source } = response.shift()
this.embeddedImagesList.push({
source,
basename,
relativePath,
})
})
}
this.imageIndex = this.embeddedImagesList.findIndex(image => image.relativePath === src)
this.showImageModal = true
},
Expand Down
42 changes: 38 additions & 4 deletions src/services/AttachmentResolver.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@

import { generateUrl, generateRemoteUrl } from '@nextcloud/router'
import pathNormalize from 'path-normalize'
import axios from '@nextcloud/axios'
import { formatFileSize } from '@nextcloud/files'

import { logger } from '../helpers/logger.js'

Expand Down Expand Up @@ -53,7 +55,7 @@ export default class AttachmentResolver {
*
* Currently returns either one or two urls.
*/
resolve(src, preferRawImage = false) {
async resolve(src, preferRawImage = false) {
if (this.#session && src.startsWith('text://')) {
const imageFileName = getQueryVariable(src, 'imageFileName')
return [{
Expand All @@ -62,6 +64,7 @@ export default class AttachmentResolver {
}]
}

// Has session and URL points to attachment from current document
if (this.#session && src.startsWith(`.attachments.${this.#session?.documentId}/`)) {
const imageFileName = decodeURIComponent(src.replace(`.attachments.${this.#session?.documentId}/`, '').split('?')[0])
return [
Expand Down Expand Up @@ -91,11 +94,11 @@ export default class AttachmentResolver {
}]
}

// if it starts with '.attachments.1234/'
if (src.match(/^\.attachments\.\d+\//)) {
// Has session and URL points to attachment from a (different) text document
if (this.#session && src.match(/^\.attachments\.\d+\//)) {
const imageFileName = this.#relativePath(src)
.replace(/\.attachments\.\d+\//, '')
// try the webdav url and attachment API if it fails
// Try webdav URL, use attachment API as fallback
return [
{
type: this.ATTACHMENT_TYPE_IMAGE,
Expand All @@ -113,6 +116,26 @@ export default class AttachmentResolver {
]
}

// Doesn't have session and URL points to attachment from (current or different) text document
if (!this.#session && src.match(/^\.attachments\.\d+\//)) {
const imageFileName = this.#relativePath(src)
.replace(/\.attachments\.\d+\//, '')
const { mimeType, size } = await this.getMetadata(this.#davUrl(src))
// Without session, use webdav URL for images and mimetype icon for media attachments
return [
{
type: this.ATTACHMENT_TYPE_IMAGE,
url: this.#davUrl(src),
},
{
type: this.ATTACHMENT_TYPE_MEDIA,
url: this.getMimeUrl(mimeType),
metadata: { size },
name: imageFileName,
},
]
}

return [{
type: this.ATTACHMENT_TYPE_IMAGE,
url: this.#davUrl(src),
Expand Down Expand Up @@ -249,6 +272,17 @@ export default class AttachmentResolver {
return pathNormalize(f)
}

async getMetadata(src) {
const headResponse = await axios.head(src)
const mimeType = headResponse.headers['content-type']
const size = formatFileSize(headResponse.headers['content-length'])
return { mimeType, size }
}

getMimeUrl(mimeType) {
return mimeType ? OC.MimeType.getIconUrl(mimeType) : null
}

}

/**
Expand Down
Loading

0 comments on commit 8676bc6

Please sign in to comment.