added 引用评论功能增加

This commit is contained in:
Vaica committed 2026-01-24 19:34:32 +08:00
1 parent b9fd4cb7f6
commit 34108e71d0
2 files changed
+237

No files matched your search

+133
View File
@@ -366,8 +366,141 @@ function initFloatingTools() {
// Listen for PJAX complete to update visibility
document.addEventListener('pjax:complete', function() {
updateFloatingToolsVisibility();
hideSelectionPopup();
});
document.addEventListener('DOMContentLoaded', function() {
initFloatingTools();
initSelectionPopup();
});
// Selection Popup Logic
let selectionPopup = null;
let selectionTimeout;
function initSelectionPopup() {
if (document.getElementById('selection-popup')) return;
selectionPopup = document.createElement('div');
selectionPopup.id = 'selection-popup';
selectionPopup.innerHTML = '<i class="ri-chat-quote-line"></i> <span>引用评论</span>';
document.body.appendChild(selectionPopup);
// Prevent mousedown on popup from clearing selection
selectionPopup.addEventListener('mousedown', function(e) {
e.preventDefault();
e.stopPropagation();
});
// Handle click on popup
selectionPopup.addEventListener('click', function(e) {
e.preventDefault();
e.stopPropagation();
let selection = window.getSelection().toString();
// Optimize: Remove extra whitespace and limit length
if (selection) {
// Collapse multiple empty lines into max 2 newlines, and trim each line
selection = selection.split('\n')
.map(line => line.trim())
.filter(line => line !== '')
.join('\n');
if (selection.length > 500) {
selection = selection.substring(0, 500) + '...';
}
scrollToCommentsAndQuote(selection);
hideSelectionPopup();
window.getSelection().removeAllRanges();
}
});
// Global listeners for selection
document.addEventListener('mouseup', handleSelectionChange);
document.addEventListener('keyup', handleSelectionChange);
}
function hideSelectionPopup() {
if (selectionPopup) {
selectionPopup.style.display = 'none';
}
}
function handleSelectionChange(e) {
// Debounce to avoid rapid firing
clearTimeout(selectionTimeout);
selectionTimeout = setTimeout(() => {
const selection = window.getSelection();
const text = selection.toString().trim();
const content = document.querySelector('.post-content'); // Main article container
if (!selectionPopup || !content) return;
// Check if selection is empty
if (!text || selection.rangeCount === 0) {
hideSelectionPopup();
return;
}
const range = selection.getRangeAt(0);
// Check if the common ancestor is inside .post-content
// Optimization: Check container existence before heavy contains check
if (!content.contains(range.commonAncestorContainer)) {
hideSelectionPopup();
return;
}
// Optimization: Use requestAnimationFrame for UI updates
requestAnimationFrame(() => {
// Show first to ensure measurements if needed (though we set top/left directly)
selectionPopup.style.display = 'flex';
// Position logic: Follow mouse if available (mouseup), else fallback to selection rect (keyup)
if (e && e.type === 'mouseup') {
// Optimization: Avoid getBoundingClientRect on mouseup
// Position above the mouse cursor
selectionPopup.style.top = `${e.clientY - 40}px`;
selectionPopup.style.left = `${e.clientX}px`;
} else {
// Fallback for keyboard selection (needs rect)
const rect = range.getBoundingClientRect();
// Check if visible and valid
if (rect.width === 0 || rect.height === 0) {
hideSelectionPopup();
return;
}
selectionPopup.style.top = `${rect.top}px`;
selectionPopup.style.left = `${rect.left + rect.width / 2}px`;
}
});
}, 150);
}
function scrollToCommentsAndQuote(text) {
const comments = document.getElementById('Comments');
if (comments) {
comments.scrollIntoView({ behavior: 'smooth' });
// Wait for scroll to complete (approximate)
setTimeout(() => {
// Find Artalk textarea
const textarea = document.querySelector('.atk-textarea');
if (textarea) {
const quote = `> ${text}\n\n`;
// Overwrite existing content as requested
textarea.value = quote;
textarea.focus();
// Trigger input event for Vue/React binding (Artalk uses Vue)
textarea.dispatchEvent(new Event('input', { bubbles: true }));
textarea.dispatchEvent(new Event('change', { bubbles: true }));
if (window.Qmsg) {
Qmsg.success('引用成功');
}
}
}, 500);
}
}