Mark-Lasfar
commited on
Commit
·
a7b1069
1
Parent(s):
32b6b18
Update backend and server frontend for OAuth JSON response, client-side navigation, and add .gitignore
Browse files- static/js/chat.js +109 -106
- templates/chat.html +6 -2
static/js/chat.js
CHANGED
|
@@ -49,127 +49,130 @@ let currentAssistantText = '';
|
|
| 49 |
let isSidebarOpen = window.innerWidth >= 768;
|
| 50 |
let abortController = null;
|
| 51 |
|
| 52 |
-
// Forcefully initialize chat view on load
|
| 53 |
-
document.addEventListener('DOMContentLoaded', async () => {
|
| 54 |
-
AOS.init({
|
| 55 |
-
duration: 800,
|
| 56 |
-
easing: 'ease-out-cubic',
|
| 57 |
-
once: true,
|
| 58 |
-
offset: 50,
|
| 59 |
-
});
|
| 60 |
|
| 61 |
-
// Force chat view to be visible immediately
|
| 62 |
-
enterChatView(true);
|
| 63 |
|
| 64 |
-
const authResult = await checkAuth();
|
| 65 |
-
if (authResult.authenticated && currentConversationId) {
|
| 66 |
-
console.log('Authenticated user, loading conversation with ID:', currentConversationId);
|
| 67 |
-
await loadConversation(currentConversationId);
|
| 68 |
-
// عرض بيانات المستخدم في الواجهة
|
| 69 |
-
const userInfoElement = document.getElementById('user-info');
|
| 70 |
-
if (userInfoElement && authResult.user) {
|
| 71 |
-
userInfoElement.textContent = `Welcome, ${authResult.user.email}`;
|
| 72 |
-
}
|
| 73 |
-
} else if (!authResult.authenticated && conversationHistory.length > 0) {
|
| 74 |
-
console.log('Unauthenticated user, restoring conversation history from sessionStorage:', conversationHistory);
|
| 75 |
-
conversationHistory.forEach(msg => {
|
| 76 |
-
console.log('Adding message from history:', msg);
|
| 77 |
-
addMsg(msg.role, msg.content);
|
| 78 |
-
});
|
| 79 |
-
// عرض Anonymous لو مفيش مستخدم موثّق
|
| 80 |
-
const userInfoElement = document.getElementById('user-info');
|
| 81 |
-
if (userInfoElement) {
|
| 82 |
-
userInfoElement.textContent = 'Anonymous';
|
| 83 |
-
}
|
| 84 |
-
} else {
|
| 85 |
-
console.log('No conversation history or ID, starting fresh');
|
| 86 |
-
const userInfoElement = document.getElementById('user-info');
|
| 87 |
-
if (userInfoElement) {
|
| 88 |
-
userInfoElement.textContent = 'Anonymous';
|
| 89 |
-
}
|
| 90 |
-
}
|
| 91 |
|
| 92 |
-
autoResizeTextarea();
|
| 93 |
-
updateSendButtonState();
|
| 94 |
-
if (uiElements.swipeHint) {
|
| 95 |
-
setTimeout(() => {
|
| 96 |
-
uiElements.swipeHint.style.display = 'none';
|
| 97 |
-
}, 3000);
|
| 98 |
-
}
|
| 99 |
-
setupTouchGestures();
|
| 100 |
-
});
|
| 101 |
|
| 102 |
-
// Check authentication token
|
| 103 |
async function checkAuth() {
|
| 104 |
-
|
| 105 |
-
|
| 106 |
-
|
| 107 |
-
|
| 108 |
-
|
| 109 |
-
|
| 110 |
-
|
| 111 |
-
|
| 112 |
-
|
| 113 |
|
| 114 |
-
|
| 115 |
-
|
| 116 |
|
| 117 |
-
|
| 118 |
-
|
| 119 |
-
|
| 120 |
-
|
| 121 |
-
|
| 122 |
-
|
|
|
|
| 123 |
}
|
| 124 |
-
}
|
| 125 |
-
|
| 126 |
-
if (!token) {
|
| 127 |
-
console.log('No auth token found in localStorage or cookie');
|
| 128 |
-
return { authenticated: false, user: null };
|
| 129 |
-
}
|
| 130 |
|
| 131 |
-
|
| 132 |
-
|
| 133 |
-
|
| 134 |
-
headers: {
|
| 135 |
-
'Authorization': `Bearer ${token}`,
|
| 136 |
-
'Accept': 'application/json'
|
| 137 |
-
}
|
| 138 |
-
});
|
| 139 |
-
const data = await response.json();
|
| 140 |
-
if (response.ok && data.status === 'valid') {
|
| 141 |
-
console.log('Auth token verified, user:', data.user);
|
| 142 |
-
return { authenticated: true, user: data.user };
|
| 143 |
-
} else {
|
| 144 |
-
console.log('Token verification failed:', data.detail || response.status);
|
| 145 |
-
localStorage.removeItem('token');
|
| 146 |
-
if (typeof Cookies !== 'undefined') {
|
| 147 |
-
Cookies.remove('fastapiusersauth');
|
| 148 |
-
}
|
| 149 |
-
return { authenticated: false, user: null };
|
| 150 |
}
|
| 151 |
-
|
| 152 |
-
|
| 153 |
-
|
| 154 |
-
|
| 155 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 156 |
}
|
| 157 |
-
return { authenticated: false, user: null };
|
| 158 |
-
}
|
| 159 |
}
|
| 160 |
-
|
| 161 |
async function handleSession() {
|
| 162 |
-
|
| 163 |
-
|
| 164 |
-
|
| 165 |
-
|
| 166 |
-
|
| 167 |
-
|
| 168 |
-
|
| 169 |
-
|
| 170 |
-
|
| 171 |
}
|
| 172 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 173 |
// Update send button state
|
| 174 |
function updateSendButtonState() {
|
| 175 |
if (uiElements.sendBtn && uiElements.input && uiElements.fileInput && uiElements.audioInput) {
|
|
|
|
| 49 |
let isSidebarOpen = window.innerWidth >= 768;
|
| 50 |
let abortController = null;
|
| 51 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 52 |
|
|
|
|
|
|
|
| 53 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 54 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 55 |
|
|
|
|
| 56 |
async function checkAuth() {
|
| 57 |
+
// تحقق من وجود access_token في query parameters
|
| 58 |
+
const urlParams = new URLSearchParams(window.location.search);
|
| 59 |
+
const accessTokenFromUrl = urlParams.get('access_token');
|
| 60 |
+
if (accessTokenFromUrl) {
|
| 61 |
+
console.log('Access token found in URL, saving to localStorage');
|
| 62 |
+
localStorage.setItem('token', accessTokenFromUrl);
|
| 63 |
+
// إزالة access_token من الـ URL عشان الأمان
|
| 64 |
+
window.history.replaceState({}, document.title, '/chat');
|
| 65 |
+
}
|
| 66 |
|
| 67 |
+
// تحقق من وجود token في localStorage
|
| 68 |
+
let token = localStorage.getItem('token');
|
| 69 |
|
| 70 |
+
// لو مفيش token في localStorage، حاول استخرج الـ token من الـ cookie
|
| 71 |
+
if (!token && typeof Cookies !== 'undefined') {
|
| 72 |
+
token = Cookies.get('fastapiusersauth');
|
| 73 |
+
if (token) {
|
| 74 |
+
console.log('Access token found in cookie, saving to localStorage');
|
| 75 |
+
localStorage.setItem('token', token);
|
| 76 |
+
}
|
| 77 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 78 |
|
| 79 |
+
if (!token) {
|
| 80 |
+
console.log('No auth token found in localStorage or cookie');
|
| 81 |
+
return { authenticated: false, user: null };
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 82 |
}
|
| 83 |
+
|
| 84 |
+
try {
|
| 85 |
+
const response = await fetch('/api/verify-token', {
|
| 86 |
+
method: 'GET',
|
| 87 |
+
headers: {
|
| 88 |
+
'Authorization': `Bearer ${token}`,
|
| 89 |
+
'Accept': 'application/json'
|
| 90 |
+
}
|
| 91 |
+
});
|
| 92 |
+
const data = await response.json();
|
| 93 |
+
if (response.ok && data.status === 'valid') {
|
| 94 |
+
console.log('Auth token verified, user:', data.user);
|
| 95 |
+
return { authenticated: true, user: data.user };
|
| 96 |
+
} else {
|
| 97 |
+
console.log('Token verification failed:', data.detail || 'Invalid token');
|
| 98 |
+
localStorage.removeItem('token');
|
| 99 |
+
if (typeof Cookies !== 'undefined') {
|
| 100 |
+
Cookies.remove('fastapiusersauth');
|
| 101 |
+
}
|
| 102 |
+
return { authenticated: false, user: null };
|
| 103 |
+
}
|
| 104 |
+
} catch (error) {
|
| 105 |
+
console.error('Error verifying token:', error);
|
| 106 |
+
localStorage.removeItem('token');
|
| 107 |
+
if (typeof Cookies !== 'undefined') {
|
| 108 |
+
Cookies.remove('fastapiusersauth');
|
| 109 |
+
}
|
| 110 |
+
return { authenticated: false, user: null };
|
| 111 |
}
|
|
|
|
|
|
|
| 112 |
}
|
| 113 |
+
|
| 114 |
async function handleSession() {
|
| 115 |
+
const sessionId = sessionStorage.getItem('session_id');
|
| 116 |
+
if (!sessionId) {
|
| 117 |
+
const newSessionId = crypto.randomUUID();
|
| 118 |
+
sessionStorage.setItem('session_id', newSessionId);
|
| 119 |
+
console.log('New session_id created:', newSessionId);
|
| 120 |
+
return newSessionId;
|
| 121 |
+
}
|
| 122 |
+
console.log('Existing session_id:', sessionId);
|
| 123 |
+
return sessionId;
|
| 124 |
}
|
| 125 |
|
| 126 |
+
window.addEventListener('load', async () => {
|
| 127 |
+
console.log('Chat page loaded, checking authentication');
|
| 128 |
+
AOS.init({
|
| 129 |
+
duration: 800,
|
| 130 |
+
easing: 'ease-out-cubic',
|
| 131 |
+
once: true,
|
| 132 |
+
offset: 50,
|
| 133 |
+
});
|
| 134 |
+
|
| 135 |
+
// Force chat view to be visible immediately
|
| 136 |
+
enterChatView(true);
|
| 137 |
+
|
| 138 |
+
const authResult = await checkAuth();
|
| 139 |
+
const userInfoElement = document.getElementById('user-info');
|
| 140 |
+
if (authResult.authenticated) {
|
| 141 |
+
console.log('User authenticated:', authResult.user);
|
| 142 |
+
if (userInfoElement) {
|
| 143 |
+
userInfoElement.textContent = `Welcome, ${authResult.user.email}`;
|
| 144 |
+
}
|
| 145 |
+
if (currentConversationId) {
|
| 146 |
+
console.log('Authenticated user, loading conversation with ID:', currentConversationId);
|
| 147 |
+
await loadConversation(currentConversationId);
|
| 148 |
+
}
|
| 149 |
+
} else {
|
| 150 |
+
console.log('User not authenticated, handling as anonymous');
|
| 151 |
+
if (userInfoElement) {
|
| 152 |
+
userInfoElement.textContent = 'Anonymous';
|
| 153 |
+
}
|
| 154 |
+
await handleSession();
|
| 155 |
+
if (conversationHistory.length > 0) {
|
| 156 |
+
console.log('Restoring conversation history from sessionStorage:', conversationHistory);
|
| 157 |
+
conversationHistory.forEach(msg => {
|
| 158 |
+
console.log('Adding message from history:', msg);
|
| 159 |
+
addMsg(msg.role, msg.content);
|
| 160 |
+
});
|
| 161 |
+
} else {
|
| 162 |
+
console.log('No conversation history, starting fresh');
|
| 163 |
+
}
|
| 164 |
+
}
|
| 165 |
+
|
| 166 |
+
autoResizeTextarea();
|
| 167 |
+
updateSendButtonState();
|
| 168 |
+
if (uiElements.swipeHint) {
|
| 169 |
+
setTimeout(() => {
|
| 170 |
+
uiElements.swipeHint.style.display = 'none';
|
| 171 |
+
}, 3000);
|
| 172 |
+
}
|
| 173 |
+
setupTouchGestures();
|
| 174 |
+
});
|
| 175 |
+
|
| 176 |
// Update send button state
|
| 177 |
function updateSendButtonState() {
|
| 178 |
if (uiElements.sendBtn && uiElements.input && uiElements.fileInput && uiElements.audioInput) {
|
templates/chat.html
CHANGED
|
@@ -100,6 +100,9 @@
|
|
| 100 |
<link rel="preload" href="/static/css/chat/style.css" as="style">
|
| 101 |
<link rel="preload" href="/static/images/mg.svg" as="image">
|
| 102 |
<link rel="preload" href="https://raw.githubusercontent.com/4gels/icons/refs/heads/main/splash-screen.png" as="image">
|
|
|
|
|
|
|
|
|
|
| 103 |
</head>
|
| 104 |
|
| 105 |
<body class="min-h-screen flex flex-col bg-gradient-to-br from-gray-900 via-teal-900 to-emerald-900">
|
|
@@ -354,6 +357,7 @@
|
|
| 354 |
</div>
|
| 355 |
<form id="settingsForm" class="space-y-4">
|
| 356 |
<div>
|
|
|
|
| 357 |
<label for="display_name" class="block text-sm text-gray-300">Display Name</label>
|
| 358 |
<input type="text" id="display_name" name="display_name" class="w-full p-2 bg-gray-700 text-white rounded">
|
| 359 |
</div>
|
|
@@ -419,8 +423,8 @@
|
|
| 419 |
|
| 420 |
<!-- Scripts -->
|
| 421 |
<script src="/static/js/chat.js?v=1.2"></script>
|
| 422 |
-
|
| 423 |
-
|
| 424 |
|
| 425 |
<script>
|
| 426 |
// تهيئة مكتبة AOS
|
|
|
|
| 100 |
<link rel="preload" href="/static/css/chat/style.css" as="style">
|
| 101 |
<link rel="preload" href="/static/images/mg.svg" as="image">
|
| 102 |
<link rel="preload" href="https://raw.githubusercontent.com/4gels/icons/refs/heads/main/splash-screen.png" as="image">
|
| 103 |
+
<script src="https://cdnjs.cloudflare.com/ajax/libs/js-cookie/3.0.1/js.cookie.min.js"></script>
|
| 104 |
+
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
|
| 105 |
+
|
| 106 |
</head>
|
| 107 |
|
| 108 |
<body class="min-h-screen flex flex-col bg-gradient-to-br from-gray-900 via-teal-900 to-emerald-900">
|
|
|
|
| 357 |
</div>
|
| 358 |
<form id="settingsForm" class="space-y-4">
|
| 359 |
<div>
|
| 360 |
+
<div id="user-info">Loading...</div>
|
| 361 |
<label for="display_name" class="block text-sm text-gray-300">Display Name</label>
|
| 362 |
<input type="text" id="display_name" name="display_name" class="w-full p-2 bg-gray-700 text-white rounded">
|
| 363 |
</div>
|
|
|
|
| 423 |
|
| 424 |
<!-- Scripts -->
|
| 425 |
<script src="/static/js/chat.js?v=1.2"></script>
|
| 426 |
+
|
| 427 |
+
|
| 428 |
|
| 429 |
<script>
|
| 430 |
// تهيئة مكتبة AOS
|