Locate this file: vendor\flarum\core\js\src\forum\components\DiscussionComposer.js
Update it to below
goto cd vendor/flarum/core/js
do npm install
npm run build
go to the root of your flarum and do php flarum cache:clear
import app from '../../forum/app'; | |
import ComposerBody from './ComposerBody'; | |
import extractText from '../../common/utils/extractText'; | |
import Stream from '../../common/utils/Stream'; | |
function minimizeComposerIfFullScreen(e) { | |
if (app.composer.isFullScreen()) { | |
app.composer.minimize(); | |
e.stopPropagation(); | |
} | |
} | |
/** | |
* The `DiscussionComposer` component displays the composer content for starting | |
* a new discussion. It adds a text field as a header control so the user can | |
* enter the title of their discussion. It also overrides the `submit` and | |
* `willExit` actions to account for the title. | |
* | |
* ### Attrs | |
* | |
* - All of the attrs for ComposerBody | |
* - `titlePlaceholder` | |
*/ | |
export default class DiscussionComposer extends ComposerBody { | |
static initAttrs(attrs) { | |
super.initAttrs(attrs); | |
attrs.placeholder = attrs.placeholder || extractText(app.translator.trans('core.forum.composer_discussion.body_placeholder')); | |
attrs.submitLabel = attrs.submitLabel || app.translator.trans('core.forum.composer_discussion.submit_button'); | |
attrs.confirmExit = attrs.confirmExit || extractText(app.translator.trans('core.forum.composer_discussion.discard_confirmation')); | |
attrs.titlePlaceholder = attrs.titlePlaceholder || extractText(app.translator.trans('core.forum.composer_discussion.title_placeholder')); | |
attrs.className = 'ComposerBody--discussion'; | |
} | |
oninit(vnode) { | |
super.oninit(vnode); | |
this.initialized = false; | |
this.previewing = false; | |
this.timer = null; | |
this.composer.fields.title = this.composer.fields.title || Stream(''); | |
/** | |
* The value of the title input. | |
* | |
* @type {Function} | |
*/ | |
this.title = this.composer.fields.title; | |
} | |
headerItems() { | |
const items = super.headerItems(); | |
items.add('title', <h3>{app.translator.trans('core.forum.composer_discussion.title')}</h3>, 100); | |
items.add( | |
'discussionTitle', | |
<h3> | |
<input | |
className="FormControl" | |
bidi={this.title} | |
placeholder={this.attrs.titlePlaceholder} | |
disabled={!!this.attrs.disabled} | |
onkeydown={this.onkeydown.bind(this)} | |
/> | |
</h3> | |
); | |
return items; | |
} | |
/** | |
* Jump to the preview when triggered by the text editor. | |
*/ | |
jumpToPreview(e) { | |
const snippetId = '#preview-discussion'; | |
const snippet = ` | |
<li id="preview-discussion" role="article" aria-setsize="-1" aria-posinset="19"> | |
<div class="DiscussionListItem DiscussionListItem--sticky"> | |
<div class="DiscussionListItem-content Slidable-content read"> | |
<a href="/d/69-what-programming-language-to-learn-in-2024/8" class="DiscussionListItem-main"> | |
<h2 class="DiscussionListItem-title" id="preview-snippet-title"></h2> | |
<ul class="DiscussionListItem-info"> | |
<li class="item-excerptM" id="preview-snippet-body"> | |
</li> | |
</ul> | |
</a> | |
</div> | |
</div> | |
</li>`; | |
if ($(snippetId).length === 0) { | |
$(".DiscussionList-discussions").append(snippet); | |
} | |
$('html, body').animate({ | |
scrollTop: $('#preview-discussion').offset().top | |
}, 1000); | |
const mdTitle = $(".ComposerBody-content input.FormControl").val(); | |
const mdText = $("textarea.TextEditor-editor").val(); | |
s9e.TextFormatter.preview(mdText, $('#preview-snippet-body')[0]); | |
$('#preview-snippet-title').html(mdTitle); | |
} | |
/** | |
* Handle the title input's keydown event. When the return key is pressed, | |
* move the focus to the start of the text editor. | |
* | |
* @param {KeyboardEvent} e | |
*/ | |
onkeydown(e) { | |
if (e.which === 13) { | |
// Return | |
e.preventDefault(); | |
this.composer.editor.moveCursorTo(0); | |
} | |
e.redraw = false; | |
} | |
hasChanges() { | |
return this.title() || this.composer.fields.content(); | |
} | |
/** | |
* Get the data to submit to the server when the discussion is saved. | |
* | |
* @return {Record<string, unknown>} | |
*/ | |
data() { | |
return { | |
title: this.title(), | |
content: this.composer.fields.content(), | |
}; | |
} | |
onsubmit() { | |
this.loading = true; | |
const data = this.data(); | |
app.store | |
.createRecord('discussions') | |
.save(data) | |
.then((discussion) => { | |
this.composer.hide(); | |
app.discussions.refresh(); | |
m.route.set(app.route.discussion(discussion)); | |
}, this.loaded.bind(this)); | |
} | |
} |