mirror of
https://github.com/discourse/discourse.git
synced 2025-05-23 16:22:20 +08:00
159 lines
4.1 KiB
JavaScript
159 lines
4.1 KiB
JavaScript
import { createWidget } from "discourse/widgets/widget";
|
|
import transformPost from "discourse/lib/transform-post";
|
|
import { Placeholder } from "discourse/lib/posts-with-placeholders";
|
|
import { addWidgetCleanCallback } from "discourse/components/mount-widget";
|
|
|
|
let transformCallbacks = null;
|
|
export function postTransformCallbacks(transformed) {
|
|
if (transformCallbacks === null) {
|
|
return;
|
|
}
|
|
|
|
for (let i = 0; i < transformCallbacks.length; i++) {
|
|
transformCallbacks[i].call(this, transformed);
|
|
}
|
|
}
|
|
export function addPostTransformCallback(callback) {
|
|
transformCallbacks = transformCallbacks || [];
|
|
transformCallbacks.push(callback);
|
|
}
|
|
|
|
const CLOAKING_ENABLED = !window.inTestEnv;
|
|
const DAY = 1000 * 60 * 60 * 24;
|
|
|
|
const _dontCloak = {};
|
|
let _cloaked = {};
|
|
let _heights = {};
|
|
|
|
export function preventCloak(postId) {
|
|
_dontCloak[postId] = true;
|
|
}
|
|
|
|
export function cloak(post, component) {
|
|
if (!CLOAKING_ENABLED || _cloaked[post.id] || _dontCloak[post.id]) {
|
|
return;
|
|
}
|
|
|
|
const $post = $(`#post_${post.post_number}`).parent();
|
|
_cloaked[post.id] = true;
|
|
_heights[post.id] = $post.outerHeight();
|
|
|
|
component.dirtyKeys.keyDirty(`post-${post.id}`);
|
|
Ember.run.debounce(component, "queueRerender", 1000);
|
|
}
|
|
|
|
export function uncloak(post, component) {
|
|
if (!CLOAKING_ENABLED || !_cloaked[post.id]) {
|
|
return;
|
|
}
|
|
_cloaked[post.id] = null;
|
|
component.dirtyKeys.keyDirty(`post-${post.id}`);
|
|
component.queueRerender();
|
|
}
|
|
|
|
addWidgetCleanCallback("post-stream", () => {
|
|
_cloaked = {};
|
|
_heights = {};
|
|
});
|
|
|
|
export default createWidget("post-stream", {
|
|
tagName: "div.post-stream",
|
|
|
|
html(attrs) {
|
|
const posts = attrs.posts || [];
|
|
const postArray = posts.toArray();
|
|
|
|
const result = [];
|
|
|
|
const before = attrs.gaps && attrs.gaps.before ? attrs.gaps.before : {};
|
|
const after = attrs.gaps && attrs.gaps.after ? attrs.gaps.after : {};
|
|
|
|
let prevPost;
|
|
let prevDate;
|
|
|
|
const mobileView = this.site.mobileView;
|
|
for (let i = 0; i < postArray.length; i++) {
|
|
const post = postArray[i];
|
|
|
|
if (post instanceof Placeholder) {
|
|
result.push(this.attach("post-placeholder"));
|
|
continue;
|
|
}
|
|
|
|
const nextPost = i < postArray.length - 1 ? postArray[i + 1] : null;
|
|
|
|
const transformed = transformPost(
|
|
this.currentUser,
|
|
this.site,
|
|
post,
|
|
prevPost,
|
|
nextPost
|
|
);
|
|
transformed.canCreatePost = attrs.canCreatePost;
|
|
transformed.mobileView = mobileView;
|
|
|
|
if (transformed.canManage) {
|
|
transformed.multiSelect = attrs.multiSelect;
|
|
|
|
if (attrs.multiSelect) {
|
|
transformed.selected = attrs.selectedQuery(post);
|
|
}
|
|
}
|
|
|
|
if (attrs.searchService) {
|
|
transformed.highlightTerm = attrs.searchService.highlightTerm;
|
|
}
|
|
|
|
// Post gap - before
|
|
const beforeGap = before[post.id];
|
|
if (beforeGap) {
|
|
result.push(
|
|
this.attach(
|
|
"post-gap",
|
|
{ pos: "before", postId: post.id, gap: beforeGap },
|
|
{ model: post }
|
|
)
|
|
);
|
|
}
|
|
|
|
// Handle time gaps
|
|
const curTime = new Date(transformed.created_at).getTime();
|
|
if (prevDate) {
|
|
const daysSince = Math.floor((curTime - prevDate) / DAY);
|
|
if (daysSince > this.siteSettings.show_time_gap_days) {
|
|
result.push(this.attach("time-gap", { daysSince }));
|
|
}
|
|
}
|
|
prevDate = curTime;
|
|
|
|
transformed.height = _heights[post.id];
|
|
transformed.cloaked = _cloaked[post.id];
|
|
|
|
postTransformCallbacks(transformed);
|
|
|
|
if (transformed.isSmallAction) {
|
|
result.push(
|
|
this.attach("post-small-action", transformed, { model: post })
|
|
);
|
|
} else {
|
|
result.push(this.attach("post", transformed, { model: post }));
|
|
}
|
|
|
|
// Post gap - after
|
|
const afterGap = after[post.id];
|
|
if (afterGap) {
|
|
result.push(
|
|
this.attach(
|
|
"post-gap",
|
|
{ pos: "after", postId: post.id, gap: afterGap },
|
|
{ model: post }
|
|
)
|
|
);
|
|
}
|
|
|
|
prevPost = post;
|
|
}
|
|
return result;
|
|
}
|
|
});
|