/** * @fileoverview Content Rotation Library UI & Post Grid Renderer * @module ui/rotation-ui * @description بناء واجهة مكتبة تدوير المنشورات، رسم شبكة المنشورات بنظام الصفحات، وعرض مؤشرات الكفاءة. */ (global => { 'use strict'; const state = global.FritreeRotationState; /** * بناء الهيكل البصري لقسم مكتبة المحتوى والتدوير */ const tryBuildLibraryLayout = () => { const sidebar = document.getElementById('bmh59axx92'); const contentArea = document.getElementById('s7ihkirolg'); if (!sidebar || !contentArea) return false; if (!sidebar.querySelector('[data-target="i2ohy2hnfl"]')) { const navItem = document.createElement('div'); navItem.className = 'f2rj8bz2yt'; navItem.setAttribute('data-target', 'i2ohy2hnfl'); navItem.innerHTML = ' مكتبة المحتوى والتدوير'; sidebar.appendChild(navItem); navItem.addEventListener('click', () => { window.location.hash = 'i2ohy2hnfl'; }); } const host = document.getElementById('fritree-dynamic-panes-host') || contentArea; let pane = document.getElementById('i2ohy2hnfl'); if (pane) { if (pane.parentElement !== host) { host.appendChild(pane); } return true; } pane = document.createElement('section'); pane.className = 'rjiai07g77'; pane.id = 'i2ohy2hnfl'; pane.innerHTML = `

مركز إدارة مكتبة المحتوى وتدوير المنشورات

نظام التناوب التلقائي الذكي يضمن كسر بصمة النشر وتفادي الحظر تماماً.

وضع التدوير معطل
المنشورات والأرشيف
الحزم المخصصة
رسائل المتابعة
تقييم الأداء والكفاءة
(المحدد: 0)
`; host.appendChild(pane); return true; }; /** * تحديد أيقونة التصنيف المناسبة لمحتوى المنشور */ const getIconForTemplateText = (text, categories) => { const raw = String(text || '').toLowerCase(); const catStr = String((categories || []).join(' ')).toLowerCase(); if (raw.includes('شقة') || raw.includes('عقار') || raw.includes('إيجار') || catStr.includes('عقارات')) { return ' '; } if (raw.includes('خصم') || raw.includes('تخفيض') || raw.includes('سعر') || catStr.includes('تجارة')) { return ' '; } if (raw.includes('برنامج') || raw.includes('تطوير') || raw.includes('موقع') || catStr.includes('تكنولوجيا')) { return ' '; } return ' '; }; const clearActiveObjectUrls = () => { if (state.activeObjectUrls && state.activeObjectUrls.size > 0) { state.activeObjectUrls.forEach(url => { try { URL.revokeObjectURL(url); } catch (e) {} }); state.activeObjectUrls.clear(); } else { state.activeObjectUrls = new Set(); } }; /** * رسم شبكة المنشورات مع ترقيم الصفحات */ const renderPreviousPostsGrid = () => { const container = document.getElementById('t9voacx68i'); const paginationContainer = document.getElementById('j023f3xaj4'); const selectedCountLbl = document.getElementById('dmq2snygti'); if (!container) return; container.innerHTML = ''; if (paginationContainer) paginationContainer.innerHTML = ''; clearActiveObjectUrls(); if (selectedCountLbl) { selectedCountLbl.textContent = `(المحدد: ${state.selectedPrevPostIds.size.toLocaleString('en-US')})`; } const query = (document.getElementById('shp1ga2pfn')?.value || '').toLowerCase().trim(); const statusFilter = document.getElementById('err5grkpdo')?.value || 'all'; const sortBy = document.getElementById('iinfss1m0l')?.value || 'newest'; const keywordFilter = (document.getElementById('r0lcfjfd3x')?.value || '').toLowerCase().trim(); const categoryFilter = (document.getElementById('xfbqqzr0sf')?.value || '').toLowerCase().trim(); const notesFilter = (document.getElementById('skxbsmas4f')?.value || '').toLowerCase().trim(); const followupDateFilter = document.getElementById('nofcqdmp2i')?.value || ''; const filtered = (state.previousPostsData || []).filter(p => { const textContent = p.text || ''; const matchSearch = String(textContent).toLowerCase().includes(query) || (p.title && String(p.title).toLowerCase().includes(query)); let matchStatus = statusFilter === 'all' || p.status === statusFilter; let matchKeyword = !keywordFilter || p.keywords?.some(k => String(k).toLowerCase().includes(keywordFilter)); let matchCategory = !categoryFilter || p.categories?.some(c => String(c).toLowerCase().includes(categoryFilter)); let matchNotes = !notesFilter || (p.notes && String(p.notes).toLowerCase().includes(notesFilter)); let matchFollowUpDate = !followupDateFilter || p.followUpDate === followupDateFilter; return matchSearch && matchStatus && matchKeyword && matchCategory && matchNotes && matchFollowUpDate; }); if (sortBy === 'newest') filtered.sort((a,b) => new Date(b.entryDate || b.date) - new Date(a.entryDate || a.date)); else if (sortBy === 'oldest') filtered.sort((a,b) => new Date(a.entryDate || a.date) - new Date(b.entryDate || b.date)); else if (sortBy === 'most_pub') filtered.sort((a,b) => (b.stats?.usage || 0) - (a.stats?.usage || 0)); else if (sortBy === 'least_pub') filtered.sort((a,b) => (a.stats?.usage || 0) - (b.stats?.usage || 0)); else if (sortBy === 'highest_score') filtered.sort((a,b) => (b.score || 0) - (a.score || 0)); const totalItems = filtered.length; const totalPages = Math.ceil(totalItems / state.itemsPerPage); if (state.currentPage > totalPages) state.currentPage = Math.max(1, totalPages); if (totalItems === 0) { container.innerHTML = `
لم نجد أي منشورات مطابقة لشروط البحث والفلترة في الأرشيف.
`; return; } const startIndex = (state.currentPage - 1) * state.itemsPerPage; const pageItems = filtered.slice(startIndex, startIndex + state.itemsPerPage); // 1. عرض البطاقات (Cards View) if (state.viewMode === 'cards') { const cardsGrid = document.createElement('div'); cardsGrid.style.cssText = 'display: grid; grid-template-columns: repeat(auto-fill, minmax(clamp(250px, 24vw, 320px), 1fr)); gap: 12px; box-sizing: border-box;'; pageItems.forEach(p => { const isSelected = state.selectedPrevPostIds.has(p.id); const scoreVal = p.score || 50; const textIcon = getIconForTemplateText(p.text, p.categories); const card = document.createElement('div'); card.style.cssText = ` background: var(--bg-card); border: 1px solid ${isSelected ? '#0d9488' : 'var(--border)'}; border-radius: var(--radius-lg); padding: 14px; display: flex; flex-direction: column; justify-content: space-between; gap: 8px; box-shadow: var(--shadow-xs); direction: rtl; text-align: right; box-sizing: border-box; ${isSelected ? 'background: rgba(13, 148, 136, 0.05);' : ''} `; let statClass = 'go30y9mfgh'; let statText = 'مسودة'; if (p.status === 'active') { statClass = 'go30y9mfgh success'; statText = 'نشط ومتاح'; } else if (p.status === 'frozen') { statClass = 'go30y9mfgh pending'; statText = 'مجمد ومحفوظ'; } else if (p.status === 'inactive') { statClass = 'go30y9mfgh failed'; statText = 'معطل ومستبعد'; } card.innerHTML = `
${textIcon} ${p.title || 'أرشيف تدوير محفوظ'}
${statText}

${p.text || '[ملف وسائط وصور فقط]'}

مرات التشغيل: ${(p.stats?.usage || p.usageCount || 0).toLocaleString('en-US')} الكفاءة: ${scoreVal}%
${new Date(p.entryDate || p.date || Date.now()).toLocaleDateString('en-US')}
`; const chk = card.querySelector('.s5zou94lsv'); chk.addEventListener('change', async () => { if (chk.checked) state.selectedPrevPostIds.add(p.id); else state.selectedPrevPostIds.delete(p.id); await global.FritreeStorage.set('local_selected_prev_posts', Array.from(state.selectedPrevPostIds)); renderPreviousPostsGrid(); updateRotationIndicatorUI(); }); const mediaContainer = card.querySelector('.gdr4gjilbo'); if (p.mediaReferences && p.mediaReferences.length > 0 && mediaContainer) { p.mediaReferences.slice(0, 3).forEach(async m => { const thumbBlob = await global.FritreeStorage.get(`media_thumb_${m.id}`); if (thumbBlob) { const img = document.createElement('img'); const localUrl = URL.createObjectURL(thumbBlob); state.activeObjectUrls.add(localUrl); img.src = localUrl; img.style.cssText = 'width: 32px; height: 32px; object-fit: cover; border-radius: var(--radius-sm); border: 1px solid var(--border);'; mediaContainer.appendChild(img); } }); } else if (mediaContainer) { mediaContainer.innerHTML = ' بدون صور مرفقة'; } card.querySelector('.ysx77m6bsw').onclick = () => { if (global.FritreeRotationCreator && typeof global.FritreeRotationCreator.openEditModal === 'function') { global.FritreeRotationCreator.openEditModal(p.id); } }; card.querySelector('.fp89nb580e').onclick = async () => { if (confirm('هل تريد حذف هذا المنشور نهائياً من الذاكرة؟')) { if (p.mediaReferences) { p.mediaReferences.forEach(m => { global.FritreeStorage.remove(`media_blob_${m.id}`); global.FritreeStorage.remove(`media_thumb_${m.id}`); }); } state.previousPostsData = state.previousPostsData.filter(x => x.id !== p.id); state.selectedPrevPostIds.delete(p.id); await global.FritreeRotationStore.save(); renderPreviousPostsGrid(); updateRotationIndicatorUI(); } }; cardsGrid.appendChild(card); }); container.appendChild(cardsGrid); } else { // 2. عرض الجدول (Table View) const tableBox = document.createElement('div'); tableBox.className = 'diktqr0h64'; tableBox.style.cssText = 'max-height: 520px;'; tableBox.innerHTML = `
عنوان ومحتوى المنشور الحالة الاستخدام كفاءة النجاح الإجراءات
`; const tbody = tableBox.querySelector('#a8jg0f3yu7'); pageItems.forEach(p => { const tr = document.createElement('tr'); const isSelected = state.selectedPrevPostIds.has(p.id); if (isSelected) tr.style.backgroundColor = 'rgba(13, 148, 136, 0.08)'; const textIcon = getIconForTemplateText(p.text, p.categories); const scoreVal = p.score || 50; let statClass = 'go30y9mfgh'; let statText = 'مسودة'; if (p.status === 'active') { statClass = 'go30y9mfgh success'; statText = 'نشط ومتاح'; } else if (p.status === 'frozen') { statClass = 'go30y9mfgh pending'; statText = 'مجمد ومحفوظ'; } else if (p.status === 'inactive') { statClass = 'go30y9mfgh failed'; statText = 'معطل ومستبعد'; } tr.innerHTML = ` ${textIcon} ${p.title || 'منشور مؤرشف'}
${p.text || '[ملف وسائط وصور فقط]'}
${statText} ${(p.stats?.usage || p.usageCount || 0).toLocaleString('en-US')} مرة
الدرجة: ${scoreVal}%
`; const chk = tr.querySelector('.s5zou94lsv'); chk.addEventListener('change', async () => { if (chk.checked) state.selectedPrevPostIds.add(p.id); else state.selectedPrevPostIds.delete(p.id); await global.FritreeStorage.set('local_selected_prev_posts', Array.from(state.selectedPrevPostIds)); renderPreviousPostsGrid(); updateRotationIndicatorUI(); }); tr.querySelector('.k4j50z448o').onclick = () => { if (global.FritreeRotationCreator && typeof global.FritreeRotationCreator.openEditModal === 'function') { global.FritreeRotationCreator.openEditModal(p.id); } }; tr.querySelector('.h2o7c0chyq').onclick = async () => { if (confirm('هل تريد حذف هذا المنشور؟')) { state.previousPostsData = state.previousPostsData.filter(x => x.id !== p.id); state.selectedPrevPostIds.delete(p.id); await global.FritreeRotationStore.save(); renderPreviousPostsGrid(); updateRotationIndicatorUI(); } }; tbody.appendChild(tr); }); container.appendChild(tableBox); } // بناء شريط التنقل بين الصفحات بنظام متجاوب if (totalPages > 1 && paginationContainer) { const createPageButton = (text, targetPage, active = false, disabled = false) => { const btn = document.createElement('button'); btn.className = active ? 'itdnt14mss vn5qn7dmpk' : 'ipxi2jz4g0'; btn.style.cssText = `padding: 4px 10px; font-size: 11px; font-weight: 700; height: auto; min-height: 30px; min-width: 32px; ${active ? 'background:#0d9488; border-color:#0d9488; color:#fff;' : ''}`; btn.innerHTML = text; btn.disabled = disabled; if (!disabled && !active) { btn.addEventListener('click', () => { state.currentPage = targetPage; renderPreviousPostsGrid(); }); } return btn; }; paginationContainer.appendChild(createPageButton('', 1, false, state.currentPage === 1)); paginationContainer.appendChild(createPageButton('', state.currentPage - 1, false, state.currentPage === 1)); const maxVisiblePages = 5; let startPage = Math.max(1, state.currentPage - Math.floor(maxVisiblePages / 2)); let endPage = Math.min(totalPages, startPage + maxVisiblePages - 1); if (endPage - startPage + 1 < maxVisiblePages) { startPage = Math.max(1, endPage - maxVisiblePages + 1); } for (let i = startPage; i <= endPage; i++) { paginationContainer.appendChild(createPageButton(i.toLocaleString('en-US'), i, i === state.currentPage)); } paginationContainer.appendChild(createPageButton('', state.currentPage + 1, false, state.currentPage === totalPages)); paginationContainer.appendChild(createPageButton('', totalPages, false, state.currentPage === totalPages)); } }; /** * تحديث شارة ومؤشرات تشغيل التدوير التلقائي بالواجهة والمحرر */ const updateRotationIndicatorUI = async () => { const indicatorPanel = document.getElementById('h6gj77qmi8'); const composerPanel = document.getElementById('qw35f6nlli'); const postTextarea = document.getElementById('nmr6mtwgan'); if (state.isRotationActive) { if (indicatorPanel) indicatorPanel.style.display = 'block'; if (composerPanel) composerPanel.style.opacity = '0.5'; if (postTextarea) postTextarea.disabled = true; const activeCount = state.previousPostsData.filter(p => state.selectedPrevPostIds.has(p.id) && p.status === 'active').length; const countLabel = document.getElementById('g87druhllc'); if (countLabel) countLabel.textContent = activeCount.toLocaleString('en-US'); const rotationMode = global.FritreeStorage ? await global.FritreeStorage.get('local_rotation_mode', 'balanced') : 'balanced'; const modeLabel = document.getElementById('c8zauwlfq4'); let modeDisplay = 'الطابور المتوازن التلقائي'; if (rotationMode === 'weighted') modeDisplay = 'التوزيع الموزون حسب الأولوية'; if (rotationMode === 'high_perf') modeDisplay = 'التركيز على الأداء الأعلى نجاحاً'; if (rotationMode === 'newest') modeDisplay = 'الترتيب الزمني (الأحدث أولاً)'; if (rotationMode === 'oldest') modeDisplay = 'الترتيب الزمني (الأقدم أولاً)'; if (rotationMode === 'random') modeDisplay = 'اختيار عشوائي كلي'; if (modeLabel) modeLabel.textContent = modeDisplay; } else { if (indicatorPanel) indicatorPanel.style.display = 'none'; if (composerPanel) composerPanel.style.opacity = '1'; if (postTextarea) postTextarea.disabled = false; } }; const updateRotationBadgeInModal = () => { const badge = document.getElementById('qsexgowprz'); if (!badge) return; if (state.isRotationActive) { badge.className = "zcsc0rlnfn green"; badge.innerHTML = ' وضع التدوير نشط بالخلفية'; } else { badge.className = "zcsc0rlnfn red"; badge.innerHTML = ' وضع التدوير معطل'; } }; /** * تطبيق تغيير الحالة الجماعي على المنشورات المحددة * @param {string} newStatus ('active' | 'inactive' | 'frozen' | 'draft') */ const applyBatchStatusChange = async (newStatus) => { if (state.selectedPrevPostIds.size === 0) { alert('حدد منشوراً واحداً على الأقل أولاً!'); return; } state.previousPostsData.forEach(p => { if (state.selectedPrevPostIds.has(p.id)) { p.status = newStatus; } }); await global.FritreeRotationStore.save(); renderPreviousPostsGrid(); updateRotationIndicatorUI(); }; /** * حذف المنشورات المحددة جماعياً */ const deleteBatchSelectedPosts = async () => { if (state.selectedPrevPostIds.size === 0) { alert('حدد منشوراً واحداً على الأقل لحذفه!'); return; } if (confirm(`هل أنت متأكد من حذف [${state.selectedPrevPostIds.size}] منشور نهائياً من المكتبة؟`)) { state.previousPostsData.forEach(p => { if (state.selectedPrevPostIds.has(p.id) && p.mediaReferences) { p.mediaReferences.forEach(m => { global.FritreeStorage.remove(`media_blob_${m.id}`); global.FritreeStorage.remove(`media_thumb_${m.id}`); }); } }); state.previousPostsData = state.previousPostsData.filter(p => !state.selectedPrevPostIds.has(p.id)); state.selectedPrevPostIds.clear(); await global.FritreeRotationStore.save(); renderPreviousPostsGrid(); updateRotationIndicatorUI(); } }; /** * ربط أحداث التبويبات والفلاتر والأزرار */ const bindTabAndFilterEvents = () => { document.querySelectorAll('.w99i6dlj03').forEach(btn => { btn.addEventListener('click', () => { document.querySelectorAll('.w99i6dlj03').forEach(b => b.classList.remove('vn5qn7dmpk')); btn.classList.add('vn5qn7dmpk'); const targetPageId = btn.getAttribute('data-page'); ['ubfw9ctgy8', 'k4afmxnpzo', 'hj8qfhtxai', 'ghf74k092q', 'xpoqh5yufi'].forEach(pId => { const pageEl = document.getElementById(pId); if (pageEl) pageEl.style.display = (pId === targetPageId) ? 'block' : 'none'; }); if (targetPageId === 'ubfw9ctgy8') { state.currentPage = 1; renderPreviousPostsGrid(); } else if (targetPageId === 'k4afmxnpzo') { if (global.FritreeRotationGroups && typeof global.FritreeRotationGroups.renderGrid === 'function') { global.FritreeRotationGroups.renderGrid(); } } else if (targetPageId === 'hj8qfhtxai') { if (global.FritreeRotationCreator && typeof global.FritreeRotationCreator.openAddModal === 'function') { global.FritreeRotationCreator.openAddModal(); } } else if (targetPageId === 'ghf74k092q') { if (global.FritreeRotationFollowups && typeof global.FritreeRotationFollowups.renderList === 'function') { global.FritreeRotationFollowups.renderList(); } } else if (targetPageId === 'xpoqh5yufi') { if (global.FritreeRotationPerformance && typeof global.FritreeRotationPerformance.init === 'function') { global.FritreeRotationPerformance.init(); } } }); }); // زر إضافة منشور جديد const btnOpenAddPost = document.getElementById('g14kkl6isc'); if (btnOpenAddPost) { btnOpenAddPost.onclick = () => { if (global.FritreeRotationCreator && typeof global.FritreeRotationCreator.openAddModal === 'function') { global.FritreeRotationCreator.openAddModal(); } }; } // زر إنشاء حزمة مخصصة جديدة const btnOpenAddGroup = document.getElementById('t7ic4cbmt2'); if (btnOpenAddGroup) { btnOpenAddGroup.onclick = () => { if (global.FritreeRotationCreator && typeof global.FritreeRotationCreator.openEditGroupModal === 'function') { global.FritreeRotationCreator.openEditGroupModal(); } }; } // أزرار العمليات الجماعية const btnGroupFromSelected = document.getElementById('q2z8wc5j16'); if (btnGroupFromSelected) { btnGroupFromSelected.onclick = () => { if (state.selectedPrevPostIds.size === 0) { alert('اختر منشوراً واحداً على الأقل لدمجه وتجميعه داخل حزمة جديدة.'); return; } if (global.FritreeRotationCreator && typeof global.FritreeRotationCreator.openEditGroupModal === 'function') { global.FritreeRotationCreator.openEditGroupModal(null, Array.from(state.selectedPrevPostIds)); } }; } const btnBatchActivate = document.getElementById('t3kfunicmw'); if (btnBatchActivate) btnBatchActivate.onclick = () => applyBatchStatusChange('active'); const btnBatchDeactivate = document.getElementById('qbmxdznf5w'); if (btnBatchDeactivate) btnBatchDeactivate.onclick = () => applyBatchStatusChange('inactive'); const btnBatchFreeze = document.getElementById('dh8awhr7nd'); if (btnBatchFreeze) btnBatchFreeze.onclick = () => applyBatchStatusChange('frozen'); const btnBatchDraft = document.getElementById('id_b3p8'); if (btnBatchDraft) btnBatchDraft.onclick = () => applyBatchStatusChange('draft'); const btnBatchDelete = document.getElementById('qf0wkm8p09'); if (btnBatchDelete) btnBatchDelete.onclick = deleteBatchSelectedPosts; const btnCards = document.getElementById('nkpzszsrpv'); const btnTable = document.getElementById('kqlpqapqhv'); if (btnCards && btnTable) { btnCards.onclick = () => { state.viewMode = 'cards'; btnCards.classList.add('vn5qn7dmpk'); btnTable.classList.remove('vn5qn7dmpk'); renderPreviousPostsGrid(); }; btnTable.onclick = () => { state.viewMode = 'table'; btnTable.classList.add('vn5qn7dmpk'); btnCards.classList.remove('vn5qn7dmpk'); renderPreviousPostsGrid(); }; } const chkEnable = document.getElementById('iukycc01s4'); const modeSelect = document.getElementById('f8wo6rlhi6'); if (chkEnable) { chkEnable.addEventListener('change', async (e) => { state.isRotationActive = e.target.checked; await global.FritreeStorage.set('local_is_rotation_active', state.isRotationActive ? 'true' : 'false'); const details = document.getElementById('cz2owxca3z'); if (details) details.style.display = state.isRotationActive ? 'grid' : 'none'; updateRotationIndicatorUI(); updateRotationBadgeInModal(); }); } if (modeSelect) { modeSelect.addEventListener('change', async (e) => { await global.FritreeStorage.set('local_rotation_mode', e.target.value); updateRotationIndicatorUI(); }); } ['shp1ga2pfn', 'err5grkpdo', 'iinfss1m0l', 'r0lcfjfd3x', 'xfbqqzr0sf', 'skxbsmas4f', 'nofcqdmp2i'].forEach(id => { const el = document.getElementById(id); if (el) { const evType = (el.tagName === 'SELECT' || el.type === 'date') ? 'change' : 'input'; el.addEventListener(evType, () => { state.currentPage = 1; renderPreviousPostsGrid(); }); } }); const selectAllChk = document.getElementById('nur6b1ao2r'); if (selectAllChk) { selectAllChk.addEventListener('change', (e) => { const isChecked = e.target.checked; document.querySelectorAll('.s5zou94lsv').forEach(chk => { chk.checked = isChecked; if (isChecked) state.selectedPrevPostIds.add(chk.value); else state.selectedPrevPostIds.delete(chk.value); }); renderPreviousPostsGrid(); }); } }; /** * تهيئة وحدة واجهة التدوير */ const initRotationUI = async () => { const sidebar = document.getElementById('bmh59axx92'); const mainContentArea = document.getElementById('s7ihkirolg'); if (!sidebar || !mainContentArea) return false; tryBuildLibraryLayout(); if (global.FritreeRotationStore && typeof global.FritreeRotationStore.load === 'function') { await global.FritreeRotationStore.load(); } bindTabAndFilterEvents(); renderPreviousPostsGrid(); updateRotationIndicatorUI(); updateRotationBadgeInModal(); return true; }; /** * تصدير وحدة واجهة تدوير المنشورات */ global.FritreeRotation = { init: initRotationUI, isRotationActive: () => global.FritreeRotationState.isRotationActive, getPosts: () => global.FritreeRotationState.previousPostsData, getGroups: () => global.FritreeRotationState.postGroupsData, getSelectedIds: () => Array.from(global.FritreeRotationState.selectedPrevPostIds), disableRotation: () => global.FritreeRotationStore.disableRotation(), incrementUsage: (id, status) => global.FritreeRotationStore.incrementUsage(id, status), selectNextPost: (mode, availableIds, targetGroupId) => global.FritreeRotationStore.selectNextPost(mode, availableIds, targetGroupId), recalculateScores: () => global.FritreeRotationStore.recalculateScores(), savePrevPostsToLocal: () => global.FritreeRotationStore.save(), renderPreviousPostsGrid, updateRotationIndicatorUI, updateRotationBadgeInModal }; if (typeof document !== 'undefined') { if (!initRotationUI()) { document.addEventListener('DOMContentLoaded', initRotationUI); window.addEventListener('load', initRotationUI); } } })(typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : this);