Spaces:
Running
Running
Upload 104 files
Browse files- 前端页面/social/评论与互动组件.js +39 -0
前端页面/social/评论与互动组件.js
CHANGED
|
@@ -29,6 +29,7 @@ export function createCommentSection(itemId, commentsData, currentUser, onCountC
|
|
| 29 |
let currentReplyTarget = null;
|
| 30 |
let sending = false, deleting = false, blocked = false, scope = null, constructing = true, observer;
|
| 31 |
let active = true, generation = 0, writePending = false;
|
|
|
|
| 32 |
const account = currentUser?.account || null;
|
| 33 |
const matches = captureRequestSession();
|
| 34 |
const sessionMatches = () => matches() && (getUser()?.account || null) === account;
|
|
@@ -56,6 +57,40 @@ export function createCommentSection(itemId, commentsData, currentUser, onCountC
|
|
| 56 |
inputArea.setAttribute('aria-busy', String(busy));
|
| 57 |
listArea.querySelectorAll('.reply-btn,.delete-btn').forEach(button => { button.disabled = busy || blocked; });
|
| 58 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 59 |
function unconfirmed() {
|
| 60 |
blocked = true;
|
| 61 |
notice.textContent = t('social.comment_unconfirmed');
|
|
@@ -227,6 +262,7 @@ export function createCommentSection(itemId, commentsData, currentUser, onCountC
|
|
| 227 |
const text = inputField.value.trim();
|
| 228 |
if (!text) return;
|
| 229 |
|
|
|
|
| 230 |
const operationGeneration = generation;
|
| 231 |
sending = true;
|
| 232 |
const submittedValue = inputField.value;
|
|
@@ -270,6 +306,7 @@ export function createCommentSection(itemId, commentsData, currentUser, onCountC
|
|
| 270 |
else unconfirmed();
|
| 271 |
} finally {
|
| 272 |
if (current() && operationGeneration === generation) { writePending = false; sending = false; setControls(); }
|
|
|
|
| 273 |
}
|
| 274 |
};
|
| 275 |
|
|
@@ -282,6 +319,7 @@ export function createCommentSection(itemId, commentsData, currentUser, onCountC
|
|
| 282 |
invalidate: () => { notice.textContent = t('auth.session_changed'); container.append(notice); }
|
| 283 |
});
|
| 284 |
scope.addCleanup(() => {
|
|
|
|
| 285 |
active = false; generation++;
|
| 286 |
observer?.disconnect(); confirmationAbort.abort();
|
| 287 |
inputField.value = ''; currentReplyTarget = null; commentsData = [];
|
|
@@ -291,6 +329,7 @@ export function createCommentSection(itemId, commentsData, currentUser, onCountC
|
|
| 291 |
const next = !!value;
|
| 292 |
if (next === active) return;
|
| 293 |
if (next && !scope.isCurrent()) return;
|
|
|
|
| 294 |
generation++;
|
| 295 |
active = next;
|
| 296 |
if (!next) {
|
|
|
|
| 29 |
let currentReplyTarget = null;
|
| 30 |
let sending = false, deleting = false, blocked = false, scope = null, constructing = true, observer;
|
| 31 |
let active = true, generation = 0, writePending = false;
|
| 32 |
+
let sendFocus = null;
|
| 33 |
const account = currentUser?.account || null;
|
| 34 |
const matches = captureRequestSession();
|
| 35 |
const sessionMatches = () => matches() && (getUser()?.account || null) === account;
|
|
|
|
| 57 |
inputArea.setAttribute('aria-busy', String(busy));
|
| 58 |
listArea.querySelectorAll('.reply-btn,.delete-btn').forEach(button => { button.disabled = busy || blocked; });
|
| 59 |
}
|
| 60 |
+
function clearSendFocus(record = sendFocus) {
|
| 61 |
+
if (!record || record !== sendFocus) return;
|
| 62 |
+
document.removeEventListener('focusin', record.onFocus, true);
|
| 63 |
+
document.removeEventListener('pointerdown', record.onPointer, true);
|
| 64 |
+
sendFocus = null;
|
| 65 |
+
}
|
| 66 |
+
function captureSendFocus() {
|
| 67 |
+
clearSendFocus();
|
| 68 |
+
if (document.activeElement !== submitBtn) return null;
|
| 69 |
+
const record = { generation };
|
| 70 |
+
record.onFocus = event => {
|
| 71 |
+
if (event.target !== submitBtn && event.target !== document.body) clearSendFocus(record);
|
| 72 |
+
};
|
| 73 |
+
record.onPointer = () => clearSendFocus(record);
|
| 74 |
+
sendFocus = record;
|
| 75 |
+
document.addEventListener('focusin', record.onFocus, true);
|
| 76 |
+
document.addEventListener('pointerdown', record.onPointer, true);
|
| 77 |
+
return record;
|
| 78 |
+
}
|
| 79 |
+
function restoreSendFocus(record) {
|
| 80 |
+
if (!record || record !== sendFocus) return;
|
| 81 |
+
const target = blocked ? notice : inputField;
|
| 82 |
+
const owned = current() && record.generation === generation && document.hasFocus()
|
| 83 |
+
&& (document.activeElement === document.body || document.activeElement === submitBtn)
|
| 84 |
+
&& !container.closest('[inert], [hidden], [aria-hidden="true"]')
|
| 85 |
+
&& target.isConnected && target.getClientRects().length > 0
|
| 86 |
+
&& getComputedStyle(target).visibility !== 'hidden';
|
| 87 |
+
clearSendFocus(record);
|
| 88 |
+
if (owned) {
|
| 89 |
+
if (target === notice) notice.tabIndex = -1;
|
| 90 |
+
target.focus({ preventScroll: true });
|
| 91 |
+
}
|
| 92 |
+
}
|
| 93 |
+
|
| 94 |
function unconfirmed() {
|
| 95 |
blocked = true;
|
| 96 |
notice.textContent = t('social.comment_unconfirmed');
|
|
|
|
| 262 |
const text = inputField.value.trim();
|
| 263 |
if (!text) return;
|
| 264 |
|
| 265 |
+
const focusRecord = captureSendFocus();
|
| 266 |
const operationGeneration = generation;
|
| 267 |
sending = true;
|
| 268 |
const submittedValue = inputField.value;
|
|
|
|
| 306 |
else unconfirmed();
|
| 307 |
} finally {
|
| 308 |
if (current() && operationGeneration === generation) { writePending = false; sending = false; setControls(); }
|
| 309 |
+
restoreSendFocus(focusRecord);
|
| 310 |
}
|
| 311 |
};
|
| 312 |
|
|
|
|
| 319 |
invalidate: () => { notice.textContent = t('auth.session_changed'); container.append(notice); }
|
| 320 |
});
|
| 321 |
scope.addCleanup(() => {
|
| 322 |
+
clearSendFocus();
|
| 323 |
active = false; generation++;
|
| 324 |
observer?.disconnect(); confirmationAbort.abort();
|
| 325 |
inputField.value = ''; currentReplyTarget = null; commentsData = [];
|
|
|
|
| 329 |
const next = !!value;
|
| 330 |
if (next === active) return;
|
| 331 |
if (next && !scope.isCurrent()) return;
|
| 332 |
+
clearSendFocus();
|
| 333 |
generation++;
|
| 334 |
active = next;
|
| 335 |
if (!next) {
|