DEV: Asyncify most of Composer controller (#17974)
…and fix cases where we were breaking the promise/async chain (by not awaiting or not returning promises)
This commit is contained in:
parent
a252bbf3e8
commit
7b51ac418b
|
@ -6,7 +6,7 @@ import {
|
||||||
authorizesOneOrMoreExtensions,
|
authorizesOneOrMoreExtensions,
|
||||||
uploadIcon,
|
uploadIcon,
|
||||||
} from "discourse/lib/uploads";
|
} from "discourse/lib/uploads";
|
||||||
import { cancel, run, scheduleOnce } from "@ember/runloop";
|
import { cancel, scheduleOnce } from "@ember/runloop";
|
||||||
import {
|
import {
|
||||||
cannotPostAgain,
|
cannotPostAgain,
|
||||||
durationTextFromSeconds,
|
durationTextFromSeconds,
|
||||||
|
@ -424,53 +424,43 @@ export default Controller.extend({
|
||||||
// - openOpts: this object will be passed to this.open if fallbackToNewTopic is
|
// - openOpts: this object will be passed to this.open if fallbackToNewTopic is
|
||||||
// true or topic is provided
|
// true or topic is provided
|
||||||
@action
|
@action
|
||||||
focusComposer(opts = {}) {
|
async focusComposer(opts = {}) {
|
||||||
return this._openComposerForFocus(opts).then(() => {
|
await this._openComposerForFocus(opts);
|
||||||
this._focusAndInsertText(opts.insertText);
|
this._focusAndInsertText(opts.insertText);
|
||||||
});
|
|
||||||
},
|
},
|
||||||
|
|
||||||
_openComposerForFocus(opts) {
|
async _openComposerForFocus(opts) {
|
||||||
if (this.get("model.viewOpen")) {
|
if (this.get("model.viewOpen")) {
|
||||||
return Promise.resolve();
|
return;
|
||||||
} else {
|
}
|
||||||
const opened = this.openIfDraft();
|
|
||||||
if (opened) {
|
|
||||||
return Promise.resolve();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (opts.topic) {
|
const opened = this.openIfDraft();
|
||||||
return this.open(
|
if (opened) {
|
||||||
Object.assign(
|
return;
|
||||||
{
|
}
|
||||||
action: Composer.REPLY,
|
|
||||||
draftKey: opts.topic.get("draft_key"),
|
|
||||||
draftSequence: opts.topic.get("draft_sequence"),
|
|
||||||
topic: opts.topic,
|
|
||||||
},
|
|
||||||
opts.openOpts || {}
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (opts.fallbackToNewTopic) {
|
if (opts.topic) {
|
||||||
return this.open(
|
return await this.open({
|
||||||
Object.assign(
|
action: Composer.REPLY,
|
||||||
{
|
draftKey: opts.topic.get("draft_key"),
|
||||||
action: Composer.CREATE_TOPIC,
|
draftSequence: opts.topic.get("draft_sequence"),
|
||||||
draftKey: Composer.NEW_TOPIC_KEY,
|
topic: opts.topic,
|
||||||
},
|
...(opts.openOpts || {}),
|
||||||
opts.openOpts || {}
|
});
|
||||||
)
|
}
|
||||||
);
|
|
||||||
}
|
if (opts.fallbackToNewTopic) {
|
||||||
|
return await this.open({
|
||||||
|
action: Composer.CREATE_TOPIC,
|
||||||
|
draftKey: Composer.NEW_TOPIC_KEY,
|
||||||
|
...(opts.openOpts || {}),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
_focusAndInsertText(insertText) {
|
_focusAndInsertText(insertText) {
|
||||||
scheduleOnce("afterRender", () => {
|
scheduleOnce("afterRender", () => {
|
||||||
const input = document.querySelector("textarea.d-editor-input");
|
document.querySelector("textarea.d-editor-input")?.focus();
|
||||||
input && input.focus();
|
|
||||||
|
|
||||||
if (insertText) {
|
if (insertText) {
|
||||||
this.model.appendText(insertText, null, { new_line: true });
|
this.model.appendText(insertText, null, { new_line: true });
|
||||||
|
@ -480,23 +470,25 @@ export default Controller.extend({
|
||||||
|
|
||||||
@action
|
@action
|
||||||
openIfDraft(event) {
|
openIfDraft(event) {
|
||||||
if (this.get("model.viewDraft")) {
|
if (!this.get("model.viewDraft")) {
|
||||||
// when called from shortcut, ensure we don't propagate the key to
|
return false;
|
||||||
// the composer input title
|
|
||||||
if (event) {
|
|
||||||
event.preventDefault();
|
|
||||||
event.stopPropagation();
|
|
||||||
}
|
|
||||||
|
|
||||||
this.set("model.composeState", Composer.OPEN);
|
|
||||||
document.documentElement.style.setProperty(
|
|
||||||
"--composer-height",
|
|
||||||
this.get("model.composerHeight")
|
|
||||||
);
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
// when called from shortcut, ensure we don't propagate the key to
|
||||||
|
// the composer input title
|
||||||
|
if (event) {
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.set("model.composeState", Composer.OPEN);
|
||||||
|
|
||||||
|
document.documentElement.style.setProperty(
|
||||||
|
"--composer-height",
|
||||||
|
this.get("model.composerHeight")
|
||||||
|
);
|
||||||
|
|
||||||
|
return true;
|
||||||
},
|
},
|
||||||
|
|
||||||
@action
|
@action
|
||||||
|
@ -513,37 +505,29 @@ export default Controller.extend({
|
||||||
this.close();
|
this.close();
|
||||||
},
|
},
|
||||||
|
|
||||||
openComposer(options, post, topic) {
|
async openComposer(options, post, topic) {
|
||||||
this.open(options).then(() => {
|
await this.open(options);
|
||||||
let url;
|
|
||||||
if (post) {
|
|
||||||
url = post.url;
|
|
||||||
}
|
|
||||||
if (!post && topic) {
|
|
||||||
url = topic.url;
|
|
||||||
}
|
|
||||||
|
|
||||||
let topicTitle;
|
let url = post?.url || topic?.url;
|
||||||
if (topic) {
|
const topicTitle = topic?.title;
|
||||||
topicTitle = topic.title;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!url || !topicTitle) {
|
if (!url || !topicTitle) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
url = `${location.protocol}//${location.host}${url}`;
|
url = `${location.protocol}//${location.host}${url}`;
|
||||||
const link = `[${escapeExpression(topicTitle)}](${url})`;
|
const link = `[${escapeExpression(topicTitle)}](${url})`;
|
||||||
const continueDiscussion = I18n.t("post.continue_discussion", {
|
const continueDiscussion = I18n.t("post.continue_discussion", {
|
||||||
postLink: link,
|
postLink: link,
|
||||||
});
|
});
|
||||||
|
|
||||||
const reply = this.get("model.reply");
|
const reply = this.get("model.reply");
|
||||||
if (!reply || !reply.includes(continueDiscussion)) {
|
if (reply?.includes(continueDiscussion)) {
|
||||||
this.model.prependText(continueDiscussion, {
|
return;
|
||||||
new_line: true,
|
}
|
||||||
});
|
|
||||||
}
|
this.model.prependText(continueDiscussion, {
|
||||||
|
new_line: true,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -654,19 +638,17 @@ export default Controller.extend({
|
||||||
},
|
},
|
||||||
|
|
||||||
// Toggle the reply view
|
// Toggle the reply view
|
||||||
toggle() {
|
async toggle() {
|
||||||
this.closeAutocomplete();
|
this.closeAutocomplete();
|
||||||
|
|
||||||
const composer = this.model;
|
const composer = this.model;
|
||||||
|
|
||||||
if (isEmpty(composer?.reply) && isEmpty(composer?.title)) {
|
if (isEmpty(composer?.reply) && isEmpty(composer?.title)) {
|
||||||
this.close();
|
this.close();
|
||||||
|
} else if (composer?.viewOpenOrFullscreen) {
|
||||||
|
this.shrink();
|
||||||
} else {
|
} else {
|
||||||
if (composer?.viewOpenOrFullscreen) {
|
await this.cancelComposer();
|
||||||
this.shrink();
|
|
||||||
} else {
|
|
||||||
this.cancelComposer();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@ -678,7 +660,7 @@ export default Controller.extend({
|
||||||
},
|
},
|
||||||
|
|
||||||
// Import a quote from the post
|
// Import a quote from the post
|
||||||
importQuote(toolbarEvent) {
|
async importQuote(toolbarEvent) {
|
||||||
const postStream = this.get("topic.postStream");
|
const postStream = this.get("topic.postStream");
|
||||||
let postId = this.get("model.post.id");
|
let postId = this.get("model.post.id");
|
||||||
|
|
||||||
|
@ -702,22 +684,21 @@ export default Controller.extend({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (postId) {
|
if (!postId) {
|
||||||
this.set("model.loading", true);
|
return;
|
||||||
|
|
||||||
return this.store.find("post", postId).then((post) => {
|
|
||||||
const quote = buildQuote(post, post.raw, {
|
|
||||||
full: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
toolbarEvent.addText(quote);
|
|
||||||
this.set("model.loading", false);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.set("model.loading", true);
|
||||||
|
|
||||||
|
const post = await this.store.find("post", postId);
|
||||||
|
const quote = buildQuote(post, post.raw, { full: true });
|
||||||
|
|
||||||
|
toolbarEvent.addText(quote);
|
||||||
|
this.set("model.loading", false);
|
||||||
},
|
},
|
||||||
|
|
||||||
cancel() {
|
async cancel() {
|
||||||
this.cancelComposer();
|
await this.cancelComposer();
|
||||||
},
|
},
|
||||||
|
|
||||||
save(ignore, event) {
|
save(ignore, event) {
|
||||||
|
@ -1002,6 +983,7 @@ export default Controller.extend({
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result.responseJson.route_to) {
|
if (result.responseJson.route_to) {
|
||||||
|
// TODO: await this:
|
||||||
this.destroyDraft();
|
this.destroyDraft();
|
||||||
if (result.responseJson.message) {
|
if (result.responseJson.message) {
|
||||||
return bootbox.alert(result.responseJson.message, () => {
|
return bootbox.alert(result.responseJson.message, () => {
|
||||||
|
@ -1072,9 +1054,7 @@ export default Controller.extend({
|
||||||
@param {Boolean} [opts.skipDraftCheck]
|
@param {Boolean} [opts.skipDraftCheck]
|
||||||
@param {Boolean} [opts.skipJumpOnSave] Option to skip navigating to the post when saved in this composer session
|
@param {Boolean} [opts.skipJumpOnSave] Option to skip navigating to the post when saved in this composer session
|
||||||
**/
|
**/
|
||||||
open(opts) {
|
open(opts = {}) {
|
||||||
opts = opts || {};
|
|
||||||
|
|
||||||
if (!opts.draftKey) {
|
if (!opts.draftKey) {
|
||||||
throw new Error("composer opened without a proper draft key");
|
throw new Error("composer opened without a proper draft key");
|
||||||
}
|
}
|
||||||
|
@ -1192,7 +1172,7 @@ export default Controller.extend({
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
this._setModel(composerModel, opts).then(resolve, reject);
|
return this._setModel(composerModel, opts).then(resolve, reject);
|
||||||
});
|
});
|
||||||
|
|
||||||
promise = promise.finally(() => {
|
promise = promise.finally(() => {
|
||||||
|
@ -1202,83 +1182,77 @@ export default Controller.extend({
|
||||||
},
|
},
|
||||||
|
|
||||||
// Given a potential instance and options, set the model for this composer.
|
// Given a potential instance and options, set the model for this composer.
|
||||||
_setModel(optionalComposerModel, opts) {
|
async _setModel(optionalComposerModel, opts) {
|
||||||
let promise = Promise.resolve();
|
|
||||||
|
|
||||||
this.set("linkLookup", null);
|
this.set("linkLookup", null);
|
||||||
|
|
||||||
promise = promise.then(() => {
|
let composerModel;
|
||||||
if (opts.draft) {
|
if (opts.draft) {
|
||||||
return loadDraft(this.store, opts).then((model) => {
|
composerModel = await loadDraft(this.store, opts);
|
||||||
if (!model) {
|
|
||||||
throw new Error("draft was not found");
|
if (!composerModel) {
|
||||||
}
|
throw new Error("draft was not found");
|
||||||
return model;
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
let model =
|
|
||||||
optionalComposerModel || this.store.createRecord("composer");
|
|
||||||
return model.open(opts).then(() => model);
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
const model =
|
||||||
|
optionalComposerModel || this.store.createRecord("composer");
|
||||||
|
|
||||||
|
await model.open(opts);
|
||||||
|
composerModel = model;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.set("model", composerModel);
|
||||||
|
|
||||||
|
composerModel.setProperties({
|
||||||
|
composeState: Composer.OPEN,
|
||||||
|
isWarning: false,
|
||||||
|
hasTargetGroups: opts.hasGroups,
|
||||||
});
|
});
|
||||||
|
|
||||||
promise.then((composerModel) => {
|
if (!this.model.targetRecipients) {
|
||||||
this.set("model", composerModel);
|
if (opts.usernames) {
|
||||||
|
deprecated("`usernames` is deprecated, use `recipients` instead.");
|
||||||
composerModel.setProperties({
|
this.model.set("targetRecipients", opts.usernames);
|
||||||
composeState: Composer.OPEN,
|
} else if (opts.recipients) {
|
||||||
isWarning: false,
|
this.model.set("targetRecipients", opts.recipients);
|
||||||
hasTargetGroups: opts.hasGroups,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!this.model.targetRecipients) {
|
|
||||||
if (opts.usernames) {
|
|
||||||
deprecated("`usernames` is deprecated, use `recipients` instead.");
|
|
||||||
this.model.set("targetRecipients", opts.usernames);
|
|
||||||
} else if (opts.recipients) {
|
|
||||||
this.model.set("targetRecipients", opts.recipients);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
opts.topicTitle &&
|
opts.topicTitle &&
|
||||||
opts.topicTitle.length <= this.siteSettings.max_topic_title_length
|
opts.topicTitle.length <= this.siteSettings.max_topic_title_length
|
||||||
) {
|
) {
|
||||||
this.model.set("title", opts.topicTitle);
|
this.model.set("title", opts.topicTitle);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (opts.topicCategoryId) {
|
if (opts.topicCategoryId) {
|
||||||
this.model.set("categoryId", opts.topicCategoryId);
|
this.model.set("categoryId", opts.topicCategoryId);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (opts.topicTags && this.site.can_tag_topics) {
|
if (opts.topicTags && this.site.can_tag_topics) {
|
||||||
let tags = escapeExpression(opts.topicTags)
|
let tags = escapeExpression(opts.topicTags)
|
||||||
.split(",")
|
.split(",")
|
||||||
.slice(0, this.siteSettings.max_tags_per_topic);
|
.slice(0, this.siteSettings.max_tags_per_topic);
|
||||||
|
|
||||||
tags.forEach(
|
tags.forEach(
|
||||||
(tag, index, array) =>
|
(tag, index, array) =>
|
||||||
(array[index] = tag.substring(0, this.siteSettings.max_tag_length))
|
(array[index] = tag.substring(0, this.siteSettings.max_tag_length))
|
||||||
);
|
|
||||||
|
|
||||||
this.model.set("tags", tags);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (opts.topicBody) {
|
|
||||||
this.model.set("reply", opts.topicBody);
|
|
||||||
}
|
|
||||||
|
|
||||||
const defaultComposerHeight =
|
|
||||||
this.model.action === "reply" ? "300px" : "400px";
|
|
||||||
|
|
||||||
this.set("model.composerHeight", defaultComposerHeight);
|
|
||||||
document.documentElement.style.setProperty(
|
|
||||||
"--composer-height",
|
|
||||||
defaultComposerHeight
|
|
||||||
);
|
);
|
||||||
});
|
|
||||||
|
|
||||||
return promise;
|
this.model.set("tags", tags);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opts.topicBody) {
|
||||||
|
this.model.set("reply", opts.topicBody);
|
||||||
|
}
|
||||||
|
|
||||||
|
const defaultComposerHeight =
|
||||||
|
this.model.action === "reply" ? "300px" : "400px";
|
||||||
|
|
||||||
|
this.set("model.composerHeight", defaultComposerHeight);
|
||||||
|
document.documentElement.style.setProperty(
|
||||||
|
"--composer-height",
|
||||||
|
defaultComposerHeight
|
||||||
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
viewNewReply() {
|
viewNewReply() {
|
||||||
|
@ -1287,24 +1261,24 @@ export default Controller.extend({
|
||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
|
|
||||||
destroyDraft(draftSequence = null) {
|
async destroyDraft(draftSequence = null) {
|
||||||
const key = this.get("model.draftKey");
|
const key = this.get("model.draftKey");
|
||||||
if (key) {
|
if (!key) {
|
||||||
if (key === Composer.NEW_TOPIC_KEY) {
|
return;
|
||||||
this.currentUser.set("has_topic_draft", false);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this._saveDraftPromise) {
|
|
||||||
return this._saveDraftPromise.then(() => this.destroyDraft());
|
|
||||||
}
|
|
||||||
|
|
||||||
const sequence = draftSequence || this.get("model.draftSequence");
|
|
||||||
return Draft.clear(key, sequence).then(() =>
|
|
||||||
this.appEvents.trigger("draft:destroyed", key)
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return Promise.resolve();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (key === Composer.NEW_TOPIC_KEY) {
|
||||||
|
this.currentUser.set("has_topic_draft", false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this._saveDraftPromise) {
|
||||||
|
await this._saveDraftPromise;
|
||||||
|
return await this.destroyDraft();
|
||||||
|
}
|
||||||
|
|
||||||
|
const sequence = draftSequence || this.get("model.draftSequence");
|
||||||
|
await Draft.clear(key, sequence);
|
||||||
|
this.appEvents.trigger("draft:destroyed", key);
|
||||||
},
|
},
|
||||||
|
|
||||||
confirmDraftAbandon(data) {
|
confirmDraftAbandon(data) {
|
||||||
|
@ -1319,30 +1293,30 @@ export default Controller.extend({
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_checkDraftPopup) {
|
if (!_checkDraftPopup) {
|
||||||
return new Promise((resolve) => {
|
|
||||||
bootbox.dialog(I18n.t("drafts.abandon.confirm"), [
|
|
||||||
{
|
|
||||||
label: I18n.t("drafts.abandon.no_value"),
|
|
||||||
callback: () => resolve(data),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: I18n.t("drafts.abandon.yes_value"),
|
|
||||||
class: "btn-danger",
|
|
||||||
icon: iconHTML("far-trash-alt"),
|
|
||||||
callback: () => {
|
|
||||||
this.destroyDraft(data.draft_sequence).finally(() => {
|
|
||||||
data.draft = null;
|
|
||||||
resolve(data);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
data.draft = null;
|
data.draft = null;
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
bootbox.dialog(I18n.t("drafts.abandon.confirm"), [
|
||||||
|
{
|
||||||
|
label: I18n.t("drafts.abandon.no_value"),
|
||||||
|
callback: () => resolve(data),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: I18n.t("drafts.abandon.yes_value"),
|
||||||
|
class: "btn-danger",
|
||||||
|
icon: iconHTML("far-trash-alt"),
|
||||||
|
callback: () => {
|
||||||
|
this.destroyDraft(data.draft_sequence).finally(() => {
|
||||||
|
data.draft = null;
|
||||||
|
resolve(data);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
cancelComposer() {
|
cancelComposer() {
|
||||||
|
@ -1352,7 +1326,7 @@ export default Controller.extend({
|
||||||
cancel(this._saveDraftDebounce);
|
cancel(this._saveDraftDebounce);
|
||||||
}
|
}
|
||||||
|
|
||||||
let promise = new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
if (this.get("model.hasMetaData") || this.get("model.replyDirty")) {
|
if (this.get("model.hasMetaData") || this.get("model.replyDirty")) {
|
||||||
const modal = showModal("discard-draft", {
|
const modal = showModal("discard-draft", {
|
||||||
model: this.model,
|
model: this.model,
|
||||||
|
@ -1360,7 +1334,7 @@ export default Controller.extend({
|
||||||
});
|
});
|
||||||
modal.setProperties({
|
modal.setProperties({
|
||||||
onDestroyDraft: () => {
|
onDestroyDraft: () => {
|
||||||
this.destroyDraft()
|
return this.destroyDraft()
|
||||||
.then(() => {
|
.then(() => {
|
||||||
this.model.clearState();
|
this.model.clearState();
|
||||||
this.close();
|
this.close();
|
||||||
|
@ -1375,7 +1349,7 @@ export default Controller.extend({
|
||||||
this.model.clearState();
|
this.model.clearState();
|
||||||
this.close();
|
this.close();
|
||||||
this.appEvents.trigger("composer:cancelled");
|
this.appEvents.trigger("composer:cancelled");
|
||||||
resolve();
|
return resolve();
|
||||||
},
|
},
|
||||||
// needed to resume saving drafts if composer stays open
|
// needed to resume saving drafts if composer stays open
|
||||||
onDismissModal: () => reject(),
|
onDismissModal: () => reject(),
|
||||||
|
@ -1392,9 +1366,7 @@ export default Controller.extend({
|
||||||
resolve();
|
resolve();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
}).finally(() => {
|
||||||
|
|
||||||
return promise.finally(() => {
|
|
||||||
this.skipAutoSave = false;
|
this.skipAutoSave = false;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -1411,26 +1383,19 @@ export default Controller.extend({
|
||||||
},
|
},
|
||||||
|
|
||||||
_saveDraft() {
|
_saveDraft() {
|
||||||
const model = this.model;
|
if (!this.model) {
|
||||||
if (model) {
|
return;
|
||||||
if (model.draftSaving) {
|
}
|
||||||
// in test debounce is Ember.run, this will cause
|
|
||||||
// an infinite loop
|
if (this.model.draftSaving) {
|
||||||
if (!isTesting()) {
|
this._saveDraftDebounce = discourseDebounce(this, this._saveDraft, 2000);
|
||||||
this._saveDraftDebounce = discourseDebounce(
|
} else {
|
||||||
this,
|
this._saveDraftPromise = this.model
|
||||||
this._saveDraft,
|
.saveDraft(this.currentUser)
|
||||||
2000
|
.finally(() => {
|
||||||
);
|
this._lastDraftSaved = Date.now();
|
||||||
}
|
this._saveDraftPromise = null;
|
||||||
} else {
|
});
|
||||||
this._saveDraftPromise = model
|
|
||||||
.saveDraft(this.currentUser)
|
|
||||||
.finally(() => {
|
|
||||||
this._lastDraftSaved = Date.now();
|
|
||||||
this._saveDraftPromise = null;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -1449,8 +1414,11 @@ export default Controller.extend({
|
||||||
if (Date.now() - this._lastDraftSaved > 15000) {
|
if (Date.now() - this._lastDraftSaved > 15000) {
|
||||||
this._saveDraft();
|
this._saveDraft();
|
||||||
} else {
|
} else {
|
||||||
let method = isTesting() ? run : discourseDebounce;
|
this._saveDraftDebounce = discourseDebounce(
|
||||||
this._saveDraftDebounce = method(this, this._saveDraft, 2000);
|
this,
|
||||||
|
this._saveDraft,
|
||||||
|
2000
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -1516,7 +1484,7 @@ export default Controller.extend({
|
||||||
elem.classList.remove("fullscreen-composer");
|
elem.classList.remove("fullscreen-composer");
|
||||||
elem.classList.remove("composer-open");
|
elem.classList.remove("composer-open");
|
||||||
|
|
||||||
document.activeElement && document.activeElement.blur();
|
document.activeElement?.blur();
|
||||||
this.setProperties({ model: null, lastValidatedAt: null });
|
this.setProperties({ model: null, lastValidatedAt: null });
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -3,16 +3,18 @@ import ModalFunctionality from "discourse/mixins/modal-functionality";
|
||||||
|
|
||||||
export default Controller.extend(ModalFunctionality, {
|
export default Controller.extend(ModalFunctionality, {
|
||||||
actions: {
|
actions: {
|
||||||
destroyDraft() {
|
async destroyDraft() {
|
||||||
this.onDestroyDraft();
|
await this.onDestroyDraft();
|
||||||
this.send("closeModal");
|
this.send("closeModal");
|
||||||
},
|
},
|
||||||
saveDraftAndClose() {
|
|
||||||
this.onSaveDraft();
|
async saveDraftAndClose() {
|
||||||
|
await this.onSaveDraft();
|
||||||
this.send("closeModal");
|
this.send("closeModal");
|
||||||
},
|
},
|
||||||
dismissModal() {
|
|
||||||
this.onDismissModal();
|
async dismissModal() {
|
||||||
|
await this.onDismissModal();
|
||||||
this.send("closeModal");
|
this.send("closeModal");
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in New Issue