discourse-journal/assets/javascripts/discourse/initializers/journal-post.js.es6
2024-03-07 08:38:41 +00:00

385 lines
11 KiB
JavaScript

import discourseComputed, { observes } from "discourse-common/utils/decorators";
import PostsWithPlaceholders from "discourse/lib/posts-with-placeholders";
import { withPluginApi } from "discourse/lib/plugin-api";
import { h } from "virtual-dom";
import { next, once } from "@ember/runloop";
import { alias } from "@ember/object/computed";
import Composer from "discourse/models/composer";
const PLUGIN_ID = "discourse-journal";
export default {
name: "journal-post",
initialize(container) {
const siteSettings = container.lookup("site-settings:main");
if (!siteSettings.journal_enabled) return;
withPluginApi("0.8.12", api => {
const store = api.container.lookup("store:main");
const appEvents = api.container.lookup("service:app-events");
const currentUser = api.getCurrentUser();
api.includePostAttributes(
"journal",
"reply_to_post_number",
"comment",
"showComment",
"entry",
"entry_post_id",
"entry_post_ids"
);
api.reopenWidget("post-menu", {
menuItems() {
let result = siteSettings.post_menu.split("|").filter(Boolean);
if (this.attrs.journal) {
result = result.filter(b => b !== "reply");
}
return result;
}
});
api.decorateWidget("post:after", function(helper) {
const model = helper.getModel();
if (model.attachCommentToggle && model.hiddenComments > 0) {
let type =
Number(siteSettings.journal_comments_default) > 0
? "more"
: "all";
return helper.attach("link", {
action: "showComments",
actionParam: model.entry_post_id,
rawLabel: I18n.t(`topic.comment.show_comments.${type}`, {
count: model.hiddenComments
}),
className: "show-comments"
});
}
});
api.addPostClassesCallback(attrs => {
if (attrs.journal && !attrs.firstPost) {
if (attrs.comment) {
let classes = ["comment"];
if (attrs.showComment) {
classes.push("show");
}
return classes;
} else {
return ["entry"];
}
}
});
api.addPostMenuButton("comment", attrs => {
if (attrs.canCreatePost && attrs.journal) {
let replyComment = attrs.reply_to_post_number;
let i18nKey = replyComment ? 'comment_reply' : 'comment';
let args = {
action: "openCommentCompose",
title: `topic.${i18nKey}.help`,
icon: replyComment ? "reply" : "comment",
className: "comment create fade-out"
};
if (!attrs.mobileView && !replyComment) {
args.label = `topic.${i18nKey}.title`;
}
return args;
}
});
api.modifyClass('component:scrolling-post-stream', {
pluginId: PLUGIN_ID,
showComments: [],
didInsertElement() {
this._super(...arguments);
this.appEvents.on("composer:opened", this, () => {
const composer = api.container.lookup("controller:composer");
const post = composer.get('model.post');
if (post && post.entry) {
this.set('showComments', [post.id]);
}
this._refresh({ force: true });
});
},
buildArgs() {
return Object.assign(
this._super(...arguments),
this.getProperties(
'showComments'
)
)
}
});
api.reopenWidget("post-stream", {
buildKey: () => "post-stream",
firstPost() {
return this.attrs.posts.toArray()[0];
},
defaultState(attrs, state) {
let defaultState = this._super(attrs, state);
const firstPost = this.firstPost();
if (!firstPost || !firstPost.journal) {
return defaultState;
}
defaultState["showComments"] = attrs.showComments;
return defaultState;
},
showComments(entryId) {
let showComments = this.state.showComments;
if (showComments.indexOf(entryId) === -1) {
showComments.push(entryId);
this.state.showComments = showComments;
this.appEvents.trigger("post-stream:refresh", { force: true });
}
},
html(attrs, state) {
const firstPost = this.firstPost();
if (!firstPost || !firstPost.journal) {
return this._super(...arguments);
}
let showComments = (state.showComments || []);
if (attrs.showComments && attrs.showComments.length) {
attrs.showComments.forEach(postId => {
if (!showComments.includes(postId)) {
showComments.push(postId);
}
});
}
let posts = attrs.posts || [];
let postArray = this.capabilities.isAndroid ? posts : posts.toArray();
let defaultComments = Number(siteSettings.journal_comments_default);
let commentCount = 0;
let lastVisible = null;
postArray.forEach((p, i) => {
if (!p.topic) {
return;
}
if (p.comment) {
commentCount++;
let showingComments = showComments.indexOf(p.entry_post_id) > -1;
let shownByDefault = commentCount <= defaultComments;
p["showComment"] = showingComments || shownByDefault;
p["attachCommentToggle"] = false;
if (p["showComment"]) {
lastVisible = i;
}
if ((!postArray[i + 1] || postArray[i + 1].entry) && !p["showComment"]) {
postArray[lastVisible]["attachCommentToggle"] = true;
postArray[lastVisible]["hiddenComments"] = commentCount - defaultComments;
}
} else {
p["attachCommentToggle"] = false;
commentCount = 0;
lastVisible = i;
}
});
if (this.capabilities.isAndroid) {
attrs.posts = postArray;
} else {
attrs.posts = PostsWithPlaceholders.create({
posts: postArray,
store
});
}
return this._super(attrs, state);
}
});
api.modifyClass("model:post-stream", {
pluginId: PLUGIN_ID,
journal: alias('topic.journal'),
getCommentIndex(post) {
const posts = this.get("posts");
let passed = false;
let commentIndex = null;
posts.some((p, i) => {
if (passed && !p.reply_to_post_number) {
commentIndex = i;
return true;
}
if (p.post_number == post.reply_to_post_number && (i < posts.length - 1)) {
passed = true;
}
});
return commentIndex;
},
insertCommentInStream(post) {
const stream = this.stream;
const postId = post.get("id");
const commentIndex = this.getCommentIndex(post) - 1;
if (stream.indexOf(postId) > -1 && commentIndex && commentIndex > 0) {
stream.removeObject(postId);
stream.insertAt(commentIndex, postId);
}
},
stagePost(post, user) {
let result = this._super(...arguments);
if (!this.journal) return result;
if (post.get("reply_to_post_number")) {
this.insertCommentInStream(post);
}
return result;
},
commitPost(post) {
let result = this._super(...arguments);
if (!this.journal) return result;
if (post.get("reply_to_post_number")) {
this.insertCommentInStream(post);
}
return result;
},
prependPost(post) {
if (!this.journal) return this._super(...arguments);
const stored = this.storePost(post);
if (stored) {
const posts = this.get("posts");
if (post.post_number === 2 && posts[0].post_number === 1) {
posts.insertAt(1, stored);
} else {
posts.unshiftObject(stored)
}
}
return post;
},
appendPost(post) {
if (!this.journal) return this._super(...arguments);
const stored = this.storePost(post);
if (stored) {
const posts = this.get("posts");
if (!posts.includes(stored)) {
let insertPost = () => posts.pushObject(stored);
if (post.get("reply_to_post_number")) {
const commentIndex = this.getCommentIndex(post);
if (commentIndex && commentIndex > 0) {
insertPost = () => posts.insertAt(commentIndex, stored);
}
}
if (!this.get("loadingBelow")) {
this.get("postsWithPlaceholders").appendPost(insertPost);
} else {
insertPost();
}
}
if (stored.get("id") !== -1) {
this.set("lastAppended", stored);
}
}
return post;
}
});
api.reopenWidget("post-avatar", {
html(attrs) {
if (!attrs || !attrs.journal) {
return this._super(...arguments);
}
if (attrs.comment) {
this.settings.size = "small";
} else {
this.settings.size = "large";
}
return this._super(...arguments);
}
});
api.reopenWidget("post", {
html(attrs) {
if (!attrs.journal) {
return this._super(...arguments);
}
if (attrs.cloaked) {
return "";
}
if (attrs.entry) {
attrs.replyToUsername = null;
}
if (attrs.comment) {
attrs.replyCount = null;
}
return this.attach("post-article", attrs);
},
openCommentCompose() {
const opts = {
action: Composer.REPLY,
draftKey: this.model.topic.get("draft_key"),
draftSequence: this.model.topic.get("draft_sequence"),
post: this.model
};
api.container.lookup("controller:composer").open(opts);
}
});
api.reopenWidget("reply-to-tab", {
title: "in_reply_to",
click() {
if (this.attrs.journal) {
return false;
} else {
return this._super(...arguments);
}
},
})
});
}
};