2020-10-01 07:43:29 +02:00
|
|
|
import ComposerEditor from "discourse/components/composer-editor";
|
2020-11-11 12:37:30 +01:00
|
|
|
import {
|
2022-08-22 15:56:58 +02:00
|
|
|
bind,
|
2020-11-11 12:37:30 +01:00
|
|
|
default as discourseComputed,
|
|
|
|
on,
|
|
|
|
} from "discourse-common/utils/decorators";
|
2022-07-26 16:18:09 +02:00
|
|
|
import { findRawTemplate } from "discourse-common/lib/raw-templates";
|
2021-12-22 09:41:38 +01:00
|
|
|
import { scheduleOnce } from "@ember/runloop";
|
2021-04-12 08:26:22 +02:00
|
|
|
import { caretPosition, inCodeBlock } from "discourse/lib/utilities";
|
2020-10-01 07:43:29 +02:00
|
|
|
import highlightSyntax from "discourse/lib/highlight-syntax";
|
2020-10-06 11:30:24 +02:00
|
|
|
import { alias } from "@ember/object/computed";
|
2022-07-26 16:18:09 +02:00
|
|
|
import Site from "discourse/models/site";
|
2021-12-01 08:19:14 +01:00
|
|
|
import { uploadIcon } from "discourse/lib/uploads";
|
|
|
|
import { dasherize } from "@ember/string";
|
2023-03-10 03:34:40 +01:00
|
|
|
import showModal from "discourse/lib/show-modal";
|
2020-10-02 06:40:10 +02:00
|
|
|
|
2022-08-22 16:10:01 +02:00
|
|
|
const IMAGE_MARKDOWN_REGEX = /!\[(.*?)\|(\d{1,4}x\d{1,4})(,\s*\d{1,3}%)?(.*?)\]\((upload:\/\/.*?)\)(?!(.*`))/g;
|
2022-08-22 15:56:58 +02:00
|
|
|
|
2019-11-20 13:08:04 +01:00
|
|
|
export default ComposerEditor.extend({
|
2020-10-01 07:43:29 +02:00
|
|
|
classNameBindings: ["fieldClass"],
|
|
|
|
allowUpload: true,
|
2019-11-20 13:08:04 +01:00
|
|
|
showLink: false,
|
|
|
|
topic: null,
|
|
|
|
showToolbar: true,
|
|
|
|
focusTarget: "reply",
|
|
|
|
canWhisper: false,
|
2020-10-01 07:43:29 +02:00
|
|
|
lastValidatedAt: "lastValidatedAt",
|
2019-11-20 13:08:04 +01:00
|
|
|
popupMenuOptions: [],
|
2020-10-01 07:43:29 +02:00
|
|
|
draftStatus: "null",
|
2022-06-15 09:08:28 +02:00
|
|
|
replyPlaceholder: alias("field.translatedPlaceholder"),
|
2022-08-22 15:56:58 +02:00
|
|
|
wizardEventFieldId: null,
|
2020-10-01 07:43:29 +02:00
|
|
|
|
2019-11-20 13:08:04 +01:00
|
|
|
@on("didInsertElement")
|
|
|
|
_composerEditorInit() {
|
|
|
|
const $input = $(this.element.querySelector(".d-editor-input"));
|
2020-10-01 07:43:29 +02:00
|
|
|
|
2019-11-20 13:08:04 +01:00
|
|
|
if (this.siteSettings.enable_mentions) {
|
|
|
|
$input.autocomplete({
|
|
|
|
template: findRawTemplate("user-selector-autocomplete"),
|
2022-07-27 15:40:05 +02:00
|
|
|
dataSource: (term) => this._userSearchTerm.call(this, term),
|
2019-11-20 13:08:04 +01:00
|
|
|
key: "@",
|
2020-10-01 07:43:29 +02:00
|
|
|
transformComplete: (v) => v.username || v.name,
|
2020-10-02 03:38:32 +02:00
|
|
|
afterComplete: (value) => {
|
|
|
|
this.composer.set("reply", value);
|
2019-11-20 13:08:04 +01:00
|
|
|
scheduleOnce("afterRender", () => $input.blur().focus());
|
2020-10-01 07:43:29 +02:00
|
|
|
},
|
2020-10-02 03:38:32 +02:00
|
|
|
triggerRule: (textarea) =>
|
2020-11-11 12:37:30 +01:00
|
|
|
!inCodeBlock(textarea.value, caretPosition(textarea)),
|
2019-11-20 13:08:04 +01:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2021-10-06 13:55:50 +02:00
|
|
|
const siteSettings = this.siteSettings;
|
|
|
|
if (siteSettings.mentionables_enabled) {
|
|
|
|
Site.currentProp("mentionable_items", this.wizard.mentionable_items);
|
|
|
|
const { SEPARATOR } = requirejs(
|
|
|
|
"discourse/plugins/discourse-mentionables/discourse/lib/discourse-markdown/mentionable-items"
|
|
|
|
);
|
|
|
|
const { searchMentionableItem } = requirejs(
|
|
|
|
"discourse/plugins/discourse-mentionables/discourse/lib/mentionable-item-search"
|
|
|
|
);
|
|
|
|
|
|
|
|
$input.autocomplete({
|
|
|
|
template: findRawTemplate("javascripts/mentionable-item-autocomplete"),
|
|
|
|
key: SEPARATOR,
|
|
|
|
afterComplete: (value) => {
|
|
|
|
this.composer.set("reply", value);
|
|
|
|
scheduleOnce("afterRender", () => $input.blur().focus());
|
|
|
|
},
|
|
|
|
transformComplete: (item) => item.model.slug,
|
|
|
|
dataSource: (term) =>
|
|
|
|
term.match(/\s/) ? null : searchMentionableItem(term, siteSettings),
|
|
|
|
triggerRule: (textarea) =>
|
|
|
|
!inCodeBlock(textarea.value, caretPosition(textarea)),
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2021-12-22 09:41:38 +01:00
|
|
|
$input.on("scroll", this._throttledSyncEditorAndPreviewScroll);
|
2019-11-20 13:08:04 +01:00
|
|
|
this._bindUploadTarget();
|
2021-12-01 08:19:14 +01:00
|
|
|
|
|
|
|
const wizardEventNames = ["insert-text", "replace-text"];
|
|
|
|
const eventPrefix = this.eventPrefix;
|
|
|
|
this.appEvents.reopen({
|
|
|
|
trigger(name, ...args) {
|
|
|
|
let eventParts = name.split(":");
|
|
|
|
let currentEventPrefix = eventParts[0];
|
|
|
|
let currentEventName = eventParts[1];
|
|
|
|
|
|
|
|
if (
|
|
|
|
currentEventPrefix !== "wizard-editor" &&
|
|
|
|
wizardEventNames.some((wen) => wen === currentEventName)
|
|
|
|
) {
|
2022-08-22 15:56:58 +02:00
|
|
|
let wizardEventName = name.replace(eventPrefix, "wizard-editor");
|
|
|
|
return this._super(wizardEventName, ...args);
|
2021-12-01 08:19:14 +01:00
|
|
|
} else {
|
|
|
|
return this._super(name, ...args);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
});
|
|
|
|
},
|
|
|
|
|
|
|
|
@discourseComputed("field.id")
|
|
|
|
fileUploadElementId(fieldId) {
|
|
|
|
return `file-uploader-${dasherize(fieldId)}`;
|
2019-11-20 13:08:04 +01:00
|
|
|
},
|
2020-11-11 12:37:30 +01:00
|
|
|
|
2020-10-06 11:30:24 +02:00
|
|
|
@discourseComputed
|
|
|
|
allowedFileTypes() {
|
2020-11-11 12:37:30 +01:00
|
|
|
return this.siteSettings.authorized_extensions
|
|
|
|
.split("|")
|
|
|
|
.map((ext) => "." + ext)
|
|
|
|
.join(",");
|
2020-10-06 11:30:24 +02:00
|
|
|
},
|
2020-11-11 12:37:30 +01:00
|
|
|
|
2021-04-12 08:26:22 +02:00
|
|
|
@discourseComputed()
|
|
|
|
uploadIcon() {
|
2020-10-06 12:05:24 +02:00
|
|
|
return uploadIcon(false, this.siteSettings);
|
|
|
|
},
|
2020-11-11 12:37:30 +01:00
|
|
|
|
2022-08-22 15:56:58 +02:00
|
|
|
@bind
|
|
|
|
_handleImageDeleteButtonClick(event) {
|
|
|
|
if (!event.target.classList.contains("delete-image-button")) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
const index = parseInt(
|
|
|
|
event.target.closest(".button-wrapper").dataset.imageIndex,
|
|
|
|
10
|
|
|
|
);
|
2022-08-22 16:10:01 +02:00
|
|
|
const matchingPlaceholder = this.get("composer.reply").match(
|
|
|
|
IMAGE_MARKDOWN_REGEX
|
|
|
|
);
|
2022-08-22 15:56:58 +02:00
|
|
|
|
|
|
|
this.session.set("wizardEventFieldId", this.field.id);
|
|
|
|
this.appEvents.trigger(
|
|
|
|
"composer:replace-text",
|
|
|
|
matchingPlaceholder[index],
|
|
|
|
"",
|
|
|
|
{ regex: IMAGE_MARKDOWN_REGEX, index }
|
|
|
|
);
|
|
|
|
},
|
|
|
|
|
2019-11-20 13:08:04 +01:00
|
|
|
actions: {
|
|
|
|
extraButtons(toolbar) {
|
2020-10-02 06:40:10 +02:00
|
|
|
const component = this;
|
2020-11-11 12:37:30 +01:00
|
|
|
|
2022-11-07 15:04:30 +01:00
|
|
|
if (this.allowUpload && this.uploadIcon) {
|
2019-11-20 13:08:04 +01:00
|
|
|
toolbar.addButton({
|
|
|
|
id: "upload",
|
|
|
|
group: "insertions",
|
|
|
|
icon: this.uploadIcon,
|
|
|
|
title: "upload",
|
2020-10-02 06:40:10 +02:00
|
|
|
sendAction: (event) => component.send("showUploadModal", event),
|
2019-11-20 13:08:04 +01:00
|
|
|
});
|
|
|
|
}
|
2020-10-01 15:48:20 +02:00
|
|
|
|
|
|
|
toolbar.addButton({
|
|
|
|
id: "link",
|
|
|
|
group: "insertions",
|
|
|
|
shortcut: "K",
|
|
|
|
trimLeading: true,
|
2020-10-02 02:33:01 +02:00
|
|
|
unshift: true,
|
2023-03-10 03:34:40 +01:00
|
|
|
sendAction: (event) => component.send("showLinkModal", event),
|
2020-10-01 15:48:20 +02:00
|
|
|
});
|
2021-10-06 13:55:50 +02:00
|
|
|
|
|
|
|
if (this.siteSettings.mentionables_enabled) {
|
|
|
|
const { SEPARATOR } = requirejs(
|
|
|
|
"discourse/plugins/discourse-mentionables/discourse/lib/discourse-markdown/mentionable-items"
|
|
|
|
);
|
|
|
|
|
|
|
|
toolbar.addButton({
|
|
|
|
id: "insert-mentionable",
|
|
|
|
group: "extras",
|
|
|
|
icon: this.siteSettings.mentionables_composer_button_icon,
|
|
|
|
title: "mentionables.composer.insert.title",
|
|
|
|
perform: () => {
|
|
|
|
this.appEvents.trigger("wizard-editor:insert-text", {
|
|
|
|
fieldId: this.field.id,
|
|
|
|
text: SEPARATOR,
|
|
|
|
});
|
|
|
|
const $textarea = $(
|
|
|
|
document.querySelector(
|
|
|
|
`.composer-field.${this.field.id} textarea.d-editor-input`
|
|
|
|
)
|
|
|
|
);
|
|
|
|
$textarea.trigger("keyup.autocomplete");
|
|
|
|
},
|
|
|
|
});
|
|
|
|
}
|
2020-10-01 07:43:29 +02:00
|
|
|
},
|
2020-11-11 12:37:30 +01:00
|
|
|
|
2022-08-25 09:49:32 +02:00
|
|
|
previewUpdated(preview) {
|
|
|
|
highlightSyntax(preview, this.siteSettings, this.session);
|
2021-10-06 13:55:50 +02:00
|
|
|
|
|
|
|
if (this.siteSettings.mentionables_enabled) {
|
|
|
|
const { linkSeenMentionableItems } = requirejs(
|
|
|
|
"discourse/plugins/discourse-mentionables/discourse/lib/mentionable-items-preview-styling"
|
|
|
|
);
|
2022-08-25 09:49:32 +02:00
|
|
|
linkSeenMentionableItems(preview, this.siteSettings);
|
2021-10-06 13:55:50 +02:00
|
|
|
}
|
2020-10-01 07:43:29 +02:00
|
|
|
this._super(...arguments);
|
|
|
|
},
|
2020-11-11 12:37:30 +01:00
|
|
|
|
2023-03-10 03:34:40 +01:00
|
|
|
showLinkModal(toolbarEvent) {
|
|
|
|
let linkText = "";
|
|
|
|
this._lastSel = toolbarEvent.selected;
|
|
|
|
|
|
|
|
if (this._lastSel) {
|
|
|
|
linkText = this._lastSel.value;
|
|
|
|
}
|
2020-11-11 12:37:30 +01:00
|
|
|
|
2023-03-10 03:34:40 +01:00
|
|
|
showModal("insert-hyperlink").setProperties({
|
|
|
|
linkText,
|
|
|
|
toolbarEvent,
|
|
|
|
});
|
2020-10-01 15:48:20 +02:00
|
|
|
},
|
2020-11-11 12:37:30 +01:00
|
|
|
|
2020-10-02 06:40:10 +02:00
|
|
|
showUploadModal() {
|
2022-08-22 15:56:58 +02:00
|
|
|
this.session.set("wizardEventFieldId", this.field.id);
|
2021-12-01 08:19:14 +01:00
|
|
|
document.getElementById(this.fileUploadElementId).click();
|
2020-11-11 12:37:30 +01:00
|
|
|
},
|
2020-10-01 07:43:29 +02:00
|
|
|
},
|
|
|
|
});
|