185 lines
8.4 KiB
JavaScript
185 lines
8.4 KiB
JavaScript
// Global Artalk Initialization Function (Supports PJAX)
|
|
window.initArtalk = function() {
|
|
if (!document.querySelector("#Comments")) return;
|
|
|
|
// Check if configuration exists
|
|
if (!window.artalkConfig) {
|
|
console.warn('window.artalkConfig is not defined. Skipping Artalk init.');
|
|
return;
|
|
}
|
|
|
|
// Check if Artalk library is loaded
|
|
if (typeof Artalk === 'undefined') {
|
|
console.warn('Artalk library is not loaded yet. Waiting for bundle...');
|
|
return;
|
|
}
|
|
|
|
try {
|
|
// Logic for caching Artalk configuration to speed up rendering
|
|
// 1. Manual Refresh (F5): Request from server and save to localStorage
|
|
// 2. PJAX: Load from localStorage if available
|
|
|
|
// Initialize initialization count to track PJAX usage
|
|
if (typeof window.artalkInitCount === 'undefined') {
|
|
window.artalkInitCount = 0;
|
|
}
|
|
window.artalkInitCount++;
|
|
|
|
var config = Object.assign({}, window.artalkConfig); // Clone config
|
|
var server = config.server.replace(/\/$/, '');
|
|
var confKey = 'artalk_conf_' + btoa(server);
|
|
var cachedConf = null;
|
|
|
|
// Try to read cache
|
|
try {
|
|
var raw = localStorage.getItem(confKey);
|
|
if (raw) cachedConf = JSON.parse(raw);
|
|
} catch(e) {
|
|
console.warn('Failed to parse Artalk cache:', e);
|
|
}
|
|
|
|
// Decision: Use Cache or Fetch?
|
|
// Use cache only if:
|
|
// 1. Not the first load (PJAX)
|
|
// 2. Cache exists
|
|
if (window.artalkInitCount > 1 && cachedConf) {
|
|
// Merge cache into config
|
|
// CAUTION: cachedConf contains page-specific data (like pageKey) from the previous page.
|
|
// We must ensure current window.artalkConfig overwrites it.
|
|
try {
|
|
// Defensive copy to avoid mutating cached object
|
|
var mergedConfig = Object.assign({}, config);
|
|
Object.assign(mergedConfig, cachedConf);
|
|
Object.assign(mergedConfig, window.artalkConfig); // Re-apply current page config
|
|
mergedConfig.useBackendConf = false;
|
|
|
|
// Attempt to init with cache
|
|
window.artalk = Artalk.init(mergedConfig);
|
|
} catch (initErr) {
|
|
console.warn('Artalk init with cache failed, falling back to default:', initErr);
|
|
localStorage.removeItem(confKey); // Clear bad cache
|
|
window.artalk = Artalk.init(config); // Fallback to normal init
|
|
}
|
|
} else {
|
|
// First load or no cache: Allow Artalk to fetch (useBackendConf defaults to true)
|
|
window.artalk = Artalk.init(config);
|
|
}
|
|
|
|
var artalk = window.artalk; // Local reference
|
|
|
|
// Aggressive Config Saving Strategy
|
|
var saveConf = function() {
|
|
try {
|
|
// Attempt to find the full configuration object
|
|
// artalk.conf is the standard property in v2+
|
|
// artalk.ctx.conf is for internal context access
|
|
var remoteConf = artalk.conf || (artalk.ctx && artalk.ctx.conf);
|
|
|
|
if (remoteConf) {
|
|
// We only really want to cache the fields that come from the server,
|
|
// but saving the whole object is easier. We just have to be careful when merging.
|
|
localStorage.setItem(confKey, JSON.stringify(remoteConf));
|
|
// console.log('Artalk: Config cached to', confKey);
|
|
}
|
|
} catch(e) {
|
|
console.error('Artalk saveConf error:', e);
|
|
}
|
|
};
|
|
|
|
// Hook into multiple events to ensure we capture the config after it's loaded
|
|
// 'conf-loaded' is the ideal event if supported
|
|
artalk.on('conf-loaded', saveConf);
|
|
|
|
// 'mounted' is when the widget is ready
|
|
artalk.on('mounted', saveConf);
|
|
|
|
// 'list-loaded' means comments (and likely config) are fetched
|
|
artalk.on('list-loaded', saveConf);
|
|
|
|
// Fallback: Poll check after a few seconds (for slow networks)
|
|
setTimeout(saveConf, 2000);
|
|
setTimeout(saveConf, 5000);
|
|
|
|
// Handle list-loaded event for lazy loading avatars and animations
|
|
artalk.on('list-loaded', function() {
|
|
if (window.artalkConfig.aiComment) {
|
|
var ai = window.artalkConfig.aiComment;
|
|
var listBody = document.querySelector('.atk-list .atk-list-body');
|
|
if (listBody && !listBody.querySelector('.atk-ai-comment')) {
|
|
var aiCommentHtml = `
|
|
<div class="atk-comment-wrap atk-comment atk-ai-comment" id="atk-comment-ai">
|
|
<div class="atk-avatar" uk-scrollspy="cls: uk-animation-scale-up; delay: 200">
|
|
<img src="${ai.avatar}" alt="${ai.name}">
|
|
</div>
|
|
<div class="atk-main" uk-scrollspy="cls: uk-animation-slide-right-small; delay: 300">
|
|
<div class="atk-header">
|
|
<span class="atk-nick" uk-scrollspy="cls: uk-animation-slide-top-small; delay: 350">${ai.name}</span>
|
|
<span class="atk-badge">${window.artalkConfig.aiBadge || 'AI'}</span>
|
|
<span class="atk-date">${ai.date}</span>
|
|
</div>
|
|
<div class="atk-body">
|
|
<div class="atk-content">${ai.content}</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
`;
|
|
listBody.insertAdjacentHTML('afterbegin', aiCommentHtml);
|
|
|
|
// Hide "No Comment" placeholder if it exists
|
|
var noComment = document.querySelector('.atk-list-no-comment');
|
|
if (noComment) {
|
|
noComment.style.display = 'none';
|
|
}
|
|
}
|
|
}
|
|
|
|
// Add staggered animation to the comment list
|
|
var list = document.querySelector('.atk-list');
|
|
if (list) {
|
|
list.setAttribute('uk-scrollspy', 'target: > .atk-comment-wrap; cls: uk-animation-slide-bottom-small; delay: 50');
|
|
}
|
|
|
|
// Apply granular animations to inner elements
|
|
document.querySelectorAll('.atk-comment-wrap:not(.atk-ai-comment)').forEach(function(wrap) {
|
|
var avatar = wrap.querySelector('.atk-avatar');
|
|
if (avatar) avatar.setAttribute('uk-scrollspy', 'cls: uk-animation-scale-up; delay: 200');
|
|
|
|
var main = wrap.querySelector('.atk-main');
|
|
if (main) main.setAttribute('uk-scrollspy', 'cls: uk-animation-slide-right-small; delay: 300');
|
|
|
|
var nick = wrap.querySelector('.atk-nick');
|
|
if (nick) nick.setAttribute('uk-scrollspy', 'cls: uk-animation-slide-top-small; delay: 350');
|
|
});
|
|
|
|
// Find all avatars in the comment list
|
|
// We let lazyload.js handle the avatars automatically by calling lazyLoadAgain()
|
|
// which will find these new images, set the placeholder, and observe them.
|
|
|
|
// Trigger lazy load update
|
|
if (window.lazyLoadAgain) {
|
|
window.lazyLoadAgain();
|
|
}
|
|
|
|
// Force hide "No Comment" if AI comment exists
|
|
if (window.artalkConfig.aiComment) {
|
|
var checkNoComment = setInterval(function() {
|
|
var noComment = document.querySelector('.atk-list-no-comment');
|
|
var aiComment = document.querySelector('.atk-ai-comment');
|
|
if (aiComment && noComment && noComment.style.display !== 'none') {
|
|
noComment.style.display = 'none';
|
|
}
|
|
if (!document.querySelector('#Comments')) {
|
|
clearInterval(checkNoComment);
|
|
}
|
|
}, 500);
|
|
|
|
// Clear interval after 10 seconds to save resources
|
|
setTimeout(function() { clearInterval(checkNoComment); }, 10000);
|
|
}
|
|
});
|
|
|
|
} catch (e) {
|
|
console.error('Artalk init failed:', e);
|
|
}
|
|
};
|