nothing-bothers-me / index.html
mobenta's picture
Update index.html
42009c2 verified
Copy
<!-- Chatbot Components -->
<style>
/* Chatbot specific styles */
#ai-chat-bubble {
transition: all 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275);
box-shadow: 0 4px 15px var(--shadow);
z-index: 100;
}
#ai-chat-bubble:hover {
transform: scale(1.1);
}
#ai-chat-interface {
box-shadow: 0 10px 25px var(--shadow);
transition: transform 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275);
background-color: var(--bg-card);
color: var(--text);
z-index: 100;
}
#ai-chat-messages::-webkit-scrollbar {
width: 6px;
}
#ai-chat-messages::-webkit-scrollbar-track {
background: var(--bg-alt);
border-radius: 3px;
}
#ai-chat-messages::-webkit-scrollbar-thumb {
background: var(--primary-light);
border-radius: 3px;
}
#ai-chat-messages::-webkit-scrollbar-thumb:hover {
background: var(--primary);
}
#ai-chat-input:focus {
border-color: var(--primary);
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.2);
}
.chat-message-user {
background-color: var(--primary);
color: white;
border-radius: 1rem 0 1rem 1rem;
padding: 0.75rem 1rem;
max-width: 80%;
margin-left: auto;
margin-bottom: 1rem;
box-shadow: 0 2px 5px var(--shadow);
animation: fadeInRight 0.3s ease forwards;
}
.chat-message-bot {
background-color: var(--bg-alt);
color: var(--text);
border-radius: 0 1rem 1rem 1rem;
padding: 0.75rem 1rem;
max-width: 80%;
margin-right: auto;
margin-bottom: 1rem;
box-shadow: 0 2px 5px var(--shadow);
animation: fadeInLeft 0.3s ease forwards;
}
@keyframes fadeInRight {
from {
opacity: 0;
transform: translateX(10px);
}
to {
opacity: 1;
transform: translateX(0);
}
}
@keyframes fadeInLeft {
from {
opacity: 0;
transform: translateX(-10px);
}
to {
opacity: 1;
transform: translateX(0);
}
}
@keyframes typing {
0% { opacity: 0.3; }
50% { opacity: 1; }
100% { opacity: 0.3; }
}
.typing-indicator {
display: flex;
align-items: center;
padding: 0.5rem 1rem;
background-color: var(--bg-alt);
border-radius: 1rem;
margin-bottom: 1rem;
width: fit-content;
}
.typing-indicator span {
height: 8px;
width: 8px;
background-color: var(--text-light);
border-radius: 50%;
display: inline-block;
margin: 0 2px;
animation: typing 1.4s infinite both;
}
.typing-indicator span:nth-child(2) {
animation-delay: 0.2s;
}
.typing-indicator span:nth-child(3) {
animation-delay: 0.4s;
}
</style>
<!-- Chat Bubble -->
<div id="ai-chat-bubble" class="fixed bottom-5 right-5 w-14 h-14 rounded-full bg-primary text-white flex items-center justify-center cursor-pointer shadow-lg z-50 transition-all duration-300 hover:scale-110">
<i class="fas fa-comment-alt"></i>
</div>
<!-- Chat Interface -->
<div id="ai-chat-interface" class="fixed bottom-24 right-5 w-80 h-96 bg-white dark:bg-secondary rounded-lg shadow-xl z-50 flex flex-col overflow-hidden transform scale-0 origin-bottom-right transition-transform duration-300">
<div class="bg-primary text-white px-4 py-3 flex justify-between items-center">
<div class="flex items-center">
<i class="fas fa-brain mr-2"></i>
<h3 class="font-medium">Mindful AI Assistant</h3>
</div>
<div class="flex items-center">
<button id="clear-chat-history" class="text-white focus:outline-none text-xs opacity-70 hover:opacity-100 transition-opacity mr-2" title="Clear chat history">
<i class="fas fa-trash-alt"></i>
</button>
<button id="ai-chat-close" class="text-white focus:outline-none">
<i class="fas fa-times"></i>
</button>
</div>
</div>
<div id="ai-chat-messages" class="flex-1 p-4 overflow-y-auto bg-bg-card dark:bg-secondary-light"></div>
<div class="p-4 border-t border-gray-200 dark:border-gray-700 bg-bg-card dark:bg-secondary-light">
<form id="ai-chat-form" class="flex items-center">
<input id="ai-chat-input" type="text" placeholder="Ask about mindfulness..." class="flex-1 px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-l-lg focus:outline-none focus:border-primary bg-white dark:bg-secondary text-text dark:text-text-light" />
<button type="submit" class="bg-primary text-white px-4 py-2 rounded-r-lg hover:bg-primary-dark focus:outline-none">
<i class="fas fa-paper-plane"></i>
</button>
</form>
</div>
</div>
<!-- Loading Indicator -->
<div id="ai-chat-loading" class="hidden fixed bottom-24 right-5 w-80 h-96 bg-black bg-opacity-50 rounded-lg z-50 flex items-center justify-center">
<div class="w-10 h-10 border-4 border-gray-300 border-t-primary rounded-full animate-spin"></div>
</div>
<script>
// Initialize GEMINI_KEY if not already defined
if (typeof GEMINI_KEY === 'undefined') {
window.GEMINI_KEY = ''; // Replace with your API key or set it in Hugging Face Spaces environment
}
// Gemini Chatbot Integration
(function() {
// DOM Elements
const chatBubble = document.getElementById('ai-chat-bubble');
const chatInterface = document.getElementById('ai-chat-interface');
const chatClose = document.getElementById('ai-chat-close');
const chatMessages = document.getElementById('ai-chat-messages');
const chatForm = document.getElementById('ai-chat-form');
const chatInput = document.getElementById('ai-chat-input');
const chatLoading = document.getElementById('ai-chat-loading');
const clearChatHistoryButton = document.getElementById('clear-chat-history');
// Chat history
let chatHistory = [];
// Load chat history from localStorage if available
function loadChatHistory() {
const savedHistory = localStorage.getItem('mindful-chat-history');
if (savedHistory) {
try {
chatHistory = JSON.parse(savedHistory);
// Display the last 10 messages if there are any
const recentMessages = chatHistory.slice(-20);
recentMessages.forEach(msg => {
if (msg.role === 'user') {
addUserMessage(msg.parts[0].text);
} else if (msg.role === 'model') {
addBotMessage(msg.parts[0].text);
}
});
} catch (e) {
console.error('Error loading chat history:', e);
chatHistory = [];
}
}
}
// Save chat history to localStorage
function saveChatHistory() {
// Limit history to last 50 messages to prevent localStorage overflow
const historyToSave = chatHistory.slice(-50);
localStorage.setItem('mindful-chat-history', JSON.stringify(historyToSave));
}
// Toggle chat interface
chatBubble.addEventListener('click', () => {
chatInterface.classList.toggle('scale-0');
// If opening the chat and no messages, load history or add welcome message
if (!chatInterface.classList.contains('scale-0')) {
if (chatMessages.children.length === 0) {
loadChatHistory();
// If still no messages after loading history, add welcome message
if (chatMessages.children.length === 0) {
addBotMessage("Hello! I'm your mindfulness assistant. I can help you apply the principles from 'Act As If Nothing Bothers You' to your daily life. What would you like help with today?");
}
}
chatInput.focus();
}
});
// Close chat interface
chatClose.addEventListener('click', () => {
chatInterface.classList.add('scale-0');
});
// Handle form submission
chatForm.addEventListener('submit', async (e) => {
e.preventDefault();
const userMessage = chatInput.value.trim();
if (userMessage) {
// Add user message to chat
addUserMessage(userMessage);
// Clear input
chatInput.value = '';
// Show loading indicator
chatLoading.classList.remove('hidden');
// Add typing indicator
const typingIndicator = document.createElement('div');
typingIndicator.className = 'typing-indicator';
typingIndicator.innerHTML = '<span></span><span></span><span></span>';
chatMessages.appendChild(typingIndicator);
chatMessages.scrollTop = chatMessages.scrollHeight;
// Update chat history
chatHistory.push({
role: 'user',
parts: [{ text: userMessage }]
});
try {
// Call Gemini API
const response = await generateContent(userMessage);
// Remove typing indicator
if (typingIndicator && typingIndicator.parentNode) {
typingIndicator.parentNode.removeChild(typingIndicator);
}
// Add bot response to chat
addBotMessage(response);
// Update chat history
chatHistory.push({
role: 'model',
parts: [{ text: response }]
});
// Save updated chat history
saveChatHistory();
} catch (error) {
// Remove typing indicator
if (typingIndicator && typingIndicator.parentNode) {
typingIndicator.parentNode.removeChild(typingIndicator);
}
console.error('Error calling Gemini API:', error);
addBotMessage("I'm sorry, I encountered an error. Please try again later.");
} finally {
// Hide loading indicator
chatLoading.classList.add('hidden');
}
}
});
// Function to add user message to chat
function addUserMessage(message) {
const messageElement = document.createElement('div');
messageElement.className = 'chat-message-user';
messageElement.innerHTML = `<p>${escapeHtml(message)}</p>`;
chatMessages.appendChild(messageElement);
chatMessages.scrollTop = chatMessages.scrollHeight;
}
// Function to add bot message to chat
function addBotMessage(message) {
const messageElement = document.createElement('div');
messageElement.className = 'chat-message-bot';
messageElement.innerHTML = `<p>${formatMessage(message)}</p>`;
chatMessages.appendChild(messageElement);
chatMessages.scrollTop = chatMessages.scrollHeight;
}
// Function to format message with markdown-like styling
function formatMessage(message) {
let formatted = escapeHtml(message);
// Bold text between ** **
formatted = formatted.replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>');
// Italic text between * *
formatted = formatted.replace(/\*(.*?)\*/g, '<em>$1</em>');
// Convert line breaks to <br>
formatted = formatted.replace(/\n/g, '<br>');
return formatted;
}
// Function to escape HTML to prevent XSS
function escapeHtml(unsafe) {
return unsafe
.replace(/&/g, "&amp;")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;")
.replace(/"/g, "&quot;")
.replace(/'/g, "&#039;");
}
// Function to call Gemini API
async function generateContent(prompt) {
// If no API key is available, use mock responses
if (!GEMINI_KEY) {
return getMockResponse(prompt);
}
try {
// Create context about the page content
const pageContext = `
This is a conversation about mindfulness, emotional control, and maintaining composure in difficult situations.
The user is viewing a page called "Act As If Nothing Bothers You" that covers these principles:
1. Mastering the Nothing Bothers Me Mindset - Detach emotions from external circumstances
2. Emotional Detachment Is Power - Experience emotions without being controlled by them
3. Mindful Indifference Is A Superpower - Choose what deserves your energy
4. Stop Seeking Approval - Free yourself from external validation
5. Handle Criticism Like A Master - Filter criticism through logic, not emotion
6. Keep Your Composure Under Pressure - Embrace uncertainty and adapt
7. Letting Go of What You Can't Control - Focus only on what you can influence
8. Silence is the Ultimate Power Move - Use strategic silence as a strength
9. Train Yourself to Stay Calm No Matter What - Build mental strength through daily practice
10. Mastering the Art of Moving in Silence - Let results speak for themselves
Help the user apply these principles to their life with practical advice and examples.
`;
// Prepare the full prompt with context
const fullPrompt = `${pageContext}\n\nUser: ${prompt}\n\nRespond in a helpful, concise way with practical advice. Keep responses under 150 words. Use markdown formatting with ** for bold and * for italic where appropriate.`;
// Make API request to Gemini API
const apiUrl = 'https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash:generateContent';
const apiKey = GEMINI_KEY; // Use the global API key variable
const response = await fetch(`${apiUrl}?key=${apiKey}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
contents: [
{
parts: [
{ text: fullPrompt }
]
}
],
generationConfig: {
temperature: 0.7,
maxOutputTokens: 800,
topP: 0.95,
topK: 40
},
safetySettings: [
{
category: "HARM_CATEGORY_HARASSMENT",
threshold: "BLOCK_MEDIUM_AND_ABOVE"
},
{
category: "HARM_CATEGORY_HATE_SPEECH",
threshold: "BLOCK_MEDIUM_AND_ABOVE"
},
{
category: "HARM_CATEGORY_SEXUALLY_EXPLICIT",
threshold: "BLOCK_MEDIUM_AND_ABOVE"
},
{
category: "HARM_CATEGORY_DANGEROUS_CONTENT",
threshold: "BLOCK_MEDIUM_AND_ABOVE"
}
]
})
});
if (!response.ok) {
throw new Error(`API request failed with status ${response.status}`);
}
const data = await response.json();
// Extract the response text
if (data.candidates && data.candidates[0].content && data.candidates[0].content.parts && data.candidates[0].content.parts[0].text) {
return data.candidates[0].content.parts[0].text;
} else {
throw new Error('Unexpected API response format');
}
} catch (error) {
console.error('Error generating content:', error);
return "I'm sorry, I couldn't process your request. Please try again later.";
}
}
// Mock responses for when API key is not available
function getMockResponse(prompt) {
// Wait for a realistic delay
return new Promise(resolve => {
setTimeout(() => {
const lowerPrompt = prompt.toLowerCase();
let response = "";
if (lowerPrompt.includes("mindset") || lowerPrompt.includes("principle 1")) {
response = "**Mastering the Nothing Bothers Me Mindset** is about mental separation from external events. Try this: When something upsets you, pause for 5 seconds before responding. During this pause, ask yourself: 'Will this matter in 5 years?' This creates space between stimulus and reaction, allowing you to choose your response rather than being controlled by it.";
}
else if (lowerPrompt.includes("detachment") || lowerPrompt.includes("principle 2")) {
response = "**Emotional detachment** means experiencing feelings without being controlled by them. Practice the 'Observer Technique': When emotions arise, mentally step back and think, 'I notice I'm feeling angry' rather than 'I am angry.' This small shift helps you recognize emotions as temporary experiences rather than defining characteristics.";
}
else if (lowerPrompt.includes("indifference") || lowerPrompt.includes("principle 3")) {
response = "**Mindful indifference** is about selective caring. Create a 'Worth My Energy' list with 5 things truly deserving your emotional investment (family, health, key goals). When something bothers you, check if it's on your list. If not, practice letting it go with a deep breath and mental release. This isn't apathy—it's strategic energy allocation.";
}
else if (lowerPrompt.includes("approval") || lowerPrompt.includes("principle 4")) {
response = "To **stop seeking approval**, conduct an 'Opinion Audit': List whose opinions you currently value and ask for each person: 'Does this person truly understand my journey and have my best interests at heart?' Reduce your list to 3-5 people maximum. Then practice self-validation by writing three things you're proud of about yourself each day.";
}
else if (lowerPrompt.includes("criticism") || lowerPrompt.includes("principle 5")) {
response = "When facing **criticism**, use this filter: 1) Is this person qualified to give feedback? 2) Is their criticism specific/actionable or vague/emotional? 3) Do they have my best interests at heart? Practice saying 'Thank you for your feedback' regardless of your internal response, then process it privately to extract any valuable insights.";
}
else if (lowerPrompt.includes("pressure") || lowerPrompt.includes("composure") || lowerPrompt.includes("principle 6")) {
response = "To **maintain composure under pressure**, try 'Pressure Rehearsal': Identify upcoming high-pressure situations, mentally rehearse worst-case scenarios, and plan your composed response. When feeling pressure, shift perspective by telling yourself: 'This is my test—my opportunity to demonstrate control.' Focus immediately on your breathing and posture.";
}
else if (lowerPrompt.includes("letting go") || lowerPrompt.includes("control") || lowerPrompt.includes("principle 7")) {
response = "For **letting go of what you can't control**, use the 'Control Inventory': Draw a line down paper's middle. List everything about your challenge you can control (left) and cannot control (right). Commit to focusing exclusively on the left column. For the right column, practice saying 'I release this' with each exhale.";
}
else if (lowerPrompt.includes("silence") || lowerPrompt.includes("principle 8")) {
response = "**Silence as power**: In your next three conversations, speak 50% less than normal, ask one thoughtful question then listen fully, and wait 3 seconds before responding to anything. When someone provokes you, maintain eye contact and say nothing for 5-10 seconds. This creates tension that shifts power dynamics in your favor.";
}
else if (lowerPrompt.includes("calm") || lowerPrompt.includes("principle 9")) {
response = "To **train calmness**, develop a daily mental training routine: 30-second cold shower (discomfort tolerance), 5-minute meditation (focus despite distractions), one small act of discipline, and gratitude practice. Each week, intentionally do something slightly uncomfortable that builds resilience, observing your reactions without judgment.";
}
else if (lowerPrompt.includes("moving in silence") || lowerPrompt.includes("principle 10")) {
response = "For **moving in silence**, choose one significant goal and commit not to discuss it with anyone except essential partners. Channel the energy you'd use talking about it into actually doing it. Before sharing achievements, ask: 'Am I sharing for validation or because it adds value to the listener?' Let your results speak for themselves.";
}
else if (lowerPrompt.includes("exercise") || lowerPrompt.includes("practice")) {
response = "Try this **daily practice**: 1) Morning: 2-minute breathing exercise focusing only on your breath. 2) Throughout day: When triggered, count to 5 before responding. 3) Evening: Reflect on 3 things you handled with composure and 1 area to improve tomorrow. Consistency with small practices builds the mental muscle for bigger challenges.";
}
else if (lowerPrompt.includes("angry") || lowerPrompt.includes("anger") || lowerPrompt.includes("mad")) {
response = "When anger arises, try the **STOP technique**: **S**top what you're doing. **T**ake a deep breath. **O**bserve your feelings without judgment. **P**roceed with intention. Remember that anger is often a secondary emotion covering fear, hurt, or frustration. Name the underlying emotion to reduce its power: 'I notice I'm feeling hurt right now.'";
}
else if (lowerPrompt.includes("anxiety") || lowerPrompt.includes("anxious") || lowerPrompt.includes("stress") || lowerPrompt.includes("worried")) {
response = "For anxiety, practice **grounding**: Find 5 things you can see, 4 things you can touch, 3 things you can hear, 2 things you can smell, and 1 thing you can taste. This brings you to the present moment. Then ask: 'What one small action can I take right now?' Taking action, however small, reduces the feeling of helplessness.";
}
else if (lowerPrompt.includes("thank") || lowerPrompt.includes("hello") || lowerPrompt.includes("hi")) {
response = "Hello! I'm here to help you apply the principles from 'Act As If Nothing Bothers You' to your daily life. Is there a specific principle you'd like to explore, or perhaps a challenging situation where you'd like to maintain more composure?";
}
else {
response = "To apply the **unshakable mindset** to your situation, remember that true power comes from choosing your reactions rather than being controlled by circumstances. Practice the 5-second pause when triggered, detach from outcomes you can't control, and remember that most things bothering you now won't matter in five years. What specific principle would you like more guidance on?";
}
resolve(response);
}, 1500); // Realistic delay
});
}
// Clear chat history
clearChatHistoryButton.addEventListener('click', function() {
if (confirm('Are you sure you want to clear your chat history?')) {
chatHistory = [];
localStorage.removeItem('mindful-chat-history');
chatMessages.innerHTML = '';
addBotMessage("I've cleared our conversation history. How can I help you today?");
}
});
// Add event listeners for page-specific interactions
document.addEventListener('DOMContentLoaded', function() {
// Listen for section completion to offer relevant suggestions
const sectionCompleteButtons = document.querySelectorAll('[id^="mark-"][id$="-complete"]');
sectionCompleteButtons.forEach(button => {
button.addEventListener('click', function() {
const sectionId = this.id.replace('mark-', '').replace('-complete', '');
// If chat is open, provide relevant suggestion based on completed section
if (!chatInterface.classList.contains('scale-0')) {
let message = "";
if (sectionId === 'section1') {
message = "I noticed you completed the section on the Nothing Bothers Me Mindset. Would you like some additional exercises for practicing emotional detachment in daily situations?";
} else if (sectionId === 'section4') {
message = "Great job completing the section on Stopping Seeking Approval! Would you like some practical tips for building self-validation?";
} else if (sectionId === 'section8') {
message = "You've completed the Power of Silence section. Would you like to discuss specific scenarios where strategic silence can be most effective?";
}
if (message) {
// Add bot suggestion with delay
setTimeout(() => {
addBotMessage(message);
// Update chat history
chatHistory.push({
role: 'model',
parts: [{ text: message }]
});
saveChatHistory();
}, 1000);
}
}
});
});
// Check for dark mode changes to update chat UI accordingly
const darkModeToggle = document.getElementById('dark-mode-toggle');
if (darkModeToggle) {
darkModeToggle.addEventListener('click', function() {
// The CSS variables take care of the styling automatically
// This is just to register the event
});
}
// Add keyboard shortcut (Alt+C) to toggle chat
document.addEventListener('keydown', function(e) {
if (e.altKey && e.key === 'c') {
e.preventDefault();
chatBubble.click();
}
// Close chat with Escape key
if (e.key === 'Escape' && !chatInterface.classList.contains('scale-0')) {
chatClose.click();
}
});
});
})();
// Additional script to initialize GEMINI_KEY from Hugging Face environment
(async function() {
// Try to get the API key from Hugging Face Spaces environment
// Note: For this to work, you need to set up a simple API endpoint in your Space
if (!GEMINI_KEY) {
try {
// This endpoint would need to be implemented in your Hugging Face Space
const response = await fetch('/api/gemini-key');
if (response.ok) {
const data = await response.json();
if (data.key) {
window.GEMINI_KEY = data.key;
console.log('Successfully loaded Gemini API key');
}
}
} catch (error) {
console.warn('Could not load Gemini API key, using mock responses');
}
}
})();
</script>