diff --git a/src/components/card/AttachmentList.vue b/src/components/card/AttachmentList.vue
index 914aa3dc1..36b2a8dce 100644
--- a/src/components/card/AttachmentList.vue
+++ b/src/components/card/AttachmentList.vue
@@ -46,9 +46,9 @@
.{{ attachmentExtension(attachment) }}
- {{ formattedFileSize(attachment.extendedData.filesize) }}
+ {{ formattedFileSize(attachment.extendedData?.filesize) }}
{{ relativeDate(attachment.createdAt*1000) }}
- {{ attachment.extendedData.attachmentCreator.displayName }}
+ {{ attachment.extendedData?.attachmentCreator?.displayName }}
{{ t('deck', 'Pending share') }}
@@ -158,7 +158,7 @@ export default {
if (!attachment) {
return {}
}
- const url = attachment.extendedData.hasPreview ? this.attachmentPreview(attachment) : OC.MimeType.getIconUrl(attachment.extendedData.mimetype)
+ const url = attachment?.extendedData?.hasPreview ? this.attachmentPreview(attachment) : OC.MimeType.getIconUrl(attachment?.extendedData?.mimetype)
const styles = {
'background-image': `url("${url}")`,
}
@@ -166,16 +166,16 @@ export default {
}
},
attachmentPreview() {
- return (attachment) => (attachment.extendedData.fileid ? generateUrl(`/core/preview?fileId=${attachment.extendedData.fileid}&x=64&y=64`) : null)
+ return (attachment) => (attachment?.extendedData?.fileid ? generateUrl(`/core/preview?fileId=${attachment.extendedData.fileid}&x=64&y=64`) : null)
},
attachmentUrl() {
- return (attachment) => generateUrl(`/apps/deck/cards/${attachment.cardId}/attachment/${attachment.id}`)
+ return (attachment) => (attachment?.cardId && attachment?.id ? generateUrl(`/apps/deck/cards/${attachment.cardId}/attachment/${attachment.id}`) : '#')
},
internalLink() {
- return (attachment) => generateUrl('/f/' + attachment.extendedData.fileid)
+ return (attachment) => (attachment?.extendedData?.fileid ? generateUrl('/f/' + attachment.extendedData.fileid) : '#')
},
downloadLink() {
- return (attachment) => generateRemoteUrl(`dav/files/${getCurrentUser().uid}/${attachment.extendedData.path}`)
+ return (attachment) => (attachment?.extendedData?.path ? generateRemoteUrl(`dav/files/${getCurrentUser().uid}/${attachment.extendedData.path}`) : '#')
},
formattedFileSize() {
return (filesize) => formatFileSize(filesize)
@@ -196,11 +196,11 @@ export default {
},
attachmentBasename() {
return (attachment) => attachment?.extendedData?.info?.filename
- ?? (attachment?.name ?? attachment.data).replace(/\.[^/.]+$/, '')
+ ?? (attachment?.name ?? attachment?.data ?? '').replace(/\.[^/.]+$/, '')
},
attachmentExtension() {
return (attachment) => attachment?.extendedData?.info?.extension
- ?? (attachment?.name ?? attachment.data).split('.').pop()
+ ?? (attachment?.name ?? attachment?.data ?? '').split('.').pop()
},
cardDetailsInModal() {
return useSettingsStore().configByKey('cardDetailsInModal')
diff --git a/src/components/card/Description.vue b/src/components/card/Description.vue
index 8da0a6019..083619a11 100644
--- a/src/components/card/Description.vue
+++ b/src/components/card/Description.vue
@@ -182,8 +182,12 @@ export default {
this.descriptionOld = newCard.description
this.description = newCard.description
- if (this.editor) {
- this.editor.setContent(this.description)
+ if (this.editor && typeof this.editor.setContent === 'function') {
+ try {
+ this.editor.setContent(this.description)
+ } catch (e) {
+ console.debug('Failed to set editor content', e)
+ }
}
showWarning(t('deck', 'The description has been changed by another user.'), { timeout: 3000 })
}
@@ -205,25 +209,42 @@ export default {
this.descriptionLastEdit = 0
this.descriptionOld = this.card.description
this.description = this.card.description
- this.editor = await window.OCA.Text.createEditor({
- el: this.$refs.editor,
- content: this.card.description,
- readOnly: !this.canEdit,
- onLoaded: () => {
- this.descriptionLastEdit = 0
- },
- onUpdate: ({ markdown }) => {
- if (this.description === markdown) {
- return
+ if (!window.OCA?.Text?.createEditor || !this.$refs.editor) {
+ return
+ }
+ try {
+ const editor = await window.OCA.Text.createEditor({
+ el: this.$refs.editor,
+ content: this.card.description,
+ readOnly: !this.canEdit,
+ onLoaded: () => {
+ this.descriptionLastEdit = 0
+ },
+ onUpdate: ({ markdown }) => {
+ if (this.description === markdown) {
+ return
+ }
+ this.description = markdown
+ this.updateDescription()
+ },
+ onFileInsert: () => {
+ this.showAttachmentModal()
+ },
+ })
+ if (this._isBeingDestroyed || this._isDestroyed) {
+ if (editor && typeof editor.destroy === 'function') {
+ try {
+ await editor.destroy()
+ } catch (e) {
+ // Ignore teardown error on already destroyed component
+ }
}
- this.description = markdown
- this.updateDescription()
- },
- onFileInsert: () => {
- this.showAttachmentModal()
- },
- })
-
+ return
+ }
+ this.editor = editor
+ } catch (e) {
+ console.warn('Failed to initialize text editor', e)
+ }
},
async destroyEditor() {
await this.saveDescription()
@@ -273,7 +294,9 @@ export default {
const asImage = (attachment.type === 'file' && attachment.extendedData.hasPreview) || attachment.extendedData.mimetype.includes('image')
// We need to strip those as text does not support rtl yet, so we cannot insert them separately
const stripRTLO = (text) => text.replaceAll('\u202e', '')
- const fileName = stripRTLO(attachment.extendedData.info.filename) + '.' + stripRTLO(attachment.extendedData.info.extension)
+ const base = attachment?.extendedData?.info?.filename ?? attachment?.data ?? ''
+ const ext = attachment?.extendedData?.info?.extension
+ const fileName = stripRTLO(base) + (ext ? '.' + stripRTLO(ext) : '')
if (this.editor) {
this.editor.insertAtCursor(
asImage