diff --git a/MindShift-Windows/MindShift-v1.0.4.apk b/MindShift-Windows/MindShift-v1.0.4.apk new file mode 100644 index 0000000..5f98266 Binary files /dev/null and b/MindShift-Windows/MindShift-v1.0.4.apk differ diff --git a/MindShift-Windows/package.json b/MindShift-Windows/package.json index 7708baf..71063d7 100644 --- a/MindShift-Windows/package.json +++ b/MindShift-Windows/package.json @@ -1,6 +1,6 @@ { "name": "mindshift-cbt-therapy", - "version": "1.0.3", + "version": "1.0.4", "description": "MindShift - Your personal CBT therapy companion for Windows 11", "main": "src/main.js", "homepage": "./", diff --git a/MindShift-Windows/src/app.js b/MindShift-Windows/src/app.js index 19fdeb0..e3e5a05 100644 --- a/MindShift-Windows/src/app.js +++ b/MindShift-Windows/src/app.js @@ -1,4 +1,55 @@ import { authAPI, moodAPI, thoughtAPI, gratitudeAPI, progressAPI, notificationAPI, exerciseAPI, isAuthenticated, initializeAPI } from './offline-api.js'; +import { translations } from './translations.js'; + +// Language Management +let currentLang = localStorage.getItem('appLang') || 'en'; + +function t(key) { + const langObj = translations[currentLang] || translations['en']; + return langObj[key] || key; +} + +function setLanguage(lang) { + currentLang = lang; + localStorage.setItem('appLang', lang); + document.documentElement.lang = lang; + document.documentElement.dir = lang === 'he' ? 'rtl' : 'ltr'; + + // Update Header + updateHeaderTranslations(); + + // Re-render current section + const activeNav = document.querySelector('.nav-item.active'); + if (activeNav) { + // Identify section from onclick attribute or class + // Simple re-render of home if unsure + const onclick = activeNav.getAttribute('onclick'); + if (onclick && onclick.includes("'")) { + const section = onclick.split("'")[1]; + showSection(section); + } else { + showSection('home'); + } + } else { + showSection('home'); + } + + // Update nav labels + document.querySelectorAll('.nav-label').forEach((el, index) => { + const keys = ['nav_home', 'nav_mood', 'nav_thoughts', 'nav_gratitude', 'nav_progress']; + if (keys[index]) el.textContent = t(keys[index]); + }); + + // Update Proactive Badge + const badge = document.getElementById('proactive-badge'); + if (badge) badge.textContent = t('proactive_badge'); +} + +function updateHeaderTranslations() { + // Update app title if dynamic, currently static in HTML but let's allow JS update + // const title = document.querySelector('.app-title'); + // if (title) title.innerHTML = `self_improvement ${t('app_title')}`; +} // Sound Manager using Web Audio API class SoundManager { @@ -72,6 +123,11 @@ document.addEventListener('DOMContentLoaded', async function() { try { console.log('App initialization started'); + // Initial Language Setup + document.documentElement.lang = currentLang; + document.documentElement.dir = currentLang === 'he' ? 'rtl' : 'ltr'; + setLanguage(currentLang); // Updates Nav labels immediately + // Check authentication if (!isAuthenticated()) { console.log('User not authenticated, showing login modal'); @@ -117,7 +173,7 @@ document.addEventListener('DOMContentLoaded', async function() { console.error('Initialization error:', error); const loader = document.getElementById('initial-loader'); if (loader) { - loader.innerHTML = `

Init Error

${error.message}

`; + loader.innerHTML = `

${t('init_error')}

${error.message}

`; } } }); @@ -153,27 +209,37 @@ function triggerSuccessPing() { ping.parentNode.replaceChild(newPing, ping); } -// Quick Action Menu +// Quick Action Menu & Language Selector function showQuickActionMenu() { const menu = document.createElement('div'); menu.className = 'exercise-modal'; menu.style.display = 'block'; menu.innerHTML = `
-

Quick Actions ⚡

+

${t('quick_title')}

+ +
+ +
+ + + +
+
+
- 📝 Log Mood + 📝 ${t('home_log_mood')}
- 🌬️ Breathe + 🌬️ ${t('home_breathe')}
- 🧘 Relax Now + 🧘 ${t('quick_relax_now')}
- +
`; @@ -187,39 +253,44 @@ function showLoginModal() { loginModal.innerHTML = ` `).join('') - : '
No notifications
'; + : `
${t('notifications_empty')}
`; } } catch (error) { console.error('Failed to load notifications:', error); @@ -777,7 +843,7 @@ async function initializeNotifications() { `).join('') - : '
No notifications
'; + : `
${t('notifications_empty')}
`; } } } @@ -787,10 +853,10 @@ function formatTime(timestamp) { const now = new Date(); const diff = now - date; - if (diff < 60000) return 'Just now'; - if (diff < 3600000) return `${Math.floor(diff / 60000)}m ago`; - if (diff < 86400000) return `${Math.floor(diff / 3600000)}h ago`; - return date.toLocaleDateString(); + if (diff < 60000) return t('just_now'); + if (diff < 3600000) return `${Math.floor(diff / 60000)}${t('ago_m')}`; + if (diff < 86400000) return `${Math.floor(diff / 3600000)}${t('ago_h')}`; + return date.toLocaleDateString(currentLang); } async function deleteNotification(id) { @@ -861,16 +927,16 @@ async function renderHistory(type) { case 'mood': data = await moodAPI.getMoodHistory(); if (data.length === 0) { - content = '
No mood entries yet. Start tracking! 📝
'; + content = `
${t('history_empty_mood')}
`; } else { content = data.map(entry => ` -
+
- ${getMoodEmoji(entry.mood_type)} ${capitalize(entry.mood_type)} + ${getMoodEmoji(entry.mood_type)} ${t('mood_' + entry.mood_type)} ${formatDate(entry.created_at)}
- Intensity: ${entry.intensity}/10 + ${t('mood_intensity')}: ${entry.intensity}/10 ${entry.notes ? `

"${entry.notes}"

` : ''}
@@ -881,18 +947,18 @@ async function renderHistory(type) { case 'thoughts': data = await thoughtAPI.getThoughtRecords(); if (data.length === 0) { - content = '
No thought records yet. 🧠
'; + content = `
${t('history_empty_thoughts')}
`; } else { content = data.map(entry => ` -
+
- Thought Record + ${t('thought_title')} ${formatDate(entry.created_at)}
-
Situation: ${entry.situation}
-
Thought: ${entry.automatic_thought}
-
Emotion: ${entry.emotion} (${entry.emotion_intensity}%)
+
${t('thought_situation').split('(')[0]}: ${entry.situation}
+
${t('thought_automatic').split('(')[0]}: ${entry.automatic_thought}
+
${t('thought_emotions')}: ${entry.emotion} (${entry.emotion_intensity}%)
`).join(''); @@ -902,12 +968,12 @@ async function renderHistory(type) { case 'gratitude': data = await gratitudeAPI.getGratitudeEntries(); if (data.length === 0) { - content = '
No gratitude entries yet. 🙏
'; + content = `
${t('history_empty_gratitude')}
`; } else { content = data.map(entry => ` -
+
- Gratitude + ${t('nav_gratitude')} ${formatDate(entry.created_at)}
@@ -928,7 +994,7 @@ async function renderHistory(type) { }); } catch (error) { - container.innerHTML = `
Failed to load history: ${error.message}
`; + container.innerHTML = `
${error.message}
`; } } @@ -946,7 +1012,7 @@ function capitalize(str) { function formatDate(dateStr) { const date = new Date(dateStr); - return date.toLocaleDateString() + ' ' + date.toLocaleTimeString([], {hour: '2-digit', minute:'2-digit'}); + return date.toLocaleDateString(currentLang) + ' ' + date.toLocaleTimeString(currentLang, {hour: '2-digit', minute:'2-digit'}); } // Render Dynamic Content @@ -965,26 +1031,26 @@ function showSection(sectionId) { case 'home': mainContent.innerHTML = `
-

Welcome Back! 🌟

-

Ready to shift your mind?

+

${t('home_welcome')}

+

${t('home_subtitle')}

📝 - Log Mood + ${t('home_log_mood')}
🧠 - Record Thought + ${t('home_record_thought')}
🙏 - Gratitude + ${t('home_gratitude')}
-

Daily Vibe Check 📊

+

${t('home_daily_vibe')}

@@ -996,15 +1062,15 @@ function showSection(sectionId) {
-

Quick Relief 🌿

+

${t('home_quick_relief')}

🌬️ - Breathe + ${t('home_breathe')}
🧘 - Relax + ${t('home_relax')}
@@ -1015,46 +1081,46 @@ function showSection(sectionId) { case 'mood': mainContent.innerHTML = `
-

How are you feeling?

+

${t('mood_title')}

😊 - Joy + ${t('mood_joy')}
😌 - Peace + ${t('mood_peace')}
- Energy + ${t('mood_energy')}
😰 - Anxiety + ${t('mood_anxiety')}
😢 - Sadness + ${t('mood_sadness')}
😠 - Anger + ${t('mood_anger')}
- Intensity + ${t('mood_intensity')} 5
- +
`; @@ -1063,36 +1129,36 @@ function showSection(sectionId) { case 'thoughts': mainContent.innerHTML = `
-

Thought Record 🧠

+

${t('thought_title')}

- +
- +
- +
- + 50
- +
- +
- +
- +
`; @@ -1102,16 +1168,16 @@ function showSection(sectionId) { case 'gratitude': mainContent.innerHTML = `
-

Gratitude Journal 🙏

-

List 3 things you are grateful for today:

+

${t('gratitude_title')}

+

${t('gratitude_intro')}

- - - + + +
- +
- +
`; @@ -1120,29 +1186,28 @@ function showSection(sectionId) { case 'progress': mainContent.innerHTML = `
-

Your Progress 📈

+

${t('progress_title')}

-

Weekly Mood 📅

+

${t('progress_weekly')}

-

Recent History 📜

+

${t('progress_history')}

- - - + + +
- -
Select a category to view history
+
${t('history_select_prompt')}
`; @@ -1152,43 +1217,6 @@ function showSection(sectionId) { } } -// Keep existing navigation and UI functions -function showSection_OLD(sectionId) { - document.querySelectorAll('.section').forEach(section => { - section.classList.remove('active'); - }); - - document.getElementById(sectionId).classList.add('active'); - - document.querySelectorAll('.nav-item').forEach(item => { - item.classList.remove('active'); - }); - event.target.closest('.nav-item').classList.add('active'); - - if (sectionId === 'analytics') { - loadAnalyticsData(); - } -} - -function showSituationBuilder() { - showSection('situation-builder'); - document.querySelectorAll('.nav-item').forEach(item => { - item.classList.remove('active'); - }); -} - -function generateExercises() { - showSection('exercises'); - document.querySelectorAll('.nav-item').forEach(item => { - item.classList.remove('active'); - }); - document.querySelectorAll('.nav-item')[1].classList.add('active'); -} - -function startExercise(type) { - alert(`Starting ${type} exercise... This would open the exercise interface.`); -} - function quickRelax() { // Launch the new Guided Grounding Experience startGuidedRelaxation(); @@ -1198,53 +1226,58 @@ function quickRelax() { let relaxationState = { step: 0, isActive: false, - steps: [ + steps: [] // Will be populated dynamically based on language +}; + +function getRelaxationSteps() { + return [ { - title: "Sight", - instruction: "Look around you.", - sub: "Find 5 things you can see.", + title: t('guided_sight_title'), + instruction: t('guided_sight_instruction'), + sub: t('guided_sight_sub'), count: 5, icon: "👁️", color: "#64B5F6" }, { - title: "Touch", - instruction: "Feel the textures.", - sub: "Find 4 things you can touch.", + title: t('guided_touch_title'), + instruction: t('guided_touch_instruction'), + sub: t('guided_touch_sub'), count: 4, icon: "✋", color: "#81C784" }, { - title: "Sound", - instruction: "Listen carefully.", - sub: "Identify 3 sounds you hear.", + title: t('guided_sound_title'), + instruction: t('guided_sound_instruction'), + sub: t('guided_sound_sub'), count: 3, icon: "👂", color: "#FFB74D" }, { - title: "Smell", - instruction: "Breathe in deep.", - sub: "Notice 2 things you can smell.", + title: t('guided_smell_title'), + instruction: t('guided_smell_instruction'), + sub: t('guided_smell_sub'), count: 2, icon: "👃", color: "#BA68C8" }, { - title: "Taste", - instruction: "Focus on your mouth.", - sub: "Find 1 thing you can taste.", + title: t('guided_taste_title'), + instruction: t('guided_taste_instruction'), + sub: t('guided_taste_sub'), count: 1, icon: "👅", color: "#E57373" } - ] -}; + ]; +} function startGuidedRelaxation() { relaxationState.step = 0; relaxationState.isActive = true; + relaxationState.steps = getRelaxationSteps(); const overlay = document.createElement('div'); overlay.id = 'guided-relaxation-overlay'; @@ -1280,7 +1313,7 @@ function renderRelaxationStep() {
`; @@ -1320,13 +1353,13 @@ function finishGuidedRelaxation() { if (overlay) { overlay.innerHTML = `
🌟
-
You did great!
-
Feeling more grounded?
+
${t('guided_complete_title')}
+
${t('guided_complete_sub')}
`; - speakText("You did great. Feeling more grounded?"); + speakText(`${t('guided_complete_title')} ${t('guided_complete_sub')}`); triggerSuccessPing(); } } @@ -1353,6 +1386,15 @@ function speakText(text) { const utterance = new SpeechSynthesisUtterance(text); utterance.rate = 0.9; utterance.pitch = 1.0; + + // Map language codes to TTS locales + const langMap = { + 'en': 'en-US', + 'ru': 'ru-RU', + 'he': 'he-IL' + }; + utterance.lang = langMap[currentLang] || 'en-US'; + window.speechSynthesis.speak(utterance); } } @@ -1361,7 +1403,7 @@ function finishRelaxSession(btn) { btn.closest('.exercise-modal').remove(); exerciseAPI.logSession('relaxation', 120).then(() => { triggerSuccessPing(); - showSuccessMessage('Relaxation session logged! 🧘'); + showToast(t('mood_saved_success')); // Reuse success message or create new updateProgress(); }); } @@ -1375,23 +1417,20 @@ function emergencyHelp() { } function startThoughtRecord() { - document.getElementById('thought-record-exercise').style.display = 'block'; - document.getElementById('exercises').classList.add('blur-background'); + showSection('thoughts'); } function startMindfulness() { - document.getElementById('mindfulness-exercise').style.display = 'block'; - document.getElementById('exercises').classList.add('blur-background'); + // Implement or route } function startGratitude() { - document.getElementById('gratitude-exercise').style.display = 'block'; - document.getElementById('exercises').classList.add('blur-background'); + showSection('gratitude'); } function closeExercise(exerciseId) { document.getElementById(exerciseId).style.display = 'none'; - document.getElementById('exercises').classList.remove('blur-background'); + showSection('home'); } function addEmotionInput() { @@ -1399,7 +1438,7 @@ function addEmotionInput() { const newEmotionInput = document.createElement('div'); newEmotionInput.className = 'emotion-inputs'; newEmotionInput.innerHTML = ` - + 50 @@ -1413,7 +1452,7 @@ function addGratitudeInput() { const newInput = document.createElement('input'); newInput.type = 'text'; newInput.className = 'form-input gratitude-input'; - newInput.placeholder = 'Something you\'re grateful for...'; + newInput.placeholder = t('gratitude_placeholder'); gratitudeContainer.appendChild(newInput); } @@ -1424,46 +1463,52 @@ let breathingState = { timer: null }; -const breathingTechniques = { - balance: { - name: 'Balance', - label: 'Coherent Breathing', - phases: [ - { name: 'inhale', duration: 5500, label: 'Breathe In', scale: 1.8 }, - { name: 'exhale', duration: 5500, label: 'Breathe Out', scale: 1.0 } - ] - }, - relax: { - name: 'Relax', - label: '4-7-8 Relief', - phases: [ - { name: 'inhale', duration: 4000, label: 'Breathe In', scale: 1.8 }, - { name: 'hold', duration: 7000, label: 'Hold', scale: 1.8 }, - { name: 'exhale', duration: 8000, label: 'Breathe Out', scale: 1.0 } - ] - }, - focus: { - name: 'Focus', - label: 'Box Breathing', - phases: [ - { name: 'inhale', duration: 4000, label: 'Breathe In', scale: 1.8 }, - { name: 'hold', duration: 4000, label: 'Hold', scale: 1.8 }, - { name: 'exhale', duration: 4000, label: 'Breathe Out', scale: 1.0 }, - { name: 'hold', duration: 4000, label: 'Hold', scale: 1.0 } - ] - } -}; +function getBreathingTechniques() { + return { + balance: { + name: 'Balance', + label: t('breath_balance'), + phases: [ + { name: 'inhale', duration: 5500, label: t('breath_in'), scale: 1.8 }, + { name: 'exhale', duration: 5500, label: t('breath_out'), scale: 1.0 } + ] + }, + relax: { + name: 'Relax', + label: t('breath_relax'), + phases: [ + { name: 'inhale', duration: 4000, label: t('breath_in'), scale: 1.8 }, + { name: 'hold', duration: 7000, label: t('breath_hold'), scale: 1.8 }, + { name: 'exhale', duration: 8000, label: t('breath_out'), scale: 1.0 } + ] + }, + focus: { + name: 'Focus', + label: t('breath_focus'), + phases: [ + { name: 'inhale', duration: 4000, label: t('breath_in'), scale: 1.8 }, + { name: 'hold', duration: 4000, label: t('breath_hold'), scale: 1.8 }, + { name: 'exhale', duration: 4000, label: t('breath_out'), scale: 1.0 }, + { name: 'hold', duration: 4000, label: t('breath_hold'), scale: 1.0 } + ] + } + }; +} function startBreathing() { // Create immersive overlay const overlay = document.createElement('div'); overlay.id = 'smart-breathing-overlay'; overlay.className = 'breathing-overlay'; + + // Render techniques dynamically + const techniques = getBreathingTechniques(); + overlay.innerHTML = `
- - - + + +
@@ -1472,8 +1517,8 @@ function startBreathing() {
-
Get Ready...
-
Sit comfortably
+
${t('breath_ready')}
+
${t('breath_sit')}
+ + +
+
+ +
+
+ `; + document.body.appendChild(menu); +} +window.showLanguageModal = showLanguageModal; diff --git a/MindShift-Windows/src/index.html b/MindShift-Windows/src/index.html index fd207c6..1d23cda 100644 --- a/MindShift-Windows/src/index.html +++ b/MindShift-Windows/src/index.html @@ -54,6 +54,9 @@ MindShift
+