artalk 2.8.0 → 2.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/Artalk.cjs +2 -2
- package/dist/Artalk.cjs.map +1 -1
- package/dist/Artalk.iife.js +2 -2
- package/dist/Artalk.iife.js.map +1 -1
- package/dist/Artalk.js +2 -2
- package/dist/Artalk.js.map +1 -1
- package/dist/Artalk.mjs +289 -247
- package/dist/Artalk.mjs.map +1 -1
- package/dist/ArtalkLite.cjs +2 -2
- package/dist/ArtalkLite.cjs.map +1 -1
- package/dist/ArtalkLite.iife.js +2 -2
- package/dist/ArtalkLite.iife.js.map +1 -1
- package/dist/ArtalkLite.js +2 -2
- package/dist/ArtalkLite.js.map +1 -1
- package/dist/ArtalkLite.mjs +289 -247
- package/dist/ArtalkLite.mjs.map +1 -1
- package/dist/main.d.cts +105 -48
- package/dist/main.d.ts +105 -48
- package/package.json +1 -1
package/dist/ArtalkLite.mjs
CHANGED
|
@@ -368,6 +368,29 @@ let Api$1 = class Api extends HttpClient {
|
|
|
368
368
|
type: "application/json",
|
|
369
369
|
format: "json"
|
|
370
370
|
}, params)),
|
|
371
|
+
/**
|
|
372
|
+
* @description Get the detail of a comment by comment id
|
|
373
|
+
*
|
|
374
|
+
* @tags Comment
|
|
375
|
+
* @name GetComment
|
|
376
|
+
* @summary Get a comment
|
|
377
|
+
* @request GET:/comments/{id}
|
|
378
|
+
* @response `200` `HandlerResponseCommentGet` OK
|
|
379
|
+
* @response `404` `(HandlerMap & {
|
|
380
|
+
msg?: string,
|
|
381
|
+
|
|
382
|
+
})` Not Found
|
|
383
|
+
* @response `500` `(HandlerMap & {
|
|
384
|
+
msg?: string,
|
|
385
|
+
|
|
386
|
+
})` Internal Server Error
|
|
387
|
+
*/
|
|
388
|
+
getComment: (id, params = {}) => this.request(__spreadValues({
|
|
389
|
+
path: `/comments/${id}`,
|
|
390
|
+
method: "GET",
|
|
391
|
+
type: "application/json",
|
|
392
|
+
format: "json"
|
|
393
|
+
}, params)),
|
|
371
394
|
/**
|
|
372
395
|
* @description Update a specific comment
|
|
373
396
|
*
|
|
@@ -3131,7 +3154,7 @@ function showLoading(parentElem, conf) {
|
|
|
3131
3154
|
let $loading = parentElem.querySelector(":scope > .atk-loading");
|
|
3132
3155
|
if (!$loading) {
|
|
3133
3156
|
$loading = createElement(
|
|
3134
|
-
`<div class="atk-loading
|
|
3157
|
+
`<div class="atk-loading" style="display: none;">
|
|
3135
3158
|
<div class="atk-loading-spinner">
|
|
3136
3159
|
<svg viewBox="25 25 50 50"><circle cx="50" cy="50" r="20" fill="none" stroke-width="2" stroke-miterlimit="10"></circle></svg>
|
|
3137
3160
|
</div>
|
|
@@ -3146,7 +3169,8 @@ function showLoading(parentElem, conf) {
|
|
|
3146
3169
|
if ($spinner) {
|
|
3147
3170
|
$spinner.style.display = "none";
|
|
3148
3171
|
window.setTimeout(() => {
|
|
3149
|
-
$spinner.
|
|
3172
|
+
if ($spinner.isConnected)
|
|
3173
|
+
$spinner.style.display = "";
|
|
3150
3174
|
}, 500);
|
|
3151
3175
|
}
|
|
3152
3176
|
}
|
|
@@ -3166,8 +3190,7 @@ function scrollIntoView(elem, enableAnim = true, relativeTo) {
|
|
|
3166
3190
|
if (relativeTo) {
|
|
3167
3191
|
const containerRect = relativeTo.getBoundingClientRect();
|
|
3168
3192
|
const elementRect = elem.getBoundingClientRect();
|
|
3169
|
-
top = elementRect.top - containerRect.top + relativeTo.scrollTop;
|
|
3170
|
-
top += getHeight(relativeTo) / 2 - getHeight(elem) / 2;
|
|
3193
|
+
top = elementRect.top - containerRect.top + relativeTo.scrollTop - relativeTo.clientHeight / 2 + elem.clientHeight / 2;
|
|
3171
3194
|
} else {
|
|
3172
3195
|
const rect = elem.getBoundingClientRect();
|
|
3173
3196
|
const elemTop = rect.top + window.scrollY;
|
|
@@ -3501,6 +3524,9 @@ class Component {
|
|
|
3501
3524
|
get conf() {
|
|
3502
3525
|
return this.ctx.conf;
|
|
3503
3526
|
}
|
|
3527
|
+
getEl() {
|
|
3528
|
+
return this.$el;
|
|
3529
|
+
}
|
|
3504
3530
|
}
|
|
3505
3531
|
const EditorHTML = '<div class="atk-main-editor">\n <div class="atk-header">\n <input name="nick" class="atk-nick" type="text" required="required">\n <input name="email" class="atk-email" type="email" required="required">\n <input name="link" class="atk-link" type="url">\n </div>\n <div class="atk-textarea-wrap">\n <textarea class="atk-textarea"></textarea>\n </div>\n <div class="atk-plug-panel-wrap" style="display: none;"></div>\n <div class="atk-bottom">\n <div class="atk-item atk-plug-btn-wrap"></div>\n <div class="atk-item">\n <button type="button" class="atk-send-btn"></button>\n </div>\n </div>\n <div class="atk-notify-wrap"></div>\n</div>\n';
|
|
3506
3532
|
const Sel = {
|
|
@@ -3885,39 +3911,18 @@ function makeNestCommentNodeList(srcData, sortBy = "DATE_DESC", nestMax = 2) {
|
|
|
3885
3911
|
})(nodeList);
|
|
3886
3912
|
return nodeList;
|
|
3887
3913
|
}
|
|
3888
|
-
|
|
3889
|
-
|
|
3890
|
-
|
|
3891
|
-
}
|
|
3892
|
-
// TODO: refactor `if syntax` to strategy pattern
|
|
3893
|
-
import(comments) {
|
|
3894
|
-
if (this.options.flatMode) {
|
|
3895
|
-
comments.forEach((commentData) => {
|
|
3896
|
-
this.putCommentFlatMode(commentData, comments, "append");
|
|
3897
|
-
});
|
|
3898
|
-
} else {
|
|
3899
|
-
this.importCommentsNestMode(comments);
|
|
3900
|
-
}
|
|
3901
|
-
}
|
|
3902
|
-
insert(comment) {
|
|
3903
|
-
if (!this.options.flatMode) {
|
|
3904
|
-
this.insertCommentNest(comment);
|
|
3905
|
-
} else {
|
|
3906
|
-
this.insertCommentFlatMode(comment);
|
|
3907
|
-
}
|
|
3908
|
-
}
|
|
3909
|
-
// 导入评论 · 嵌套模式
|
|
3910
|
-
importCommentsNestMode(srcData) {
|
|
3911
|
-
const rootNodes = makeNestCommentNodeList(srcData, this.options.nestSortBy, this.options.nestMax);
|
|
3914
|
+
const createNestStrategy = (opts) => ({
|
|
3915
|
+
import: (comments) => {
|
|
3916
|
+
const rootNodes = makeNestCommentNodeList(comments, opts.nestSortBy, opts.nestMax);
|
|
3912
3917
|
rootNodes.forEach((rootNode) => {
|
|
3913
3918
|
var _a;
|
|
3914
|
-
const rootC =
|
|
3915
|
-
(_a =
|
|
3919
|
+
const rootC = opts.createCommentNode(rootNode.comment);
|
|
3920
|
+
(_a = opts.$commentsWrap) == null ? void 0 : _a.appendChild(rootC.getEl());
|
|
3916
3921
|
rootC.getRender().playFadeAnim();
|
|
3917
3922
|
const loadChildren = (parentC, parentNode) => {
|
|
3918
3923
|
parentNode.children.forEach((node) => {
|
|
3919
3924
|
const childD = node.comment;
|
|
3920
|
-
const childC =
|
|
3925
|
+
const childC = opts.createCommentNode(childD, parentC.getData());
|
|
3921
3926
|
parentC.putChild(childC);
|
|
3922
3927
|
loadChildren(childC, node);
|
|
3923
3928
|
});
|
|
@@ -3925,44 +3930,66 @@ class ListLayout {
|
|
|
3925
3930
|
loadChildren(rootC, rootNode);
|
|
3926
3931
|
rootC.getRender().checkHeightLimit();
|
|
3927
3932
|
});
|
|
3928
|
-
}
|
|
3929
|
-
|
|
3930
|
-
putCommentFlatMode(cData, ctxData, insertMode) {
|
|
3931
|
-
var _a, _b;
|
|
3932
|
-
if (cData.is_collapsed)
|
|
3933
|
-
cData.is_allow_reply = false;
|
|
3934
|
-
const comment = this.options.createCommentNode(cData, ctxData);
|
|
3935
|
-
if (cData.visible) {
|
|
3936
|
-
if (insertMode === "append")
|
|
3937
|
-
(_a = this.options.$commentsWrap) == null ? void 0 : _a.append(comment.getEl());
|
|
3938
|
-
if (insertMode === "prepend")
|
|
3939
|
-
(_b = this.options.$commentsWrap) == null ? void 0 : _b.prepend(comment.getEl());
|
|
3940
|
-
comment.getRender().playFadeAnim();
|
|
3941
|
-
}
|
|
3942
|
-
comment.getRender().checkHeightLimit();
|
|
3943
|
-
return comment;
|
|
3944
|
-
}
|
|
3945
|
-
insertCommentNest(commentData) {
|
|
3933
|
+
},
|
|
3934
|
+
insert: (comment, replyComment) => {
|
|
3946
3935
|
var _a;
|
|
3947
|
-
const
|
|
3948
|
-
if (
|
|
3949
|
-
(_a =
|
|
3936
|
+
const node = opts.createCommentNode(comment, replyComment);
|
|
3937
|
+
if (comment.rid === 0) {
|
|
3938
|
+
(_a = opts.$commentsWrap) == null ? void 0 : _a.prepend(node.getEl());
|
|
3950
3939
|
} else {
|
|
3951
|
-
const parent =
|
|
3940
|
+
const parent = opts.findCommentNode(comment.rid);
|
|
3952
3941
|
if (parent) {
|
|
3953
|
-
parent.putChild(
|
|
3954
|
-
|
|
3942
|
+
parent.putChild(node, opts.nestSortBy === "DATE_ASC" ? "append" : "prepend");
|
|
3943
|
+
node.getParents().forEach((p) => {
|
|
3955
3944
|
p.getRender().heightLimitRemoveForChildren();
|
|
3956
3945
|
});
|
|
3957
3946
|
}
|
|
3958
3947
|
}
|
|
3959
|
-
|
|
3960
|
-
scrollIntoView(
|
|
3961
|
-
|
|
3948
|
+
node.getRender().checkHeightLimit();
|
|
3949
|
+
node.scrollIntoView();
|
|
3950
|
+
node.getRender().playFadeAnim();
|
|
3951
|
+
}
|
|
3952
|
+
});
|
|
3953
|
+
const createFlatStrategy = (opts) => ({
|
|
3954
|
+
import: (comments) => {
|
|
3955
|
+
comments.forEach((comment) => {
|
|
3956
|
+
const replyComment = comment.rid === 0 ? void 0 : comments.find((c) => c.id === comment.rid);
|
|
3957
|
+
insertComment(opts, "append", comment, replyComment);
|
|
3958
|
+
});
|
|
3959
|
+
},
|
|
3960
|
+
insert: (comment, replyComment) => {
|
|
3961
|
+
const node = insertComment(opts, "prepend", comment, replyComment);
|
|
3962
|
+
node.scrollIntoView();
|
|
3963
|
+
}
|
|
3964
|
+
});
|
|
3965
|
+
function insertComment(opts, insertMode, comment, replyComment) {
|
|
3966
|
+
if (comment.is_collapsed)
|
|
3967
|
+
comment.is_allow_reply = false;
|
|
3968
|
+
const node = opts.createCommentNode(comment, replyComment);
|
|
3969
|
+
if (comment.visible) {
|
|
3970
|
+
const $comment = node.getEl();
|
|
3971
|
+
const $listCommentsWrap = opts.$commentsWrap;
|
|
3972
|
+
if (insertMode === "append")
|
|
3973
|
+
$listCommentsWrap == null ? void 0 : $listCommentsWrap.append($comment);
|
|
3974
|
+
if (insertMode === "prepend")
|
|
3975
|
+
$listCommentsWrap == null ? void 0 : $listCommentsWrap.prepend($comment);
|
|
3976
|
+
node.getRender().playFadeAnim();
|
|
3977
|
+
}
|
|
3978
|
+
node.getRender().checkHeightLimit();
|
|
3979
|
+
return node;
|
|
3980
|
+
}
|
|
3981
|
+
class ListLayout {
|
|
3982
|
+
constructor(options) {
|
|
3983
|
+
this.options = options;
|
|
3984
|
+
}
|
|
3985
|
+
getStrategy() {
|
|
3986
|
+
return this.options.flatMode ? createFlatStrategy(this.options) : createNestStrategy(this.options);
|
|
3987
|
+
}
|
|
3988
|
+
import(comments) {
|
|
3989
|
+
this.getStrategy().import(comments);
|
|
3962
3990
|
}
|
|
3963
|
-
|
|
3964
|
-
|
|
3965
|
-
scrollIntoView(comment.getEl());
|
|
3991
|
+
insert(comment, replyComment) {
|
|
3992
|
+
this.getStrategy().insert(comment, replyComment);
|
|
3966
3993
|
}
|
|
3967
3994
|
}
|
|
3968
3995
|
function Detect(userAgent) {
|
|
@@ -4225,7 +4252,7 @@ const CommentHTML = '<div class="atk-comment-wrap">\n <div class="atk-comment">
|
|
|
4225
4252
|
function renderAvatar(r) {
|
|
4226
4253
|
const $avatar = r.$el.querySelector(".atk-avatar");
|
|
4227
4254
|
const $avatarImg = createElement("<img />");
|
|
4228
|
-
const avatarURLBuilder = r.
|
|
4255
|
+
const avatarURLBuilder = r.opts.avatarURLBuilder;
|
|
4229
4256
|
$avatarImg.src = avatarURLBuilder ? avatarURLBuilder(r.data) : r.comment.getGravatarURL();
|
|
4230
4257
|
if (r.data.link) {
|
|
4231
4258
|
const $avatarA = createElement('<a target="_blank" rel="noreferrer noopener nofollow"></a>');
|
|
@@ -4264,12 +4291,12 @@ function renderVerifyBadge(ctx) {
|
|
|
4264
4291
|
const badgeColor = ctx.data.badge_color;
|
|
4265
4292
|
if (badgeText) {
|
|
4266
4293
|
const $badge = createElement(`<span class="atk-badge"></span>`);
|
|
4267
|
-
$badge.innerText = badgeText.replace("管理员",
|
|
4294
|
+
$badge.innerText = badgeText.replace("管理员", t("admin"));
|
|
4268
4295
|
$badge.style.backgroundColor = badgeColor || "";
|
|
4269
4296
|
ctx.$headerBadgeWrap.append($badge);
|
|
4270
4297
|
}
|
|
4271
4298
|
if (ctx.data.is_pinned) {
|
|
4272
|
-
const $pinnedBadge = createElement(`<span class="atk-pinned-badge">${
|
|
4299
|
+
const $pinnedBadge = createElement(`<span class="atk-pinned-badge">${t("pin")}</span>`);
|
|
4273
4300
|
ctx.$headerBadgeWrap.append($pinnedBadge);
|
|
4274
4301
|
}
|
|
4275
4302
|
}
|
|
@@ -4279,7 +4306,7 @@ function renderDate(ctx) {
|
|
|
4279
4306
|
$date.setAttribute("data-atk-comment-date", String(+new Date(ctx.data.date)));
|
|
4280
4307
|
}
|
|
4281
4308
|
function renderUABadge(ctx) {
|
|
4282
|
-
if (!ctx.
|
|
4309
|
+
if (!ctx.opts.uaBadge && !ctx.data.ip_region)
|
|
4283
4310
|
return;
|
|
4284
4311
|
let $uaWrap = ctx.$header.querySelector("atk-ua-wrap");
|
|
4285
4312
|
if (!$uaWrap) {
|
|
@@ -4292,7 +4319,7 @@ function renderUABadge(ctx) {
|
|
|
4292
4319
|
$regionBadge.innerText = ctx.data.ip_region;
|
|
4293
4320
|
$uaWrap.append($regionBadge);
|
|
4294
4321
|
}
|
|
4295
|
-
if (ctx.
|
|
4322
|
+
if (ctx.opts.uaBadge) {
|
|
4296
4323
|
const { browser, os } = ctx.comment.getUserUA();
|
|
4297
4324
|
if (String(browser).trim()) {
|
|
4298
4325
|
const $uaBrowser = createElement(`<span class="atk-ua ua-browser"></span>`);
|
|
@@ -4315,8 +4342,8 @@ function renderContent(r) {
|
|
|
4315
4342
|
r.$content.classList.add("atk-hide", "atk-type-collapsed");
|
|
4316
4343
|
const collapsedInfoEl = createElement(`
|
|
4317
4344
|
<div class="atk-collapsed">
|
|
4318
|
-
<span class="atk-text">${
|
|
4319
|
-
<span class="atk-show-btn">${
|
|
4345
|
+
<span class="atk-text">${t("collapsedMsg")}</span>
|
|
4346
|
+
<span class="atk-show-btn">${t("expand")}</span>
|
|
4320
4347
|
</div>`);
|
|
4321
4348
|
r.$body.insertAdjacentElement("beforeend", collapsedInfoEl);
|
|
4322
4349
|
const contentShowBtn = collapsedInfoEl.querySelector(".atk-show-btn");
|
|
@@ -4326,51 +4353,51 @@ function renderContent(r) {
|
|
|
4326
4353
|
r.$content.innerHTML = r.comment.getContentMarked();
|
|
4327
4354
|
r.$content.classList.remove("atk-hide");
|
|
4328
4355
|
playFadeInAnim(r.$content);
|
|
4329
|
-
contentShowBtn.innerText =
|
|
4356
|
+
contentShowBtn.innerText = t("collapse");
|
|
4330
4357
|
} else {
|
|
4331
4358
|
r.$content.innerHTML = "";
|
|
4332
4359
|
r.$content.classList.add("atk-hide");
|
|
4333
|
-
contentShowBtn.innerText =
|
|
4360
|
+
contentShowBtn.innerText = t("expand");
|
|
4334
4361
|
}
|
|
4335
4362
|
});
|
|
4336
4363
|
}
|
|
4337
4364
|
function renderReplyAt(r) {
|
|
4338
|
-
if (r.
|
|
4365
|
+
if (r.opts.flatMode || r.data.rid === 0)
|
|
4339
4366
|
return;
|
|
4340
|
-
if (!r.
|
|
4367
|
+
if (!r.opts.replyTo)
|
|
4341
4368
|
return;
|
|
4342
4369
|
r.$replyAt = createElement(`<span class="atk-item atk-reply-at"><span class="atk-arrow"></span><span class="atk-nick"></span></span>`);
|
|
4343
|
-
r.$replyAt.querySelector(".atk-nick").innerText = `${r.
|
|
4370
|
+
r.$replyAt.querySelector(".atk-nick").innerText = `${r.opts.replyTo.nick}`;
|
|
4344
4371
|
r.$replyAt.onclick = () => {
|
|
4345
4372
|
r.comment.getActions().goToReplyComment();
|
|
4346
4373
|
};
|
|
4347
4374
|
r.$headerBadgeWrap.insertAdjacentElement("afterend", r.$replyAt);
|
|
4348
4375
|
}
|
|
4349
4376
|
function renderReplyTo(r) {
|
|
4350
|
-
if (!r.
|
|
4377
|
+
if (!r.opts.flatMode)
|
|
4351
4378
|
return;
|
|
4352
|
-
if (!r.
|
|
4379
|
+
if (!r.opts.replyTo)
|
|
4353
4380
|
return;
|
|
4354
4381
|
r.$replyTo = createElement(`
|
|
4355
4382
|
<div class="atk-reply-to">
|
|
4356
|
-
<div class="atk-meta">${
|
|
4383
|
+
<div class="atk-meta">${t("reply")} <span class="atk-nick"></span>:</div>
|
|
4357
4384
|
<div class="atk-content"></div>
|
|
4358
4385
|
</div>`);
|
|
4359
4386
|
const $nick = r.$replyTo.querySelector(".atk-nick");
|
|
4360
|
-
$nick.innerText = `@${r.
|
|
4387
|
+
$nick.innerText = `@${r.opts.replyTo.nick}`;
|
|
4361
4388
|
$nick.onclick = () => {
|
|
4362
4389
|
r.comment.getActions().goToReplyComment();
|
|
4363
4390
|
};
|
|
4364
|
-
let replyContent = marked(r.
|
|
4365
|
-
if (r.
|
|
4366
|
-
replyContent = `[${
|
|
4391
|
+
let replyContent = marked(r.opts.replyTo.content);
|
|
4392
|
+
if (r.opts.replyTo.is_collapsed)
|
|
4393
|
+
replyContent = `[${t("collapsed")}]`;
|
|
4367
4394
|
r.$replyTo.querySelector(".atk-content").innerHTML = replyContent;
|
|
4368
4395
|
r.$body.prepend(r.$replyTo);
|
|
4369
4396
|
}
|
|
4370
4397
|
function renderPending(r) {
|
|
4371
4398
|
if (!r.data.is_pending)
|
|
4372
4399
|
return;
|
|
4373
|
-
const pendingEl = createElement(`<div class="atk-pending">${
|
|
4400
|
+
const pendingEl = createElement(`<div class="atk-pending">${t("pendingMsg")}</div>`);
|
|
4374
4401
|
r.$body.prepend(pendingEl);
|
|
4375
4402
|
}
|
|
4376
4403
|
class ActionBtn {
|
|
@@ -4523,14 +4550,14 @@ function renderActions(r) {
|
|
|
4523
4550
|
});
|
|
4524
4551
|
}
|
|
4525
4552
|
function renderVote(r) {
|
|
4526
|
-
if (!r.
|
|
4553
|
+
if (!r.opts.vote)
|
|
4527
4554
|
return;
|
|
4528
|
-
r.voteBtnUp = new ActionBtn(() => `${
|
|
4555
|
+
r.voteBtnUp = new ActionBtn(() => `${t("voteUp")} (${r.data.vote_up || 0})`).appendTo(r.$actions);
|
|
4529
4556
|
r.voteBtnUp.setClick(() => {
|
|
4530
4557
|
r.comment.getActions().vote("up");
|
|
4531
4558
|
});
|
|
4532
|
-
if (r.
|
|
4533
|
-
r.voteBtnDown = new ActionBtn(() => `${
|
|
4559
|
+
if (r.opts.voteDown) {
|
|
4560
|
+
r.voteBtnDown = new ActionBtn(() => `${t("voteDown")} (${r.data.vote_down || 0})`).appendTo(r.$actions);
|
|
4534
4561
|
r.voteBtnDown.setClick(() => {
|
|
4535
4562
|
r.comment.getActions().vote("down");
|
|
4536
4563
|
});
|
|
@@ -4539,20 +4566,16 @@ function renderVote(r) {
|
|
|
4539
4566
|
function renderReply(r) {
|
|
4540
4567
|
if (!r.data.is_allow_reply)
|
|
4541
4568
|
return;
|
|
4542
|
-
const replyBtn = createElement(`<span>${
|
|
4569
|
+
const replyBtn = createElement(`<span>${t("reply")}</span>`);
|
|
4543
4570
|
r.$actions.append(replyBtn);
|
|
4544
4571
|
replyBtn.addEventListener("click", (e) => {
|
|
4545
4572
|
e.stopPropagation();
|
|
4546
|
-
|
|
4547
|
-
r.ctx.replyComment(r.data, r.$el);
|
|
4548
|
-
} else {
|
|
4549
|
-
r.cConf.onReplyBtnClick();
|
|
4550
|
-
}
|
|
4573
|
+
r.opts.replyComment(r.data, r.$el);
|
|
4551
4574
|
});
|
|
4552
4575
|
}
|
|
4553
4576
|
function renderCollapse(r) {
|
|
4554
4577
|
const collapseBtn = new ActionBtn({
|
|
4555
|
-
text: () => r.data.is_collapsed ?
|
|
4578
|
+
text: () => r.data.is_collapsed ? t("expand") : t("collapse"),
|
|
4556
4579
|
adminOnly: true
|
|
4557
4580
|
});
|
|
4558
4581
|
collapseBtn.appendTo(r.$actions);
|
|
@@ -4562,7 +4585,7 @@ function renderCollapse(r) {
|
|
|
4562
4585
|
}
|
|
4563
4586
|
function renderModerator(r) {
|
|
4564
4587
|
const pendingBtn = new ActionBtn({
|
|
4565
|
-
text: () => r.data.is_pending ?
|
|
4588
|
+
text: () => r.data.is_pending ? t("pending") : t("approved"),
|
|
4566
4589
|
adminOnly: true
|
|
4567
4590
|
});
|
|
4568
4591
|
pendingBtn.appendTo(r.$actions);
|
|
@@ -4572,7 +4595,7 @@ function renderModerator(r) {
|
|
|
4572
4595
|
}
|
|
4573
4596
|
function renderPin(r) {
|
|
4574
4597
|
const pinnedBtn = new ActionBtn({
|
|
4575
|
-
text: () => r.data.is_pinned ?
|
|
4598
|
+
text: () => r.data.is_pinned ? t("unpin") : t("pin"),
|
|
4576
4599
|
adminOnly: true
|
|
4577
4600
|
});
|
|
4578
4601
|
pinnedBtn.appendTo(r.$actions);
|
|
@@ -4582,19 +4605,19 @@ function renderPin(r) {
|
|
|
4582
4605
|
}
|
|
4583
4606
|
function renderEdit(r) {
|
|
4584
4607
|
const editBtn = new ActionBtn({
|
|
4585
|
-
text:
|
|
4608
|
+
text: t("edit"),
|
|
4586
4609
|
adminOnly: true
|
|
4587
4610
|
});
|
|
4588
4611
|
editBtn.appendTo(r.$actions);
|
|
4589
4612
|
editBtn.setClick(() => {
|
|
4590
|
-
r.
|
|
4613
|
+
r.opts.editComment(r.data, r.$el);
|
|
4591
4614
|
});
|
|
4592
4615
|
}
|
|
4593
4616
|
function renderDel(r) {
|
|
4594
4617
|
const delBtn = new ActionBtn({
|
|
4595
|
-
text:
|
|
4618
|
+
text: t("delete"),
|
|
4596
4619
|
confirm: true,
|
|
4597
|
-
confirmText:
|
|
4620
|
+
confirmText: t("deleteConfirm"),
|
|
4598
4621
|
adminOnly: true
|
|
4599
4622
|
});
|
|
4600
4623
|
delBtn.appendTo(r.$actions);
|
|
@@ -4636,18 +4659,21 @@ class Render {
|
|
|
4636
4659
|
__publicField(this, "$replyAt");
|
|
4637
4660
|
this.comment = comment;
|
|
4638
4661
|
}
|
|
4639
|
-
get ctx() {
|
|
4640
|
-
return this.comment.ctx;
|
|
4641
|
-
}
|
|
4642
4662
|
get data() {
|
|
4643
4663
|
return this.comment.getData();
|
|
4644
4664
|
}
|
|
4645
|
-
get
|
|
4646
|
-
return this.comment.
|
|
4647
|
-
}
|
|
4648
|
-
get cConf() {
|
|
4649
|
-
return this.comment.getConf();
|
|
4665
|
+
get opts() {
|
|
4666
|
+
return this.comment.getOpts();
|
|
4650
4667
|
}
|
|
4668
|
+
/**
|
|
4669
|
+
* Render the comment ui
|
|
4670
|
+
*
|
|
4671
|
+
* If comment data is updated, call this method to re-render the comment ui.
|
|
4672
|
+
* The method will be called multiple times, so it should be idempotent.
|
|
4673
|
+
*
|
|
4674
|
+
* Renders may add event listeners to the comment ui, so it should be called only once or override the original.
|
|
4675
|
+
* Please be aware of the memory leak caused by the event listener.
|
|
4676
|
+
*/
|
|
4651
4677
|
render() {
|
|
4652
4678
|
this.$el = createElement(CommentHTML);
|
|
4653
4679
|
this.$main = this.$el.querySelector(".atk-main");
|
|
@@ -4657,12 +4683,14 @@ class Render {
|
|
|
4657
4683
|
this.$actions = this.$el.querySelector(".atk-actions");
|
|
4658
4684
|
this.$el.setAttribute("id", `atk-comment-${this.data.id}`);
|
|
4659
4685
|
loadRenders(this);
|
|
4660
|
-
this
|
|
4686
|
+
if (this.$childrenWrap) {
|
|
4687
|
+
this.$main.append(this.$childrenWrap);
|
|
4688
|
+
}
|
|
4661
4689
|
return this.$el;
|
|
4662
4690
|
}
|
|
4663
4691
|
/** 内容限高检测 */
|
|
4664
4692
|
checkHeightLimit() {
|
|
4665
|
-
const conf = this.
|
|
4693
|
+
const conf = this.opts.heightLimit;
|
|
4666
4694
|
if (!conf || !conf.content || !conf.children)
|
|
4667
4695
|
return;
|
|
4668
4696
|
const contentMaxH = conf.content;
|
|
@@ -4696,24 +4724,21 @@ class Render {
|
|
|
4696
4724
|
playFadeAnimForBody() {
|
|
4697
4725
|
playFadeInAnim(this.comment.getRender().$body);
|
|
4698
4726
|
}
|
|
4727
|
+
/** Perform the flash animation */
|
|
4728
|
+
playFlashAnim() {
|
|
4729
|
+
this.$el.classList.remove("atk-flash-once");
|
|
4730
|
+
window.setTimeout(() => {
|
|
4731
|
+
this.$el.classList.add("atk-flash-once");
|
|
4732
|
+
}, 150);
|
|
4733
|
+
}
|
|
4699
4734
|
/** 获取子评论 Wrap */
|
|
4700
4735
|
getChildrenWrap() {
|
|
4701
|
-
return this.$childrenWrap;
|
|
4702
|
-
}
|
|
4703
|
-
/** 初始化子评论区域 Wrap */
|
|
4704
|
-
renderChildrenWrap() {
|
|
4705
4736
|
if (!this.$childrenWrap) {
|
|
4706
4737
|
this.$childrenWrap = createElement('<div class="atk-comment-children"></div>');
|
|
4707
4738
|
this.$main.append(this.$childrenWrap);
|
|
4708
4739
|
}
|
|
4709
4740
|
return this.$childrenWrap;
|
|
4710
4741
|
}
|
|
4711
|
-
/** 恢复原有的子评论区域 Wrap */
|
|
4712
|
-
recoveryChildrenWrap() {
|
|
4713
|
-
if (this.$childrenWrap) {
|
|
4714
|
-
this.$main.append(this.$childrenWrap);
|
|
4715
|
-
}
|
|
4716
|
-
}
|
|
4717
4742
|
/** 设置已读 */
|
|
4718
4743
|
setUnread(val) {
|
|
4719
4744
|
if (val)
|
|
@@ -4732,17 +4757,15 @@ class Render {
|
|
|
4732
4757
|
setOpenURL(url) {
|
|
4733
4758
|
this.setOpenable(true);
|
|
4734
4759
|
this.$el.onclick = (evt) => {
|
|
4735
|
-
evt.
|
|
4760
|
+
evt.stopPropagation();
|
|
4736
4761
|
window.open(url);
|
|
4737
|
-
if (this.cConf.openEvt)
|
|
4738
|
-
this.cConf.openEvt();
|
|
4739
4762
|
};
|
|
4740
4763
|
}
|
|
4741
4764
|
/** 设置点击评论时的操作 */
|
|
4742
4765
|
setOpenAction(action) {
|
|
4743
4766
|
this.setOpenable(true);
|
|
4744
4767
|
this.$el.onclick = (evt) => {
|
|
4745
|
-
evt.
|
|
4768
|
+
evt.stopPropagation();
|
|
4746
4769
|
action();
|
|
4747
4770
|
};
|
|
4748
4771
|
}
|
|
@@ -4752,26 +4775,26 @@ class CommentActions {
|
|
|
4752
4775
|
__publicField(this, "comment");
|
|
4753
4776
|
this.comment = comment;
|
|
4754
4777
|
}
|
|
4755
|
-
get ctx() {
|
|
4756
|
-
return this.comment.ctx;
|
|
4757
|
-
}
|
|
4758
4778
|
get data() {
|
|
4759
4779
|
return this.comment.getData();
|
|
4760
4780
|
}
|
|
4761
|
-
get
|
|
4762
|
-
return this.comment.
|
|
4781
|
+
get opts() {
|
|
4782
|
+
return this.comment.getOpts();
|
|
4783
|
+
}
|
|
4784
|
+
getApi() {
|
|
4785
|
+
return this.comment.getOpts().getApi();
|
|
4763
4786
|
}
|
|
4764
4787
|
/** 投票操作 */
|
|
4765
4788
|
vote(type) {
|
|
4766
4789
|
const actionBtn = type === "up" ? this.comment.getRender().voteBtnUp : this.comment.getRender().voteBtnDown;
|
|
4767
|
-
this.
|
|
4790
|
+
this.getApi().votes.vote(`comment_${type}`, this.data.id, __spreadValues({}, this.getApi().getUserFields())).then((res) => {
|
|
4768
4791
|
var _a, _b;
|
|
4769
4792
|
this.data.vote_up = res.data.up;
|
|
4770
4793
|
this.data.vote_down = res.data.down;
|
|
4771
4794
|
(_a = this.comment.getRender().voteBtnUp) == null ? void 0 : _a.updateText();
|
|
4772
4795
|
(_b = this.comment.getRender().voteBtnDown) == null ? void 0 : _b.updateText();
|
|
4773
4796
|
}).catch((err) => {
|
|
4774
|
-
actionBtn == null ? void 0 : actionBtn.setError(
|
|
4797
|
+
actionBtn == null ? void 0 : actionBtn.setError(t("voteFail"));
|
|
4775
4798
|
console.log(err);
|
|
4776
4799
|
});
|
|
4777
4800
|
}
|
|
@@ -4779,7 +4802,7 @@ class CommentActions {
|
|
|
4779
4802
|
adminEdit(type, btnElem) {
|
|
4780
4803
|
if (btnElem.isLoading)
|
|
4781
4804
|
return;
|
|
4782
|
-
btnElem.setLoading(true, `${
|
|
4805
|
+
btnElem.setLoading(true, `${t("editing")}...`);
|
|
4783
4806
|
const modify = __spreadValues({}, this.data);
|
|
4784
4807
|
if (type === "collapsed") {
|
|
4785
4808
|
modify.is_collapsed = !modify.is_collapsed;
|
|
@@ -4788,26 +4811,26 @@ class CommentActions {
|
|
|
4788
4811
|
} else if (type === "pinned") {
|
|
4789
4812
|
modify.is_pinned = !modify.is_pinned;
|
|
4790
4813
|
}
|
|
4791
|
-
this.
|
|
4814
|
+
this.getApi().comments.updateComment(this.data.id, __spreadValues({}, modify)).then((res) => {
|
|
4792
4815
|
btnElem.setLoading(false);
|
|
4793
4816
|
this.comment.setData(res.data);
|
|
4794
4817
|
}).catch((err) => {
|
|
4795
4818
|
console.error(err);
|
|
4796
|
-
btnElem.setError(
|
|
4819
|
+
btnElem.setError(t("editFail"));
|
|
4797
4820
|
});
|
|
4798
4821
|
}
|
|
4799
4822
|
/** 管理员 - 评论删除 */
|
|
4800
4823
|
adminDelete(btnElem) {
|
|
4801
4824
|
if (btnElem.isLoading)
|
|
4802
4825
|
return;
|
|
4803
|
-
btnElem.setLoading(true, `${
|
|
4804
|
-
this.
|
|
4826
|
+
btnElem.setLoading(true, `${t("deleting")}...`);
|
|
4827
|
+
this.getApi().comments.deleteComment(this.data.id).then(() => {
|
|
4805
4828
|
btnElem.setLoading(false);
|
|
4806
|
-
if (this.
|
|
4807
|
-
this.
|
|
4829
|
+
if (this.opts.onDelete)
|
|
4830
|
+
this.opts.onDelete(this.comment);
|
|
4808
4831
|
}).catch((e) => {
|
|
4809
4832
|
console.error(e);
|
|
4810
|
-
btnElem.setError(
|
|
4833
|
+
btnElem.setError(t("deleteFail"));
|
|
4811
4834
|
});
|
|
4812
4835
|
}
|
|
4813
4836
|
/** 快速跳转到该评论 */
|
|
@@ -4819,21 +4842,18 @@ class CommentActions {
|
|
|
4819
4842
|
window.dispatchEvent(new Event("hashchange"));
|
|
4820
4843
|
}
|
|
4821
4844
|
}
|
|
4822
|
-
class CommentNode
|
|
4823
|
-
//
|
|
4824
|
-
constructor(
|
|
4825
|
-
|
|
4845
|
+
class CommentNode {
|
|
4846
|
+
// 当前嵌套层数
|
|
4847
|
+
constructor(data, opts) {
|
|
4848
|
+
__publicField(this, "$el");
|
|
4826
4849
|
__publicField(this, "renderInstance");
|
|
4827
4850
|
__publicField(this, "actionInstance");
|
|
4828
4851
|
__publicField(this, "data");
|
|
4829
|
-
__publicField(this, "
|
|
4852
|
+
__publicField(this, "opts");
|
|
4830
4853
|
__publicField(this, "parent");
|
|
4831
4854
|
__publicField(this, "children", []);
|
|
4832
4855
|
__publicField(this, "nestCurt");
|
|
4833
|
-
|
|
4834
|
-
__publicField(this, "nestMax");
|
|
4835
|
-
this.nestMax = ctx.conf.nestMax || 3;
|
|
4836
|
-
this.cConf = conf;
|
|
4856
|
+
this.opts = opts;
|
|
4837
4857
|
this.data = __spreadValues({}, data);
|
|
4838
4858
|
this.data.date = this.data.date.replace(/-/g, "/");
|
|
4839
4859
|
this.parent = null;
|
|
@@ -4847,8 +4867,8 @@ class CommentNode extends Component {
|
|
|
4847
4867
|
if (this.$el)
|
|
4848
4868
|
this.$el.replaceWith(newEl);
|
|
4849
4869
|
this.$el = newEl;
|
|
4850
|
-
if (this.
|
|
4851
|
-
this.
|
|
4870
|
+
if (this.opts.onAfterRender)
|
|
4871
|
+
this.opts.onAfterRender();
|
|
4852
4872
|
}
|
|
4853
4873
|
/** 获取评论操作实例对象 */
|
|
4854
4874
|
getActions() {
|
|
@@ -4889,51 +4909,76 @@ class CommentNode extends Component {
|
|
|
4889
4909
|
return this.data.id;
|
|
4890
4910
|
}
|
|
4891
4911
|
/** 置入子评论 */
|
|
4892
|
-
putChild(
|
|
4893
|
-
|
|
4894
|
-
|
|
4895
|
-
this.children.push(
|
|
4896
|
-
const $
|
|
4912
|
+
putChild(childNode, insertMode = "append") {
|
|
4913
|
+
childNode.parent = this;
|
|
4914
|
+
childNode.nestCurt = this.nestCurt + 1;
|
|
4915
|
+
this.children.push(childNode);
|
|
4916
|
+
const $childrenWrap = this.getChildrenWrapEl();
|
|
4917
|
+
const $childComment = childNode.getEl();
|
|
4897
4918
|
if (insertMode === "append")
|
|
4898
|
-
$
|
|
4919
|
+
$childrenWrap.append($childComment);
|
|
4899
4920
|
else if (insertMode === "prepend")
|
|
4900
|
-
$
|
|
4901
|
-
|
|
4902
|
-
|
|
4921
|
+
$childrenWrap.prepend($childComment);
|
|
4922
|
+
childNode.getRender().playFadeAnim();
|
|
4923
|
+
childNode.getRender().checkHeightLimit();
|
|
4903
4924
|
}
|
|
4904
4925
|
/** 获取存放子评论的元素对象 */
|
|
4905
|
-
|
|
4906
|
-
|
|
4907
|
-
|
|
4908
|
-
if (this.nestCurt < this.nestMax) {
|
|
4909
|
-
$children = this.getRender().renderChildrenWrap();
|
|
4910
|
-
} else {
|
|
4911
|
-
$children = this.parent.getChildrenEl();
|
|
4912
|
-
}
|
|
4926
|
+
getChildrenWrapEl() {
|
|
4927
|
+
if (this.nestCurt >= this.opts.nestMax) {
|
|
4928
|
+
return this.parent.getChildrenWrapEl();
|
|
4913
4929
|
}
|
|
4914
|
-
return
|
|
4930
|
+
return this.getRender().getChildrenWrap();
|
|
4915
4931
|
}
|
|
4916
4932
|
/** 获取所有父评论 */
|
|
4917
4933
|
getParents() {
|
|
4918
|
-
const
|
|
4919
|
-
|
|
4920
|
-
|
|
4921
|
-
|
|
4922
|
-
|
|
4923
|
-
|
|
4924
|
-
|
|
4925
|
-
once(this);
|
|
4926
|
-
return parents;
|
|
4934
|
+
const flattenParents = [];
|
|
4935
|
+
let parent = this.parent;
|
|
4936
|
+
while (parent) {
|
|
4937
|
+
flattenParents.push(parent);
|
|
4938
|
+
parent = parent.getParent();
|
|
4939
|
+
}
|
|
4940
|
+
return flattenParents;
|
|
4927
4941
|
}
|
|
4928
|
-
/**
|
|
4942
|
+
/**
|
|
4943
|
+
* Get the element of the comment
|
|
4944
|
+
*
|
|
4945
|
+
* The `getEl()` will always return the latest $el after calling `render()`.
|
|
4946
|
+
* Please be aware of the memory leak if you use the $el reference directly.
|
|
4947
|
+
*/
|
|
4929
4948
|
getEl() {
|
|
4949
|
+
if (!this.$el)
|
|
4950
|
+
throw new Error("comment element not initialized before `getEl()`");
|
|
4930
4951
|
return this.$el;
|
|
4931
4952
|
}
|
|
4953
|
+
/**
|
|
4954
|
+
* Focus on the comment
|
|
4955
|
+
*
|
|
4956
|
+
* Scroll to the comment and perform flash animation
|
|
4957
|
+
*/
|
|
4958
|
+
focus() {
|
|
4959
|
+
if (!this.$el)
|
|
4960
|
+
throw new Error("comment element not initialized before `focus()`");
|
|
4961
|
+
this.getParents().forEach((p) => {
|
|
4962
|
+
p.getRender().heightLimitRemoveForChildren();
|
|
4963
|
+
});
|
|
4964
|
+
this.scrollIntoView();
|
|
4965
|
+
this.getRender().playFlashAnim();
|
|
4966
|
+
}
|
|
4967
|
+
scrollIntoView() {
|
|
4968
|
+
this.$el && scrollIntoView(this.$el, false, this.opts.scrollRelativeTo && this.opts.scrollRelativeTo());
|
|
4969
|
+
}
|
|
4970
|
+
/**
|
|
4971
|
+
* Remove the comment node
|
|
4972
|
+
*/
|
|
4973
|
+
remove() {
|
|
4974
|
+
var _a;
|
|
4975
|
+
(_a = this.$el) == null ? void 0 : _a.remove();
|
|
4976
|
+
}
|
|
4932
4977
|
/** 获取 Gravatar 头像 URL */
|
|
4933
4978
|
getGravatarURL() {
|
|
4934
4979
|
return getGravatarURL({
|
|
4935
|
-
mirror: this.
|
|
4936
|
-
params: this.
|
|
4980
|
+
mirror: this.opts.gravatar.mirror,
|
|
4981
|
+
params: this.opts.gravatar.params,
|
|
4937
4982
|
emailMD5: this.data.email_encrypted
|
|
4938
4983
|
});
|
|
4939
4984
|
}
|
|
@@ -4943,7 +4988,7 @@ class CommentNode extends Component {
|
|
|
4943
4988
|
}
|
|
4944
4989
|
/** 获取格式化后的日期 */
|
|
4945
4990
|
getDateFormatted() {
|
|
4946
|
-
return timeAgo(new Date(this.data.date),
|
|
4991
|
+
return timeAgo(new Date(this.data.date), t);
|
|
4947
4992
|
}
|
|
4948
4993
|
/** 获取用户 UserAgent 信息 */
|
|
4949
4994
|
getUserUA() {
|
|
@@ -4954,21 +4999,33 @@ class CommentNode extends Component {
|
|
|
4954
4999
|
};
|
|
4955
5000
|
}
|
|
4956
5001
|
/** 获取配置 */
|
|
4957
|
-
|
|
4958
|
-
return this.
|
|
5002
|
+
getOpts() {
|
|
5003
|
+
return this.opts;
|
|
4959
5004
|
}
|
|
4960
5005
|
}
|
|
4961
|
-
function
|
|
4962
|
-
|
|
4963
|
-
|
|
4964
|
-
isFlatMode: (_a = ctx.getData().getListLastFetch()) == null ? void 0 : _a.params.flatMode,
|
|
4965
|
-
afterRender: () => {
|
|
5006
|
+
function createCommentNode(ctx, comment, replyComment, opts) {
|
|
5007
|
+
const instance2 = new CommentNode(comment, {
|
|
5008
|
+
onAfterRender: () => {
|
|
4966
5009
|
ctx.trigger("comment-rendered", instance2);
|
|
4967
5010
|
},
|
|
4968
5011
|
onDelete: (c) => {
|
|
4969
5012
|
ctx.getData().deleteComment(c.getID());
|
|
4970
5013
|
},
|
|
4971
|
-
replyTo:
|
|
5014
|
+
replyTo: replyComment,
|
|
5015
|
+
// TODO simplify reference
|
|
5016
|
+
flatMode: typeof (opts == null ? void 0 : opts.forceFlatMode) === "boolean" ? opts == null ? void 0 : opts.forceFlatMode : ctx.conf.flatMode,
|
|
5017
|
+
gravatar: ctx.conf.gravatar,
|
|
5018
|
+
nestMax: ctx.conf.nestMax,
|
|
5019
|
+
heightLimit: ctx.conf.heightLimit,
|
|
5020
|
+
avatarURLBuilder: ctx.conf.avatarURLBuilder,
|
|
5021
|
+
scrollRelativeTo: ctx.conf.scrollRelativeTo,
|
|
5022
|
+
vote: ctx.conf.vote,
|
|
5023
|
+
voteDown: ctx.conf.voteDown,
|
|
5024
|
+
uaBadge: ctx.conf.uaBadge,
|
|
5025
|
+
// TODO: move to plugin folder and remove from core
|
|
5026
|
+
getApi: () => ctx.getApi(),
|
|
5027
|
+
replyComment: (c, $el) => ctx.replyComment(c, $el),
|
|
5028
|
+
editComment: (c, $el) => ctx.editComment(c, $el)
|
|
4972
5029
|
});
|
|
4973
5030
|
instance2.render();
|
|
4974
5031
|
return instance2;
|
|
@@ -5344,20 +5401,19 @@ class List extends Component {
|
|
|
5344
5401
|
getCommentNodes() {
|
|
5345
5402
|
return this.commentNodes;
|
|
5346
5403
|
}
|
|
5347
|
-
getListLayout() {
|
|
5404
|
+
getListLayout({ forceFlatMode } = {}) {
|
|
5348
5405
|
return new ListLayout({
|
|
5349
5406
|
$commentsWrap: this.$commentsWrap,
|
|
5350
5407
|
nestSortBy: this.ctx.conf.nestSort,
|
|
5351
5408
|
nestMax: this.ctx.conf.nestMax,
|
|
5352
|
-
flatMode: this.ctx.conf.flatMode,
|
|
5409
|
+
flatMode: typeof forceFlatMode === "boolean" ? forceFlatMode : this.ctx.conf.flatMode,
|
|
5353
5410
|
// flatMode must be boolean because it had been handled when Artalk.init
|
|
5354
|
-
createCommentNode: (d,
|
|
5355
|
-
const node =
|
|
5411
|
+
createCommentNode: (d, r) => {
|
|
5412
|
+
const node = createCommentNode(this.ctx, d, r, { forceFlatMode });
|
|
5356
5413
|
this.commentNodes.push(node);
|
|
5357
5414
|
return node;
|
|
5358
5415
|
},
|
|
5359
|
-
findCommentNode: (id) => this.commentNodes.find((c) => c.getID() === id)
|
|
5360
|
-
getCommentDataList: () => this.ctx.getData().getComments()
|
|
5416
|
+
findCommentNode: (id) => this.commentNodes.find((c) => c.getID() === id)
|
|
5361
5417
|
});
|
|
5362
5418
|
}
|
|
5363
5419
|
initCrudEvents() {
|
|
@@ -5365,8 +5421,10 @@ class List extends Component {
|
|
|
5365
5421
|
this.getListLayout().import(comments);
|
|
5366
5422
|
});
|
|
5367
5423
|
this.ctx.on("list-loaded", (comments) => {
|
|
5368
|
-
if (comments.length === 0)
|
|
5424
|
+
if (comments.length === 0) {
|
|
5425
|
+
this.commentNodes = [];
|
|
5369
5426
|
this.$commentsWrap.innerHTML = "";
|
|
5427
|
+
}
|
|
5370
5428
|
});
|
|
5371
5429
|
this.ctx.on("comment-inserted", (comment) => {
|
|
5372
5430
|
this.getListLayout().insert(comment);
|
|
@@ -5377,7 +5435,7 @@ class List extends Component {
|
|
|
5377
5435
|
console.error(`comment node id=${comment.id} not found`);
|
|
5378
5436
|
return;
|
|
5379
5437
|
}
|
|
5380
|
-
node.
|
|
5438
|
+
node.remove();
|
|
5381
5439
|
this.commentNodes = this.commentNodes.filter((c) => c.getID() !== comment.id);
|
|
5382
5440
|
});
|
|
5383
5441
|
this.ctx.on("comment-updated", (comment) => {
|
|
@@ -6862,62 +6920,50 @@ const UnreadBadge = (ctx) => {
|
|
|
6862
6920
|
showUnreadBadge(notifies.length || 0);
|
|
6863
6921
|
});
|
|
6864
6922
|
};
|
|
6865
|
-
const
|
|
6866
|
-
let
|
|
6867
|
-
const check2 = () => {
|
|
6923
|
+
const GotoDispatcher = (ctx) => {
|
|
6924
|
+
let lastID = 0;
|
|
6925
|
+
const check2 = ({ locker }) => {
|
|
6868
6926
|
const commentID = extractCommentID();
|
|
6869
6927
|
if (!commentID)
|
|
6870
6928
|
return;
|
|
6929
|
+
if (locker && lastID === commentID)
|
|
6930
|
+
return;
|
|
6931
|
+
lastID = commentID;
|
|
6871
6932
|
ctx.trigger("list-goto", commentID);
|
|
6872
|
-
delayGoto = true;
|
|
6873
|
-
};
|
|
6874
|
-
const hashChangeHandler = () => {
|
|
6875
|
-
delayGoto = false;
|
|
6876
|
-
check2();
|
|
6877
6933
|
};
|
|
6934
|
+
const hashChangeHandler = () => check2({ locker: false });
|
|
6935
|
+
const listLoadedHandler = () => check2({ locker: true });
|
|
6878
6936
|
ctx.on("mounted", () => {
|
|
6879
6937
|
window.addEventListener("hashchange", hashChangeHandler);
|
|
6880
|
-
ctx.on("list-loaded",
|
|
6938
|
+
ctx.on("list-loaded", listLoadedHandler);
|
|
6881
6939
|
});
|
|
6882
6940
|
ctx.on("unmounted", () => {
|
|
6883
6941
|
window.removeEventListener("hashchange", hashChangeHandler);
|
|
6884
|
-
ctx.off("list-loaded",
|
|
6885
|
-
});
|
|
6886
|
-
let foundID = 0;
|
|
6887
|
-
ctx.on("list-goto", (commentID) => {
|
|
6888
|
-
if (foundID === commentID)
|
|
6889
|
-
return;
|
|
6890
|
-
const comment = ctx.get("list").getCommentNodes().find((c) => c.getID() === commentID);
|
|
6891
|
-
if (!comment)
|
|
6892
|
-
return;
|
|
6893
|
-
foundID = commentID;
|
|
6894
|
-
comment.getParents().forEach((p) => {
|
|
6895
|
-
p.getRender().heightLimitRemoveForChildren();
|
|
6896
|
-
});
|
|
6897
|
-
const goTo = () => {
|
|
6898
|
-
scrollIntoView(comment.getEl(), false);
|
|
6899
|
-
comment.getEl().classList.remove("atk-flash-once");
|
|
6900
|
-
window.setTimeout(() => {
|
|
6901
|
-
comment.getEl().classList.add("atk-flash-once");
|
|
6902
|
-
}, 150);
|
|
6903
|
-
};
|
|
6904
|
-
if (!delayGoto)
|
|
6905
|
-
goTo();
|
|
6906
|
-
else
|
|
6907
|
-
window.setTimeout(() => goTo(), 350);
|
|
6942
|
+
ctx.off("list-loaded", listLoadedHandler);
|
|
6908
6943
|
});
|
|
6909
6944
|
};
|
|
6910
6945
|
function extractCommentID() {
|
|
6911
|
-
|
|
6946
|
+
const match = window.location.hash.match(/#atk-comment-([0-9]+)/);
|
|
6947
|
+
let commentId = match && match[1] && !Number.isNaN(parseFloat(match[1])) ? parseFloat(match[1]) : null;
|
|
6912
6948
|
if (!commentId) {
|
|
6913
|
-
|
|
6914
|
-
if (!match || !match[1] || Number.isNaN(Number(match[1])))
|
|
6915
|
-
return null;
|
|
6916
|
-
commentId = Number(match[1]);
|
|
6949
|
+
commentId = Number(getQueryParam("atk_comment"));
|
|
6917
6950
|
}
|
|
6918
6951
|
return commentId || null;
|
|
6919
6952
|
}
|
|
6920
|
-
const
|
|
6953
|
+
const GotoFocus = (ctx) => {
|
|
6954
|
+
ctx.on("list-goto", (commentID) => __async(void 0, null, function* () {
|
|
6955
|
+
let comment = ctx.getCommentNodes().find((c) => c.getID() === commentID);
|
|
6956
|
+
if (!comment) {
|
|
6957
|
+
const data = (yield ctx.getApi().comments.getComment(commentID)).data;
|
|
6958
|
+
ctx.get("list").getListLayout({ forceFlatMode: true }).insert(data.comment, data.reply_comment);
|
|
6959
|
+
comment = ctx.getCommentNodes().find((c) => c.getID() === commentID);
|
|
6960
|
+
}
|
|
6961
|
+
if (!comment)
|
|
6962
|
+
return;
|
|
6963
|
+
comment.focus();
|
|
6964
|
+
}));
|
|
6965
|
+
};
|
|
6966
|
+
const version = "2.8.1";
|
|
6921
6967
|
const Copyright = (ctx) => {
|
|
6922
6968
|
ctx.on("mounted", () => {
|
|
6923
6969
|
const list = ctx.get("list");
|
|
@@ -6928,14 +6974,7 @@ const Copyright = (ctx) => {
|
|
|
6928
6974
|
});
|
|
6929
6975
|
};
|
|
6930
6976
|
const NoComment = (ctx) => {
|
|
6931
|
-
let isFetching = false;
|
|
6932
|
-
ctx.on("list-fetch", (params) => {
|
|
6933
|
-
isFetching = true;
|
|
6934
|
-
});
|
|
6935
6977
|
ctx.on("list-loaded", (comments) => {
|
|
6936
|
-
if (!isFetching)
|
|
6937
|
-
return;
|
|
6938
|
-
isFetching = false;
|
|
6939
6978
|
const list = ctx.get("list");
|
|
6940
6979
|
const isNoComment = comments.length <= 0;
|
|
6941
6980
|
let $noComment = list.getCommentsWrapEl().querySelector(".atk-list-no-comment");
|
|
@@ -7187,7 +7226,8 @@ const ListPlugins = [
|
|
|
7187
7226
|
SidebarBtn,
|
|
7188
7227
|
UnreadBadge,
|
|
7189
7228
|
Dropdown,
|
|
7190
|
-
|
|
7229
|
+
GotoDispatcher,
|
|
7230
|
+
GotoFocus,
|
|
7191
7231
|
NoComment,
|
|
7192
7232
|
Copyright,
|
|
7193
7233
|
TimeTicking,
|
|
@@ -7211,6 +7251,7 @@ const PvCountWidget = (ctx) => {
|
|
|
7211
7251
|
ctx.watchConf([
|
|
7212
7252
|
"site",
|
|
7213
7253
|
"pageKey",
|
|
7254
|
+
"pageTitle",
|
|
7214
7255
|
"countEl",
|
|
7215
7256
|
"pvEl"
|
|
7216
7257
|
], (conf) => {
|
|
@@ -7218,6 +7259,7 @@ const PvCountWidget = (ctx) => {
|
|
|
7218
7259
|
getApi: () => ctx.getApi(),
|
|
7219
7260
|
siteName: conf.site,
|
|
7220
7261
|
pageKey: conf.pageKey,
|
|
7262
|
+
pageTitle: conf.pageTitle,
|
|
7221
7263
|
countEl: conf.countEl,
|
|
7222
7264
|
pvEl: conf.pvEl,
|
|
7223
7265
|
pvAdd: typeof ctx.conf.pvAdd === "boolean" ? ctx.conf.pvAdd : true
|
|
@@ -7229,10 +7271,10 @@ function initCountWidget(opt) {
|
|
|
7229
7271
|
if (opt.countEl && document.querySelector(opt.countEl)) {
|
|
7230
7272
|
refreshStatCount(opt, { query: "page_comment", numEl: opt.countEl });
|
|
7231
7273
|
}
|
|
7232
|
-
const initialData = opt.pvAdd ? {
|
|
7274
|
+
const initialData = opt.pvAdd && opt.pageKey ? {
|
|
7233
7275
|
[opt.pageKey]: (yield opt.getApi().pages.logPv({
|
|
7234
7276
|
page_key: opt.pageKey,
|
|
7235
|
-
page_title: opt.
|
|
7277
|
+
page_title: opt.pageTitle,
|
|
7236
7278
|
site_name: opt.siteName
|
|
7237
7279
|
})).data.pv
|
|
7238
7280
|
// pv+1 and get pv count
|
|
@@ -7249,7 +7291,7 @@ function initCountWidget(opt) {
|
|
|
7249
7291
|
function refreshStatCount(opt, args) {
|
|
7250
7292
|
return __async(this, null, function* () {
|
|
7251
7293
|
let data = args.data || {};
|
|
7252
|
-
let queryPageKeys = Array.from(document.querySelectorAll(args.numEl)).map((e) => e.getAttribute("data-page-key") || opt.pageKey).filter((k) => typeof data[k] !== "number");
|
|
7294
|
+
let queryPageKeys = Array.from(document.querySelectorAll(args.numEl)).map((e) => e.getAttribute("data-page-key") || opt.pageKey).filter((k) => k && typeof data[k] !== "number");
|
|
7253
7295
|
queryPageKeys = [...new Set(queryPageKeys)];
|
|
7254
7296
|
if (queryPageKeys.length > 0) {
|
|
7255
7297
|
const res = (yield opt.getApi().stats.getStats(args.query, {
|
|
@@ -7258,7 +7300,8 @@ function refreshStatCount(opt, args) {
|
|
|
7258
7300
|
})).data.data;
|
|
7259
7301
|
data = __spreadValues(__spreadValues({}, data), res);
|
|
7260
7302
|
}
|
|
7261
|
-
|
|
7303
|
+
const defaultCount = opt.pageKey ? data[opt.pageKey] : 0;
|
|
7304
|
+
applyCountData(args.numEl, data, defaultCount);
|
|
7262
7305
|
});
|
|
7263
7306
|
}
|
|
7264
7307
|
function applyCountData(selector, data, defaultCount) {
|
|
@@ -7447,7 +7490,6 @@ class Artalk {
|
|
|
7447
7490
|
initCountWidget({
|
|
7448
7491
|
getApi: () => new Api2(convertApiOptions(conf)),
|
|
7449
7492
|
siteName: conf.site,
|
|
7450
|
-
pageKey: conf.pageKey,
|
|
7451
7493
|
countEl: conf.countEl,
|
|
7452
7494
|
pvEl: conf.pvEl,
|
|
7453
7495
|
pvAdd: false
|