diff --git a/MindShift-Windows/MindShift-v1.0.3.apk b/MindShift-Windows/MindShift-v1.0.3.apk new file mode 100644 index 0000000..5f98266 Binary files /dev/null and b/MindShift-Windows/MindShift-v1.0.3.apk differ diff --git a/MindShift-Windows/package.json b/MindShift-Windows/package.json index ed20862..7708baf 100644 --- a/MindShift-Windows/package.json +++ b/MindShift-Windows/package.json @@ -1,6 +1,6 @@ { "name": "mindshift-cbt-therapy", - "version": "1.0.2", + "version": "1.0.3", "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 56399d5..19fdeb0 100644 --- a/MindShift-Windows/src/app.js +++ b/MindShift-Windows/src/app.js @@ -1190,30 +1190,171 @@ function startExercise(type) { } function quickRelax() { - const techniques = [ - { icon: '🌬️', title: 'Box Breathing', desc: 'Inhale 4s, Hold 4s, Exhale 4s, Hold 4s' }, - { icon: '👁️', title: '5-4-3-2-1 Grounding', desc: 'Name 5 things you see, 4 feel, 3 hear...' }, - { icon: '💆', title: 'Muscle Relaxation', desc: 'Tense and release each muscle group' }, - { icon: '🌊', title: 'Visualisation', desc: 'Imagine a peaceful place in detail' } - ]; + // Launch the new Guided Grounding Experience + startGuidedRelaxation(); +} + +// --- Guided Relaxation (5-4-3-2-1 Grounding) --- +let relaxationState = { + step: 0, + isActive: false, + steps: [ + { + title: "Sight", + instruction: "Look around you.", + sub: "Find 5 things you can see.", + count: 5, + icon: "👁️", + color: "#64B5F6" + }, + { + title: "Touch", + instruction: "Feel the textures.", + sub: "Find 4 things you can touch.", + count: 4, + icon: "✋", + color: "#81C784" + }, + { + title: "Sound", + instruction: "Listen carefully.", + sub: "Identify 3 sounds you hear.", + count: 3, + icon: "👂", + color: "#FFB74D" + }, + { + title: "Smell", + instruction: "Breathe in deep.", + sub: "Notice 2 things you can smell.", + count: 2, + icon: "👃", + color: "#BA68C8" + }, + { + title: "Taste", + instruction: "Focus on your mouth.", + sub: "Find 1 thing you can taste.", + count: 1, + icon: "👅", + color: "#E57373" + } + ] +}; + +function startGuidedRelaxation() { + relaxationState.step = 0; + relaxationState.isActive = true; - const randomTechnique = techniques[Math.floor(Math.random() * techniques.length)]; + const overlay = document.createElement('div'); + overlay.id = 'guided-relaxation-overlay'; + overlay.className = 'guided-overlay'; + document.body.appendChild(overlay); - const modal = document.createElement('div'); - modal.className = 'exercise-modal'; - modal.style.display = 'block'; - modal.innerHTML = ` -
-
${randomTechnique.icon}
-

${randomTechnique.title}

-

${randomTechnique.desc}

-
- - -
+ renderRelaxationStep(); +} + +function renderRelaxationStep() { + const overlay = document.getElementById('guided-relaxation-overlay'); + if (!overlay || !relaxationState.isActive) return; + + const currentStep = relaxationState.steps[relaxationState.step]; + const progressDots = Array(currentStep.count).fill('
').join(''); + + overlay.innerHTML = ` +
+
+ +
+ ${currentStep.icon} +
+ +
${currentStep.instruction}
+
${currentStep.sub}
+ +
+ ${progressDots} +
+ + `; - document.body.appendChild(modal); + + // Speak instruction + speakText(`${currentStep.instruction} ${currentStep.sub}`); +} + +let currentDotIndex = 0; + +function nextRelaxationSubStep() { + const dots = document.querySelectorAll('.progress-dot'); + if (currentDotIndex < dots.length) { + dots[currentDotIndex].classList.add('active'); + // Haptic feedback + if (navigator.vibrate) navigator.vibrate(50); + // Sound feedback + soundManager.playTone(400 + (currentDotIndex * 50), 'sine', 0.1, 0.1); + + currentDotIndex++; + + if (currentDotIndex === dots.length) { + setTimeout(() => { + currentDotIndex = 0; + relaxationState.step++; + if (relaxationState.step < relaxationState.steps.length) { + renderRelaxationStep(); + } else { + finishGuidedRelaxation(); + } + }, 1000); + } + } +} + +function finishGuidedRelaxation() { + const overlay = document.getElementById('guided-relaxation-overlay'); + if (overlay) { + overlay.innerHTML = ` +
🌟
+
You did great!
+
Feeling more grounded?
+ + `; + speakText("You did great. Feeling more grounded?"); + triggerSuccessPing(); + } +} + +function closeGuidedRelaxation() { + relaxationState.isActive = false; + currentDotIndex = 0; + const overlay = document.getElementById('guided-relaxation-overlay'); + if (overlay) overlay.remove(); + + if (window.speechSynthesis) { + window.speechSynthesis.cancel(); + } + + // Log session + if (relaxationState.step >= relaxationState.steps.length) { + exerciseAPI.logSession('grounding', 180).then(() => updateProgress()); + } +} + +function speakText(text) { + if ('speechSynthesis' in window) { + window.speechSynthesis.cancel(); // Stop previous + const utterance = new SpeechSynthesisUtterance(text); + utterance.rate = 0.9; + utterance.pitch = 1.0; + window.speechSynthesis.speak(utterance); + } } function finishRelaxSession(btn) { diff --git a/MindShift-Windows/src/styles.css b/MindShift-Windows/src/styles.css index a591322..f8e68f4 100644 --- a/MindShift-Windows/src/styles.css +++ b/MindShift-Windows/src/styles.css @@ -255,13 +255,115 @@ body { display: flex; justify-content: space-around; padding: 12px 0; - /* Android Safe Area Fix - Increased Padding */ - padding-bottom: calc(24px + env(safe-area-inset-bottom)); + /* Android Safe Area Fix - Significantly Increased Padding */ + padding-bottom: calc(40px + env(safe-area-inset-bottom)); z-index: 100; border-top-left-radius: 24px; border-top-right-radius: 24px; } +/* Guided Relaxation Styles */ +.guided-overlay { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: radial-gradient(circle at center, #2E7D32, #004D40); + z-index: 6000; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + color: white; + animation: fadeIn 0.5s ease; + padding: 20px; + text-align: center; +} + +.guided-step-icon { + font-size: 80px; + margin-bottom: 30px; + animation: floatIcon 3s ease-in-out infinite; + filter: drop-shadow(0 0 20px rgba(255,255,255,0.3)); +} + +@keyframes floatIcon { + 0%, 100% { transform: translateY(0); } + 50% { transform: translateY(-15px); } +} + +.guided-instruction { + font-size: 28px; + font-weight: 300; + margin-bottom: 16px; + line-height: 1.4; +} + +.guided-sub { + font-size: 18px; + opacity: 0.8; + margin-bottom: 40px; + max-width: 80%; +} + +.guided-progress-dots { + display: flex; + gap: 8px; + margin-bottom: 40px; +} + +.progress-dot { + width: 12px; + height: 12px; + border-radius: 50%; + background: rgba(255, 255, 255, 0.3); + transition: all 0.3s; +} + +.progress-dot.active { + background: white; + transform: scale(1.2); +} + +.guided-action-btn { + background: white; + color: #004D40; + border: none; + padding: 16px 40px; + border-radius: 50px; + font-size: 18px; + font-weight: bold; + cursor: pointer; + box-shadow: 0 8px 20px rgba(0,0,0,0.2); + transition: transform 0.2s; +} + +.guided-action-btn:active { + transform: scale(0.95); +} + +.guided-controls { + position: absolute; + top: 20px; + right: 20px; + display: flex; + gap: 16px; +} + +.icon-btn { + background: rgba(255, 255, 255, 0.2); + border: none; + color: white; + width: 44px; + height: 44px; + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + cursor: pointer; +} + .nav-item { display: flex; flex-direction: column;