some little fixes
Continuous integration / Check (push) Successful in 31s
Continuous integration / build (push) Successful in 35s
Continuous integration / Rustfmt (push) Successful in 44s
Continuous integration / build-release (push) Successful in 56s
Continuous integration / Check (pull_request) Successful in 42s
Continuous integration / Rustfmt (pull_request) Successful in 1m29s
Continuous integration / build (pull_request) Successful in 38s
Continuous integration / build-release (pull_request) Successful in 1m3s

This commit is contained in:
wt committed 2025-11-28 12:23:33 +07:00
1 parent b833266664
commit db57b5a62f
6 files changed
+137 -105

No files matched your search

+87 -87
View File
@@ -1,94 +1,94 @@
use crate::state;
use crate::utils;
use axum::extract::{Json, State};
use sqlx::Row;
use std::sync::Arc;
// use crate::state;
// use crate::utils;
// use axum::extract::{Json, State};
// use sqlx::Row;
// use std::sync::Arc;
// Debug endpoint to see all messages
pub async fn debug_messages_handler(
State(state): State<Arc<state::AppState>>,
headers: axum::http::HeaderMap,
) -> Json<serde_json::Value> {
// Extract token from header
let token = if let Some(auth_header) = headers.get("authorization") {
auth_header.to_str().unwrap_or("").replace("Bearer ", "")
} else {
return Json(serde_json::json!({"error": "No token"}));
};
// // Debug endpoint to see all messages
// pub async fn debug_messages_handler(
// State(state): State<Arc<state::AppState>>,
// headers: axum::http::HeaderMap,
// ) -> Json<serde_json::Value> {
// // Extract token from header
// let token = if let Some(auth_header) = headers.get("authorization") {
// auth_header.to_str().unwrap_or("").replace("Bearer ", "")
// } else {
// return Json(serde_json::json!({"error": "No token"}));
// };
// Get current user from token
let username = match utils::verify_token(&state.db_pool, &token).await {
Ok(Some(user)) => user,
_ => return Json(serde_json::json!({"error": "Invalid token"})),
};
// // Get current user from token
// let username = match utils::verify_token(&state.db_pool, &token).await {
// Ok(Some(user)) => user,
// _ => return Json(serde_json::json!({"error": "Invalid token"})),
// };
// Get all messages for this user
let messages = sqlx::query(
r#"
SELECT id, from_user, to_user, content, timestamp, message_type, read,
deleted_for_sender, deleted_for_receiver, deleted_for_everyone
FROM messages
WHERE from_user = ? OR to_user = ?
ORDER BY timestamp DESC
LIMIT 100
"#,
)
.bind(&username)
.bind(&username)
.fetch_all(&state.db_pool)
.await;
// // Get all messages for this user
// let messages = sqlx::query(
// r#"
// SELECT id, from_user, to_user, content, timestamp, message_type, read,
// deleted_for_sender, deleted_for_receiver, deleted_for_everyone
// FROM messages
// WHERE from_user = ? OR to_user = ?
// ORDER BY timestamp DESC
// LIMIT 100
// "#,
// )
// .bind(&username)
// .bind(&username)
// .fetch_all(&state.db_pool)
// .await;
// Get chat partners count
let partners_result = sqlx::query(
r#"
SELECT COUNT(DISTINCT
CASE
WHEN from_user = ? THEN to_user
ELSE from_user
END
) as partner_count
FROM messages
WHERE from_user = ? OR to_user = ?
"#,
)
.bind(&username)
.bind(&username)
.bind(&username)
.fetch_one(&state.db_pool)
.await;
// // Get chat partners count
// let partners_result = sqlx::query(
// r#"
// SELECT COUNT(DISTINCT
// CASE
// WHEN from_user = ? THEN to_user
// ELSE from_user
// END
// ) as partner_count
// FROM messages
// WHERE from_user = ? OR to_user = ?
// "#,
// )
// .bind(&username)
// .bind(&username)
// .bind(&username)
// .fetch_one(&state.db_pool)
// .await;
match messages {
Ok(rows) => {
let mut result = Vec::new();
for row in rows {
result.push(serde_json::json!({
"id": row.get::<String, _>("id"),
"from_user": row.get::<String, _>("from_user"),
"to_user": row.get::<String, _>("to_user"),
"content": row.get::<String, _>("content"),
"timestamp": row.get::<i64, _>("timestamp"),
"message_type": row.get::<String, _>("message_type"),
"read": row.get::<bool, _>("read"),
"deleted_for_sender": row.get::<bool, _>("deleted_for_sender"),
"deleted_for_receiver": row.get::<bool, _>("deleted_for_receiver"),
"deleted_for_everyone": row.get::<bool, _>("deleted_for_everyone"),
"is_current_user_from": row.get::<String, _>("from_user") == username,
"is_current_user_to": row.get::<String, _>("to_user") == username,
}));
}
// match messages {
// Ok(rows) => {
// let mut result = Vec::new();
// for row in rows {
// result.push(serde_json::json!({
// "id": row.get::<String, _>("id"),
// "from_user": row.get::<String, _>("from_user"),
// "to_user": row.get::<String, _>("to_user"),
// "content": row.get::<String, _>("content"),
// "timestamp": row.get::<i64, _>("timestamp"),
// "message_type": row.get::<String, _>("message_type"),
// "read": row.get::<bool, _>("read"),
// "deleted_for_sender": row.get::<bool, _>("deleted_for_sender"),
// "deleted_for_receiver": row.get::<bool, _>("deleted_for_receiver"),
// "deleted_for_everyone": row.get::<bool, _>("deleted_for_everyone"),
// "is_current_user_from": row.get::<String, _>("from_user") == username,
// "is_current_user_to": row.get::<String, _>("to_user") == username,
// }));
// }
let partner_count = match partners_result {
Ok(row) => row.get::<i64, _>("partner_count"),
Err(_) => 0,
};
// let partner_count = match partners_result {
// Ok(row) => row.get::<i64, _>("partner_count"),
// Err(_) => 0,
// };
Json(serde_json::json!({
"user": username,
"total_messages": result.len(),
"chat_partners_count": partner_count,
"messages": result
}))
}
Err(e) => Json(serde_json::json!({"error": format!("Database error: {}", e)})),
}
}
// Json(serde_json::json!({
// "user": username,
// "total_messages": result.len(),
// "chat_partners_count": partner_count,
// "messages": result
// }))
// }
// Err(e) => Json(serde_json::json!({"error": format!("Database error: {}", e)})),
// }
// }
+2 -2
View File
@@ -60,7 +60,7 @@ async fn handle_websocket(socket: WebSocket, state: Arc<state::AppState>) {
))
.await;
utils::broadcast_user_list(&state.users).await;
// utils::broadcast_user_list(&state.users).await;
if let Ok(messages) = utils::get_message_history(
&state.db_pool,
@@ -169,6 +169,6 @@ async fn handle_websocket(socket: WebSocket, state: Arc<state::AppState>) {
}
state_clone.users.write().await.remove(&username_clone);
utils::broadcast_user_list(&state_clone.users).await;
// utils::broadcast_user_list(&state_clone.users).await;
println!("User {} disconnected", username_clone);
}
+4 -4
View File
@@ -47,10 +47,10 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
)
.route("/api/chats", get(api::chats::get_chats_handler))
.route("/api/search-users", get(api::search::search_users_handler))
.route(
"/api/debug-messages",
get(api::debug::debug_messages_handler),
)
// .route(
// "/api/debug-messages",
// get(api::debug::debug_messages_handler),
// )
.route("/api/mark-read", post(api::messages::mark_read_handler))
.route(
"/api/delete-message",
+12 -12
View File
@@ -1,6 +1,6 @@
use crate::model;
use crate::state;
use axum::extract::ws::Message;
// use crate::state;
// use axum::extract::ws::Message;
use rand::distributions::Alphanumeric;
use rand::{Rng, thread_rng};
use sqlx::{Row, SqlitePool};
@@ -135,17 +135,17 @@ pub async fn get_message_history(
Ok(messages)
}
pub async fn broadcast_user_list(users: &state::UserMap) {
let user_list: Vec<String> = users.read().await.keys().cloned().collect();
let user_list_msg = serde_json::json!({
"type": "user_list",
"users": user_list
});
// pub async fn broadcast_user_list(users: &state::UserMap) {
// let user_list: Vec<String> = users.read().await.keys().cloned().collect();
// let user_list_msg = serde_json::json!({
// "type": "user_list",
// "users": user_list
// });
for tx in users.read().await.values() {
let _ = tx.send(Message::Text(user_list_msg.to_string()));
}
}
// for tx in users.read().await.values() {
// let _ = tx.send(Message::Text(user_list_msg.to_string()));
// }
// }
pub async fn save_message(pool: &SqlitePool, msg: &model::ChatMessage) -> Result<(), sqlx::Error> {
sqlx::query(
+31
View File
@@ -631,6 +631,37 @@ body {
box-shadow: none;
}
.add-button {
padding: 12px 20px;
background: linear-gradient(
135deg,
var(--primary-color),
var(--primary-hover)
);
color: white;
border: none;
border-radius: 25px;
cursor: pointer;
font-size: 14px;
font-weight: 600;
transition: all 0.3s ease;
flex-shrink: 0;
min-height: 44px;
}
.add-button:hover:not(:disabled) {
transform: translateY(-2px);
box-shadow: 0 5px 15px rgba(52, 152, 219, 0.4);
}
.add-button:disabled {
background: var(--bg-tertiary);
color: var(--text-secondary);
cursor: not-allowed;
transform: none;
box-shadow: none;
}
.system-message {
text-align: center;
color: var(--text-secondary);
+1
View File
@@ -194,6 +194,7 @@
disabled
rows="1"
></textarea>
<button class="add-button">&plus;</button>
<button
onclick="sendMessage()"
class="send-button"