diff --git a/src/becca/entities/bnote.js b/src/becca/entities/bnote.js index f2acf31e0..27cad3f26 100644 --- a/src/becca/entities/bnote.js +++ b/src/becca/entities/bnote.js @@ -1635,24 +1635,32 @@ class BNote extends AbstractBeccaEntity { } /** + * @param {string} matchBy - choose by which property we detect if to update an existing attachment. + * Supported values are either 'attachmentId' (default) or 'title' * @returns {BAttachment} */ - saveAttachment({attachmentId, role, mime, title, content, position}) { + saveAttachment({attachmentId, role, mime, title, content, position}, matchBy = 'attachmentId') { + if (!['attachmentId', 'title'].includes(matchBy)) { + throw new Error(`Unsupported value '${matchBy}' for matchBy param, has to be either 'attachmentId' or 'title'.`); + } + let attachment; - if (attachmentId) { + if (matchBy === 'title') { + attachment = this.getAttachmentByTitle(title); + } else if (matchBy === 'attachmentId' && attachmentId) { attachment = this.becca.getAttachmentOrThrow(attachmentId); - } else { - attachment = new BAttachment({ - ownerId: this.noteId, - title, - role, - mime, - isProtected: this.isProtected, - position - }); } + attachment = attachment || new BAttachment({ + ownerId: this.noteId, + title, + role, + mime, + isProtected: this.isProtected, + position + }); + content = content || ""; attachment.setContent(content, {forceSave: true}); diff --git a/src/public/app/layouts/desktop_layout.js b/src/public/app/layouts/desktop_layout.js index 05b4a386e..18f44cf89 100644 --- a/src/public/app/layouts/desktop_layout.js +++ b/src/public/app/layouts/desktop_layout.js @@ -78,7 +78,7 @@ import HideFloatingButtonsButton from "../widgets/floating_buttons/hide_floating import ScriptExecutorWidget from "../widgets/ribbon_widgets/script_executor.js"; import MovePaneButton from "../widgets/buttons/move_pane_button.js"; import UploadAttachmentsDialog from "../widgets/dialogs/upload_attachments.js"; -import CanvasPropertiesWidget from "../widgets/ribbon_widgets/canvas_properties.js"; +import CopyImageReferenceButton from "../widgets/floating_buttons/copy_image_reference_button.js"; export default class DesktopLayout { constructor(customWidgets) { @@ -145,7 +145,6 @@ export default class DesktopLayout { .ribbon(new NotePropertiesWidget()) .ribbon(new FilePropertiesWidget()) .ribbon(new ImagePropertiesWidget()) - .ribbon(new CanvasPropertiesWidget()) .ribbon(new BasicPropertiesWidget()) .ribbon(new OwnedAttributeListWidget()) .ribbon(new InheritedAttributesWidget()) @@ -162,6 +161,7 @@ export default class DesktopLayout { .child(new EditButton()) .child(new CodeButtonsWidget()) .child(new RelationMapButtons()) + .child(new CopyImageReferenceButton()) .child(new MermaidExportButton()) .child(new BacklinksWidget()) .child(new HideFloatingButtonsButton()) diff --git a/src/public/app/services/note_content_renderer.js b/src/public/app/services/note_content_renderer.js deleted file mode 100644 index e69de29bb..000000000 diff --git a/src/public/app/widgets/dialogs/revisions.js b/src/public/app/widgets/dialogs/revisions.js index d5a56328c..1799ce37a 100644 --- a/src/public/app/widgets/dialogs/revisions.js +++ b/src/public/app/widgets/dialogs/revisions.js @@ -242,7 +242,7 @@ export default class RevisionsDialog extends BasicWidget { renderMathInElement(this.$content[0], {trust: true}); } - } else if (revisionItem.type === 'code' || revisionItem.type === 'mermaid') { + } else if (revisionItem.type === 'code') { this.$content.html($("
").text(fullRevision.content)); } else if (revisionItem.type === 'image') { this.$content.html($("") @@ -279,6 +279,14 @@ export default class RevisionsDialog extends BasicWidget { this.$content.html($("
") .attr("src", `api/revisions/${revisionItem.revisionId}/image/${sanitizedTitle}?${Math.random()}`) .css("max-width", "100%")); + } else if (revisionItem.type === 'mermaid') { + const sanitizedTitle = revisionItem.title.replace(/[^a-z0-9-.]/gi, ""); + + this.$content.html($("
") + .attr("src", `api/revisions/${revisionItem.revisionId}/image/${sanitizedTitle}?${Math.random()}`) + .css("max-width", "100%")); + + this.$content.append($("
").text(fullRevision.content)); } else { this.$content.text("Preview isn't available for this note type."); } diff --git a/src/public/app/widgets/floating_buttons/copy_image_reference_button.js b/src/public/app/widgets/floating_buttons/copy_image_reference_button.js new file mode 100644 index 000000000..025d5b238 --- /dev/null +++ b/src/public/app/widgets/floating_buttons/copy_image_reference_button.js @@ -0,0 +1,40 @@ +import NoteContextAwareWidget from "../note_context_aware_widget.js"; +import utils from "../../services/utils.js"; +import imageService from "../../services/image.js"; + +const TPL = ` +`; + +export default class CopyImageReferenceButton extends NoteContextAwareWidget { + isEnabled() { + return super.isEnabled() + && ['mermaid', 'canvas'].includes(this.note?.type) + && this.note.isContentAvailable() + && this.noteContext?.viewScope.viewMode === 'default'; + } + + doRender() { + super.doRender(); + + this.$widget = $(TPL); + this.$hiddenImageCopy = this.$widget.find(".hidden-image-copy"); + + this.$widget.on('click', () => { + this.$hiddenImageCopy.empty().append( + $("") + .attr("src", utils.createImageSrcUrl(this.note)) + ); + + imageService.copyImageReferenceToClipboard(this.$hiddenImageCopy); + + this.$hiddenImageCopy.empty(); + }); + this.contentSized(); + } +} diff --git a/src/public/app/widgets/mermaid.js b/src/public/app/widgets/mermaid.js index b64eb2564..9fc2928b0 100644 --- a/src/public/app/widgets/mermaid.js +++ b/src/public/app/widgets/mermaid.js @@ -1,5 +1,6 @@ import libraryLoader from "../services/library_loader.js"; import NoteContextAwareWidget from "./note_context_aware_widget.js"; +import server from "../services/server.js"; const TPL = `