=3) { r = parseFloat(parts[0]); g = parseFloat(parts[1]); b = parseFloat(parts[2]); if(parts.length > 3) a = Math.round(parseFloat(parts[3]) * 100); } } const hsv = rgbToHsv(r,g,b); return { h:hsv.h, s:hsv.s, v:hsv.v, a:a }; }
function initSavedColors() { const s = localStorage.getItem('mySavedColors'); if(s) { try{savedColors=JSON.parse(s)||[];}catch(e){savedColors=[];} } renderSavedColors(); }
function saveCurrentColor() { const rgb = hsvToRgb(pickerState.h, pickerState.s, pickerState.v); const hex = rgbToHex(rgb.r, rgb.g, rgb.b); savedColors.push(hex); localStorage.setItem('mySavedColors', JSON.stringify(savedColors)); renderSavedColors(); showToast("این رنگ در حافظه رنگها ذخیره شد", "fa-solid fa-save"); }
function renderSavedColors(){ const c = document.getElementById('savedColorsContainer'); if(!c) return; const svBtn = c.querySelector('.btn-save-text'); while(svBtn.nextSibling) svBtn.nextSibling.remove(); savedColors.forEach((hex, idx) => { const w = document.createElement('div'); w.className='saved-color-wrapper'; w.innerHTML = `
`; w.querySelector('.saved-circle').onclick = () => { let parsed = parseColorStringToState(hex); pickerState=parsed; syncAllUI(); syncGridSelectedFromCurrentColor(); }; w.querySelector('.mini-delete-btn').onclick = (e) => { e.stopPropagation(); currentDeleteIndex=idx; document.getElementById('delColorPreview').style.backgroundColor=hex; document.getElementById('deleteModal').classList.add('active'); }; c.appendChild(w); }); }
function showToast(message = "این رنگ در حافظه رنگها ذخیره شد", iconClass = "fa-solid fa-circle-check") { const t=document.getElementById('toastNotification'); if (!t) return; const span = t.querySelector('span'); const icon = t.querySelector('i'); if(span) span.innerText = message; if(icon) icon.className = iconClass; t.classList.add('show'); clearTimeout(toastTimeout); toastTimeout=setTimeout(()=>t.classList.remove('show'),2200); }
function confirmDelete(){ if(currentDeleteIndex>-1) { savedColors.splice(currentDeleteIndex,1); localStorage.setItem('mySavedColors',JSON.stringify(savedColors)); renderSavedColors(); } closeDeleteModal(); }
function closeDeleteModal(){ document.getElementById('deleteModal').classList.remove('active'); currentDeleteIndex=-1; }
function generateGridPalette() { const colors = ['#FFFFFF','#F2F2F7','#E5E5EA','#D1D1D6','#C7C7CC','#AEAEB2','#8E8E93','#636366','#48484A','#3A3A3C','#2C2C2E','#1C1C1E','#000000','#FF3B30','#FF453A','#FF9500','#FF9F0A','#FFD60A','#FFCC00','#34C759','#30D158','#00C7BE','#64D2FF','#32ADE6','#0A84FF','#007AFF','#5E5CE6','#5856D6','#AF52DE','#BF5AF2','#FF2D55']; for(let i=0;i<=20;i++){ let v=Math.round(i/20*255); colors.push(rgbToHex(v,v,v)); } for(let h=0;h<360;h+=12){ for(let s of [92,72]) for(let v of [100,85,70]) { colors.push(rgbToHex(hsvToRgb(h,s,v).r,hsvToRgb(h,s,v).g,hsvToRgb(h,s,v).b)); } } return [...new Set(colors)]; }
function renderGridWithData(colors){ if(!gridContP) return; gridContP.innerHTML=''; colors.forEach(hex => { const d = document.createElement('div'); d.className='grid-item'; d.style.backgroundColor=hex; d.setAttribute('data-hex', hex.toUpperCase()); d.onclick=()=>{ document.querySelectorAll('.grid-item').forEach(x=>x.classList.remove('selected')); d.classList.add('selected'); let parsed=parseColorStringToState(hex); pickerState=parsed; syncAllUI(); }; gridContP.appendChild(d); }); }
function syncGridSelectedFromCurrentColor() { if(!gridContP) return; const rgb = hsvToRgb(pickerState.h, pickerState.s, pickerState.v); const hex = rgbToHex(rgb.r,rgb.g,rgb.b).toUpperCase(); const items = gridContP.querySelectorAll('.grid-item'); items.forEach(it => { if(it.getAttribute('data-hex')===hex) it.classList.add('selected'); else it.classList.remove('selected'); }); }
// --- توابع جدید بخش تنظیمات فونت ---
function switchSubTab(tabName, btnEl) {
if (btnEl) {
document.querySelectorAll('.sub-nav-btn').forEach(b => b.classList.remove('active'));
btnEl.classList.add('active');
}
document.querySelectorAll('.sub-section-content').forEach(c => c.classList.remove('active'));
if(tabName === 'settings') {
document.getElementById('sub-settings').classList.add('active');
if(state && state.st) renderSettings(state.st.name);
} else if(tabName === 'opacity') {
document.getElementById('sub-opacity').classList.add('active');
const unreadCard = document.querySelector('#sub-opacity .settings-row-toggle:nth-child(1)');
if(unreadCard) unreadCard.classList.toggle('active', state.st.fadeUnread !== false);
const surroundingCard = document.getElementById('surroundingToggleCard');
if(surroundingCard) surroundingCard.classList.toggle('active', state.st.fadeSurrounding === true);
const typeCard = document.getElementById('typewriterToggleCard');
if(typeCard) typeCard.classList.toggle('active', state.st.typewriter === true);
} else {
document.getElementById('sub-fonts').classList.add('active');
}
}
function renderSettings(styleId) {
const container = document.getElementById('settingsContainerInline');
if (!container) return;
container.innerHTML = '';
const stylesWithCustomColor = ['alpha_gradient', 'music_player', 'instagram_box', 'karaoke_static', 'auto_director', 'plain_white', 'white_outline', 'simple_bar', 'dark_edges', 'falling_words', 'falling_karaoke', 'classic', 'progressive_write', 'blue_cloud', 'blue_outline', 'spring_popup'];
const stylesWithSecondaryColor = ['alpha_gradient', 'music_player', 'instagram_box', 'karaoke_static', 'dark_edges', 'falling_words', 'falling_karaoke'];
if (stylesWithCustomColor.includes(styleId)) {
const textIcon = '';
const savedColors = state.st.styleColors || {};
const currentColor = savedColors[styleId] || '#ffffff';
const row = document.createElement('div');
row.className = 'settings-row';
if (['classic', 'progressive_write'].includes(styleId)) row.style.display = 'none';
row.onclick = function(e) { openColorPicker('style_custom', e); };
row.innerHTML = `
${textIcon}
رنگ متن اختصاصی
`;
container.appendChild(row);
if (stylesWithSecondaryColor.includes(styleId)) {
const bgIcon = '';
const savedBgColors = state.st.styleBgColors || {};
const secondColor = savedBgColors[styleId] || '#ffffff';
const row2 = document.createElement('div');
row2.className = 'settings-row';
row2.onclick = function(e) { openColorPicker('temp_alpha', e); };
row2.innerHTML = `
`;
container.appendChild(row2);
}
const stylesWithActiveColor = ['alpha_gradient', 'instagram_box', 'karaoke_static', 'auto_director', 'simple_bar', 'dark_edges', 'falling_words', 'falling_karaoke', 'white_outline', 'plain_white', 'classic', 'progressive_write', 'blue_cloud', 'blue_outline', 'spring_popup'];
if (stylesWithActiveColor.includes(styleId)) {
const activeIcon = '';
const savedActiveColors = state.st.styleActiveColors || {};
const activeColor = savedActiveColors[styleId] || '#ffffff';
const row3 = document.createElement('div');
const activeToggles = state.st.styleActiveWordToggles || {};
const isToggleActive = activeToggles[styleId] !== false;
row3.className = 'settings-row-toggle' + (isToggleActive ? ' active' : '');
row3.innerHTML = `
`;
container.appendChild(row3);
if (styleId === 'instagram_box' || styleId === 'simple_bar') {
const boxIcon = '';
const savedBgColors = state.st.styleBgColors || {};
const mainBoxColor = savedBgColors[styleId + '_main_box'] || '#ffffff';
const rowBox = document.createElement('div');
rowBox.className = 'settings-row';
rowBox.onclick = function(e) { openColorPicker('style_main_box', e); };
rowBox.innerHTML = ``;
container.appendChild(rowBox);
}
}
if (styleId === 'music_player' || styleId === 'simple_bar') {
const progressIcon = '';
const savedBgColors = state.st.styleBgColors || {};
const progressColor = savedBgColors[styleId + '_progress'] || '#d32f2f';
const row4 = document.createElement('div');
row4.className = 'settings-row';
row4.onclick = function(e) { openColorPicker('style_progress', e); };
row4.innerHTML = `${progressIcon}
رنگ نوار پیشرفت `;
container.appendChild(row4);
}
} else {
container.innerHTML = 'تنظیمات خاصی برای این استایل وجود ندارد.
';
}
}
window.toggleUnreadOpacity = function(el) {
const currentStyle = state.st.name;
if (BLACKLIST_FADE_UNREAD.includes(currentStyle)) {
showToast("این انیمیشن برای استایل انتخاب شده در دسترس نیست", "fa-solid fa-triangle-exclamation");
return;
}
const card = el.parentElement;
card.classList.toggle('active');
state.st.fadeUnread = card.classList.contains('active');
if (state.st.fadeUnread) {
state.st.fadeSurrounding = false;
const surroundingCard = document.getElementById('surroundingToggleCard');
if (surroundingCard) surroundingCard.classList.remove('active');
}
upd();
};
window.toggleSurroundingOpacity = function(el) {
const currentStyle = state.st.name;
if (BLACKLIST_FADE_SURROUNDING.includes(currentStyle)) {
showToast("این انیمیشن برای استایل انتخاب شده در دسترس نیست", "fa-solid fa-triangle-exclamation");
return;
}
const card = el.parentElement;
card.classList.toggle('active');
state.st.fadeSurrounding = card.classList.contains('active');
if (state.st.fadeSurrounding) {
state.st.fadeUnread = false;
const unreadCard = document.querySelector('#sub-opacity .settings-row-toggle:nth-child(1)');
if (unreadCard) unreadCard.classList.remove('active');
}
upd();
};
window.toggleTypewriter = function(el) {
const currentStyle = state.st.name;
if (BLACKLIST_TYPEWRITER.includes(currentStyle)) {
showToast("این انیمیشن برای استایل انتخاب شده در دسترس نیست", "fa-solid fa-triangle-exclamation");
return;
}
const card = el.parentElement;
card.classList.toggle('active');
state.st.typewriter = card.classList.contains('active');
upd();
};
window.toggleActiveColor = function(el) {
const card = el.parentElement;
card.classList.toggle('active');
if (!state.st.styleActiveWordToggles) state.st.styleActiveWordToggles = {};
state.st.styleActiveWordToggles[state.st.name] = card.classList.contains('active');
upd();
};
// --- منطق اضافه کردن دستی کلمه جدید و تقسیم زمان ---
let targetAddWordInfo = null;
window.openAddWordModal = function(sIdx, wIdx) {
targetAddWordInfo = { sIdx, wIdx };
const modal = document.getElementById('addWordModal');
document.getElementById('newWordInput').value = '';
modal.style.display = 'flex';
setTimeout(() => modal.classList.add('show'), 10);
setTimeout(() => document.getElementById('newWordInput').focus(), 100);
};
window.closeAddWordModal = function() {
const modal = document.getElementById('addWordModal');
modal.classList.remove('show');
setTimeout(() => modal.style.display = 'none', 300);
targetAddWordInfo = null;
};
window.confirmAddWord = function() {
if (!targetAddWordInfo) return;
const { sIdx, wIdx } = targetAddWordInfo;
const val = document.getElementById('newWordInput').value.trim();
if (!val) {
closeAddWordModal();
return;
}
const seg = state.segs[sIdx];
// 1. اضافه کردن کلمه جدید دقیقاً بعد از کلمه انتخاب شده
const newWord = {
word: val,
start: 0,
end: 0,
isManual: true, // مشخص کننده زیرکلمه دستی
highlight: false,
color: null
};
seg.words.splice(wIdx + 1, 0, newWord);
// 2. محاسبات ریاضی برای تقسیم عادلانه زمان بین کلمات اصلی و دستی
// الف) پیدا کردن کلمه اصلی (هوش مصنوعی) قبل از این مجموعه کلمات
let origIdx = wIdx;
while (origIdx >= 0 && seg.words[origIdx].isManual) {
origIdx--;
}
if (origIdx < 0) origIdx = 0; // در حالت استثنایی که کلمه اول هم دستی باشد
// ب) پیدا کردن کلمه اصلی (هوش مصنوعی) بعدی
let nextOrigIdx = wIdx + 2; // wIdx + 1 کلمه جدید است که الان اضافه شد
while (nextOrigIdx < seg.words.length && seg.words[nextOrigIdx].isManual) {
nextOrigIdx++;
}
// ج) محاسبه کل زمان موجود برای این بلاک
let startTime = seg.words[origIdx].start;
let endTime = (nextOrigIdx < seg.words.length) ? seg.words[nextOrigIdx].start : seg.end;
// د) تقسیم مساوی زمان بین کلمه اصلی و تمام زیرکلمات جدید
let count = nextOrigIdx - origIdx;
let step = (endTime - startTime) / count;
for (let k = origIdx; k < nextOrigIdx; k++) {
seg.words[k].start = startTime + (k - origIdx) * step;
seg.words[k].end = seg.words[k].start + step;
}
// 3. بروزرسانی متن کامل سگمنت
seg.text = seg.words.map(w => w.word).join(' ');
closeAddWordModal();
// 4. رفرش کردن ظاهر و هایلایت کردن کلمه جدید
renderSegList();
highlightWord(sIdx, wIdx + 1, true);
upd();
};