Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
|
@@ -939,8 +939,6 @@ def format_project_ideas(ideas):
|
|
| 939 |
|
| 940 |
return result
|
| 941 |
|
| 942 |
-
# Missing function implementations
|
| 943 |
-
|
| 944 |
# Dictionary to store user profiles by session ID
|
| 945 |
user_profiles = {}
|
| 946 |
|
|
@@ -1167,8 +1165,8 @@ def create_chatbot():
|
|
| 1167 |
|
| 1168 |
# Create CSS with theme variables
|
| 1169 |
custom_css = """
|
| 1170 |
-
/*
|
| 1171 |
-
|
| 1172 |
--primary-color: #4a6fa5;
|
| 1173 |
--secondary-color: #6c757d;
|
| 1174 |
--success-color: #28a745;
|
|
@@ -1183,21 +1181,41 @@ def create_chatbot():
|
|
| 1183 |
--info-box-bg: #e7f5fe;
|
| 1184 |
}
|
| 1185 |
|
| 1186 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1187 |
@media (prefers-color-scheme: dark) {
|
| 1188 |
-
|
| 1189 |
-
|
| 1190 |
-
|
| 1191 |
-
|
| 1192 |
-
|
| 1193 |
-
|
| 1194 |
-
--
|
| 1195 |
-
|
| 1196 |
-
|
| 1197 |
-
|
| 1198 |
-
|
| 1199 |
-
|
| 1200 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1201 |
}
|
| 1202 |
}
|
| 1203 |
|
|
@@ -1338,42 +1356,43 @@ def create_chatbot():
|
|
| 1338 |
}
|
| 1339 |
"""
|
| 1340 |
|
| 1341 |
-
# JavaScript to detect and apply theme
|
| 1342 |
theme_script = """
|
| 1343 |
<script>
|
| 1344 |
-
//
|
| 1345 |
-
|
| 1346 |
-
//
|
| 1347 |
-
|
| 1348 |
-
const isDarkMode = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
|
| 1349 |
-
|
| 1350 |
-
// Force any specific elements that might need extra help
|
| 1351 |
-
const codeBlocks = document.querySelectorAll('pre code');
|
| 1352 |
-
codeBlocks.forEach(block => {
|
| 1353 |
-
block.style.color = isDarkMode ? '#f1f1f1' : '#212529';
|
| 1354 |
-
block.style.backgroundColor = isDarkMode ? '#2d2d2d' : '#f8f9fa';
|
| 1355 |
-
});
|
| 1356 |
-
|
| 1357 |
-
// Ensure markdown-rendered content is visible
|
| 1358 |
-
const markdownContent = document.querySelectorAll('.prose *');
|
| 1359 |
-
markdownContent.forEach(element => {
|
| 1360 |
-
// Skip elements that already have specific styling
|
| 1361 |
-
if (element.tagName === 'A' ||
|
| 1362 |
-
element.tagName.match(/^H[1-6]$/) ||
|
| 1363 |
-
element.tagName === 'CODE') {
|
| 1364 |
-
return;
|
| 1365 |
-
}
|
| 1366 |
-
|
| 1367 |
-
element.style.color = isDarkMode ? '#f1f1f1' : '#212529';
|
| 1368 |
-
});
|
| 1369 |
-
}
|
| 1370 |
|
| 1371 |
-
|
| 1372 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1373 |
|
| 1374 |
-
//
|
| 1375 |
-
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change',
|
| 1376 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1377 |
</script>
|
| 1378 |
"""
|
| 1379 |
|
|
@@ -1494,6 +1513,70 @@ def create_chatbot():
|
|
| 1494 |
|
| 1495 |
generate_plan_btn = gr.Button("Generate Study Plan", variant="primary")
|
| 1496 |
plan_output = gr.Markdown(label="Personalized Study Plan")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1497 |
|
| 1498 |
gr.HTML("""<div class="footer">
|
| 1499 |
AI Teaching Assistant | Version 2.0 | © 2025 | Powered by Groq AI
|
|
|
|
| 939 |
|
| 940 |
return result
|
| 941 |
|
|
|
|
|
|
|
| 942 |
# Dictionary to store user profiles by session ID
|
| 943 |
user_profiles = {}
|
| 944 |
|
|
|
|
| 1165 |
|
| 1166 |
# Create CSS with theme variables
|
| 1167 |
custom_css = """
|
| 1168 |
+
/* Theme variables - will be applied based on user's theme preference */
|
| 1169 |
+
.light-theme {
|
| 1170 |
--primary-color: #4a6fa5;
|
| 1171 |
--secondary-color: #6c757d;
|
| 1172 |
--success-color: #28a745;
|
|
|
|
| 1181 |
--info-box-bg: #e7f5fe;
|
| 1182 |
}
|
| 1183 |
|
| 1184 |
+
.dark-theme {
|
| 1185 |
+
--primary-color: #5b88c7;
|
| 1186 |
+
--secondary-color: #adb5bd;
|
| 1187 |
+
--success-color: #48c774;
|
| 1188 |
+
--bg-color: #1a1a1a;
|
| 1189 |
+
--text-color: #f1f1f1;
|
| 1190 |
+
--card-bg: #2d2d2d;
|
| 1191 |
+
--card-border: #444444;
|
| 1192 |
+
--input-bg: #333333;
|
| 1193 |
+
--highlight-color: #193652;
|
| 1194 |
+
--accent-color: #3291ff;
|
| 1195 |
+
--completed-color: #204829;
|
| 1196 |
+
--info-box-bg: #193652;
|
| 1197 |
+
}
|
| 1198 |
+
|
| 1199 |
+
/* Automatically detect theme preference and apply appropriate theme class */
|
| 1200 |
@media (prefers-color-scheme: dark) {
|
| 1201 |
+
body {
|
| 1202 |
+
color-scheme: dark;
|
| 1203 |
+
}
|
| 1204 |
+
|
| 1205 |
+
body:not(.light-theme):not(.force-light) {
|
| 1206 |
+
background-color: var(--bg-color);
|
| 1207 |
+
color: var(--text-color);
|
| 1208 |
+
}
|
| 1209 |
+
}
|
| 1210 |
+
|
| 1211 |
+
@media (prefers-color-scheme: light) {
|
| 1212 |
+
body {
|
| 1213 |
+
color-scheme: light;
|
| 1214 |
+
}
|
| 1215 |
+
|
| 1216 |
+
body:not(.dark-theme):not(.force-dark) {
|
| 1217 |
+
background-color: var(--bg-color);
|
| 1218 |
+
color: var(--text-color);
|
| 1219 |
}
|
| 1220 |
}
|
| 1221 |
|
|
|
|
| 1356 |
}
|
| 1357 |
"""
|
| 1358 |
|
| 1359 |
+
# JavaScript to detect and apply theme
|
| 1360 |
theme_script = """
|
| 1361 |
<script>
|
| 1362 |
+
// Function to detect and apply theme
|
| 1363 |
+
function applyTheme() {
|
| 1364 |
+
// Check if user has a saved preference
|
| 1365 |
+
const savedTheme = localStorage.getItem('preferredTheme');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1366 |
|
| 1367 |
+
if (savedTheme) {
|
| 1368 |
+
// Apply saved preference
|
| 1369 |
+
document.body.classList.add(savedTheme + '-theme');
|
| 1370 |
+
} else {
|
| 1371 |
+
// Check system preference
|
| 1372 |
+
if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
|
| 1373 |
+
document.body.classList.add('dark-theme');
|
| 1374 |
+
} else {
|
| 1375 |
+
document.body.classList.add('light-theme');
|
| 1376 |
+
}
|
| 1377 |
+
}
|
| 1378 |
|
| 1379 |
+
// Listen for theme changes
|
| 1380 |
+
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', event => {
|
| 1381 |
+
// Only apply if no saved preference
|
| 1382 |
+
if (!savedTheme) {
|
| 1383 |
+
document.body.classList.remove('light-theme', 'dark-theme');
|
| 1384 |
+
document.body.classList.add(event.matches ? 'dark-theme' : 'light-theme');
|
| 1385 |
+
}
|
| 1386 |
+
});
|
| 1387 |
+
}
|
| 1388 |
+
|
| 1389 |
+
// Apply theme when DOM is loaded
|
| 1390 |
+
document.addEventListener('DOMContentLoaded', applyTheme);
|
| 1391 |
+
|
| 1392 |
+
// For Gradio that might load content dynamically
|
| 1393 |
+
if (document.readyState === 'complete' || document.readyState === 'interactive') {
|
| 1394 |
+
setTimeout(applyTheme, 1);
|
| 1395 |
+
}
|
| 1396 |
</script>
|
| 1397 |
"""
|
| 1398 |
|
|
|
|
| 1513 |
|
| 1514 |
generate_plan_btn = gr.Button("Generate Study Plan", variant="primary")
|
| 1515 |
plan_output = gr.Markdown(label="Personalized Study Plan")
|
| 1516 |
+
|
| 1517 |
+
# Theme Selector Tab (New)
|
| 1518 |
+
with gr.Tab("Settings"):
|
| 1519 |
+
with gr.Column(elem_classes=["card"]):
|
| 1520 |
+
gr.HTML("<h3>App Settings</h3>")
|
| 1521 |
+
|
| 1522 |
+
theme_selector = gr.Radio(
|
| 1523 |
+
choices=["System Default", "Light Theme", "Dark Theme"],
|
| 1524 |
+
label="Theme Preference",
|
| 1525 |
+
value="System Default"
|
| 1526 |
+
)
|
| 1527 |
+
|
| 1528 |
+
# Add JavaScript to handle theme changes
|
| 1529 |
+
theme_js = """
|
| 1530 |
+
<script>
|
| 1531 |
+
// Get the radio input once it exists
|
| 1532 |
+
function setupThemeSelector() {
|
| 1533 |
+
const radioInputs = document.querySelectorAll('input[type="radio"][name="theme"]');
|
| 1534 |
+
if (radioInputs.length === 0) {
|
| 1535 |
+
setTimeout(setupThemeSelector, 300);
|
| 1536 |
+
return;
|
| 1537 |
+
}
|
| 1538 |
+
|
| 1539 |
+
// Set initial value based on stored preference
|
| 1540 |
+
const savedTheme = localStorage.getItem('preferredTheme');
|
| 1541 |
+
if (savedTheme === 'light') {
|
| 1542 |
+
radioInputs[1].checked = true;
|
| 1543 |
+
} else if (savedTheme === 'dark') {
|
| 1544 |
+
radioInputs[2].checked = true;
|
| 1545 |
+
} else {
|
| 1546 |
+
radioInputs[0].checked = true;
|
| 1547 |
+
}
|
| 1548 |
+
|
| 1549 |
+
// Add event listeners
|
| 1550 |
+
radioInputs.forEach(input => {
|
| 1551 |
+
input.addEventListener('change', function() {
|
| 1552 |
+
const body = document.body;
|
| 1553 |
+
body.classList.remove('light-theme', 'dark-theme', 'force-light', 'force-dark');
|
| 1554 |
+
|
| 1555 |
+
if (this.value === "Light Theme") {
|
| 1556 |
+
body.classList.add('light-theme', 'force-light');
|
| 1557 |
+
localStorage.setItem('preferredTheme', 'light');
|
| 1558 |
+
} else if (this.value === "Dark Theme") {
|
| 1559 |
+
body.classList.add('dark-theme', 'force-dark');
|
| 1560 |
+
localStorage.setItem('preferredTheme', 'dark');
|
| 1561 |
+
} else {
|
| 1562 |
+
localStorage.removeItem('preferredTheme');
|
| 1563 |
+
applyTheme(); // Reapply system theme
|
| 1564 |
+
}
|
| 1565 |
+
});
|
| 1566 |
+
});
|
| 1567 |
+
}
|
| 1568 |
+
|
| 1569 |
+
// Start setup
|
| 1570 |
+
setupThemeSelector();
|
| 1571 |
+
</script>
|
| 1572 |
+
"""
|
| 1573 |
+
gr.HTML(theme_js)
|
| 1574 |
+
|
| 1575 |
+
gr.HTML("""
|
| 1576 |
+
<div class="info-box">
|
| 1577 |
+
<p>These settings will be saved in your browser for future visits.</p>
|
| 1578 |
+
</div>
|
| 1579 |
+
""")
|
| 1580 |
|
| 1581 |
gr.HTML("""<div class="footer">
|
| 1582 |
AI Teaching Assistant | Version 2.0 | © 2025 | Powered by Groq AI
|