const { ipcRenderer } = require('electron');
// --- DOM ELEMENTS ---
const chatArea = document.getElementById('chat-area');
const userInput = document.getElementById('user-input');
const sendBtn = document.getElementById('send-btn');
const welcomeScreen = document.getElementById('welcome-screen');
const historyList = document.getElementById('history-list');
const newChatBtn = document.getElementById('new-chat-btn');
const themeToggle = document.getElementById('theme-toggle');
const statusIndicator = document.getElementById('status-indicator');
const reloadBtn = document.getElementById('reload-btn');
const activePersonaSelect = document.getElementById('active-persona-select');
const currentPersonaAvatar = document.getElementById('current-persona-avatar');
// --- MODALS ---
const managePersonasBtn = document.getElementById('manage-personas-btn');
const managePersonasModal = document.getElementById('manage-personas-modal');
const closeManageBtn = document.getElementById('close-manage-btn');
const savePersonaBtn = document.getElementById('save-persona-btn');
const personaListDisplay = document.getElementById('persona-list-display');
const deleteModal = document.getElementById('delete-modal');
const confirmDeleteBtn = document.getElementById('confirm-delete');
const cancelDeleteBtn = document.getElementById('cancel-delete');
const personaDeleteModal = document.getElementById('persona-delete-modal');
const confirmPersonaDeleteBtn = document.getElementById('confirm-persona-delete');
const cancelPersonaDeleteBtn = document.getElementById('cancel-persona-delete');
// --- STATE ---
let chatHistory = [];
let currentChatId = null;
let isGenerating = false;
let isEngineReady = false;
let deleteTargetId = null;
let deletePersonaTargetId = null;
let abortController = null;
let personas = [];
let tempBase64Image = "";
let editingPersonaId = null;
const DEFAULT_PERSONA = {
id: 'default',
name: 'bujji',
relation: 'Friend',
gender: 'Female',
instruction: 'Supportive, platonic companion. Professional, kind, and respectful.',
length: 'short',
sticker: ''
};
// --- DOM VIEWS ---
const views = {
chat: document.getElementById('view-chat'),
habits: document.getElementById('view-habits'),
games: document.getElementById('view-games'),
fashion: document.getElementById('view-fashion'),
astro: document.getElementById('view-astro'),
productivity: document.getElementById('view-productivity'),
breathing: document.getElementById('view-breathing')
};
// --- NAVIGATION ---
window.switchView = (viewName) => {
// If Browser is clicked, redirect to the separate HTML file
if (viewName === 'browser') {
window.location.href = 'web.html';
return;
}
Object.values(views).forEach(el => { if(el) el.classList.add('hidden'); });
document.querySelectorAll('.nav-icon-btn').forEach(btn => btn.classList.remove('active'));
if(views[viewName]) views[viewName].classList.remove('hidden');
const activeBtn = document.querySelector(`.nav-icon-btn[onclick="switchView('${viewName}')"]`);
if(activeBtn) activeBtn.classList.add('active');
if (viewName === 'habits') renderHabits();
};
// --- THEME ---
themeToggle.addEventListener('click', () => {
document.body.classList.toggle('dark-mode');
localStorage.setItem('bujji_theme', document.body.classList.contains('dark-mode') ? 'dark' : 'light');
lucide.createIcons();
});
if (localStorage.getItem('bujji_theme') === 'dark') document.body.classList.add('dark-mode');
// --- INIT ---
function init() {
loadPersonas();
loadChats();
isGenerating = false;
updatePersonaDropdown();
if (chatHistory.length === 0) createNewSession();
else { loadChat(chatHistory[0].id); renderHistory(); }
checkEngineStatus();
lucide.createIcons();
}
// --- DATA HANDLING ---
function saveChats() { localStorage.setItem('bujji_chats', JSON.stringify(chatHistory)); }
function loadChats() { chatHistory = JSON.parse(localStorage.getItem('bujji_chats') || '[]'); }
function savePersonas() { localStorage.setItem('bujji_personas', JSON.stringify(personas)); }
function loadPersonas() {
const stored = localStorage.getItem('bujji_personas');
personas = stored ? JSON.parse(stored) : [DEFAULT_PERSONA];
if(!personas.find(p => p.id === 'default')) personas.unshift(DEFAULT_PERSONA);
}
userInput.addEventListener('input', function() {
this.style.height = 'auto';
this.style.height = (this.scrollHeight) + 'px';
});
if(reloadBtn) {
reloadBtn.addEventListener('click', () => ipcRenderer.send('reload-window'));
}
// --- PERSONA MANAGEMENT ---
function updatePersonaDropdown() {
const currentSelection = activePersonaSelect.value;
activePersonaSelect.innerHTML = '';
personas.forEach(p => {
const opt = document.createElement('option');
opt.value = p.id;
opt.innerText = p.name;
activePersonaSelect.appendChild(opt);
});
if(currentChatId) {
const chat = chatHistory.find(c => c.id === currentChatId);
if(chat && chat.personaId) {
activePersonaSelect.value = chat.personaId;
updateHeaderAvatar(chat.personaId);
}
} else {
if(currentSelection && personas.find(p => p.id === currentSelection)) activePersonaSelect.value = currentSelection;
updateHeaderAvatar(activePersonaSelect.value);
}
}
function updateHeaderAvatar(personaId) {
const p = personas.find(x => x.id === personaId) || DEFAULT_PERSONA;
if (p.sticker) {
currentPersonaAvatar.src = p.sticker;
currentPersonaAvatar.classList.remove('hidden');
} else {
currentPersonaAvatar.classList.add('hidden');
currentPersonaAvatar.src = "";
}
}
activePersonaSelect.addEventListener('change', () => createNewSession());
managePersonasBtn.addEventListener('click', () => { renderPersonaList(); managePersonasModal.classList.remove('hidden'); });
closeManageBtn.addEventListener('click', () => { managePersonasModal.classList.add('hidden'); resetPersonaForm(); });
document.getElementById('p-sticker-file').addEventListener('change', function(event) {
const file = event.target.files[0];
if (file) {
const reader = new FileReader();
reader.onload = function(e) {
tempBase64Image = e.target.result;
document.getElementById('p-preview').src = tempBase64Image;
document.getElementById('p-preview').style.display = 'block';
};
reader.readAsDataURL(file);
}
});
savePersonaBtn.addEventListener('click', () => {
const name = document.getElementById('p-name').value;
const rel = document.getElementById('p-relation').value;
const gender = document.getElementById('p-gender').value;
const inst = document.getElementById('p-instruction').value;
const len = document.getElementById('p-length').value;
if(name) {
const newP = {
id: editingPersonaId ? editingPersonaId : Date.now().toString(),
name, relation: rel, gender, instruction: inst, length: len, sticker: tempBase64Image
};
if (editingPersonaId) {
const index = personas.findIndex(p => p.id === editingPersonaId);
if(index !== -1) personas[index] = newP;
} else {
personas.push(newP);
}
savePersonas();
updatePersonaDropdown();
renderPersonaList();
resetPersonaForm();
}
});
function resetPersonaForm() {
document.getElementById('p-name').value = '';
document.getElementById('p-relation').value = '';
document.getElementById('p-instruction').value = '';
document.getElementById('p-sticker-file').value = '';
document.getElementById('p-preview').style.display = 'none';
tempBase64Image = "";
editingPersonaId = null;
savePersonaBtn.innerText = "Save Character";
savePersonaBtn.style.backgroundColor = "";
}
function renderPersonaList() {
personaListDisplay.innerHTML = '';
personas.forEach(p => {
if(p.id !== 'default') {
const div = document.createElement('div');
div.className = 'persona-item';
let imgHtml = '';
if(p.sticker) imgHtml = ``;
div.innerHTML = `
${isDone ? 'Done!' : 'Click to Complete'}
`; div.onclick = () => toggleHabit(index); list.appendChild(div); }); } window.addNewHabit = () => { const name = prompt("Enter habit name:"); if (name) { habits.push({ name, streak: 0, lastDone: null }); localStorage.setItem('bujji_habits', JSON.stringify(habits)); renderHabits(); } }; function toggleHabit(index) { const today = new Date().toISOString().split('T')[0]; const habit = habits[index]; if (habit.lastDone !== today) { habit.streak++; habit.lastDone = today; } else { habit.streak = Math.max(0, habit.streak - 1); habit.lastDone = null; } localStorage.setItem('bujji_habits', JSON.stringify(habits)); renderHabits(); } // Breathing window.startBreathing = (type) => { if (isBreathing) stopBreathing(); isBreathing = true; const circle = document.getElementById('breathing-circle'); const text = document.getElementById('breath-text'); let dIn = 4000, dHold = 4000, dOut = 4000, dHold2 = 4000; if (type === '478') { dIn=4000; dHold=7000; dOut=8000; dHold2=0; } const cycle = async () => { if (!isBreathing) return; text.innerText = "Inhale..."; circle.style.transform = "scale(1.5)"; circle.style.transition = `transform ${dIn}ms ease-in-out`; await new Promise(r => setTimeout(r, dIn)); if (!isBreathing) return; text.innerText = "Hold..."; await new Promise(r => setTimeout(r, dHold)); if (!isBreathing) return; text.innerText = "Exhale..."; circle.style.transform = "scale(1.0)"; circle.style.transition = `transform ${dOut}ms ease-in-out`; await new Promise(r => setTimeout(r, dOut)); if (dHold2 > 0) { if (!isBreathing) return; text.innerText = "Hold..."; await new Promise(r => setTimeout(r, dHold2)); } cycle(); }; cycle(); }; window.stopBreathing = () => { isBreathing = false; document.getElementById('breathing-circle').style.transform = "scale(1.0)"; document.getElementById('breath-text').innerText = "Ready"; }; // Games window.startIQTest = () => { document.querySelector('.games-grid-layout').classList.add('hidden'); document.getElementById('game-playground').classList.remove('hidden'); document.getElementById('game-content').innerHTML = `