mirror of
https://github.com/fromchat-messenger/web.git
synced 2026-09-22 19:15:08 +03:00
Implement working DMs
This commit is contained in:
@@ -202,3 +202,19 @@ def logout(
|
|||||||
"status": "success",
|
"status": "success",
|
||||||
"message": "Logged out successfully"
|
"message": "Logged out successfully"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@router.get("/users")
|
||||||
|
def list_users(current_user: User = Depends(get_current_user), db: Session = Depends(get_db)):
|
||||||
|
users = db.query(User).order_by(User.username.asc()).all()
|
||||||
|
return {
|
||||||
|
"users": [
|
||||||
|
convert_user(u) for u in users if u.id != current_user.id
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@router.get("/crypto/public-key/of/{user_id}")
|
||||||
|
def get_public_key_of(user_id: int, current_user: User = Depends(get_current_user), db: Session = Depends(get_db)):
|
||||||
|
row = db.query(CryptoPublicKey).filter(CryptoPublicKey.user_id == user_id).first()
|
||||||
|
return {"publicKey": row.public_key_b64 if row else None}
|
||||||
+1
-10
@@ -164,16 +164,7 @@
|
|||||||
<mdui-tab-panel slot="panel" value="channels">Скоро будет...</mdui-tab-panel>
|
<mdui-tab-panel slot="panel" value="channels">Скоро будет...</mdui-tab-panel>
|
||||||
<mdui-tab-panel slot="panel" value="contacts">Скоро будет...</mdui-tab-panel>
|
<mdui-tab-panel slot="panel" value="contacts">Скоро будет...</mdui-tab-panel>
|
||||||
<mdui-tab-panel slot="panel" value="dms">
|
<mdui-tab-panel slot="panel" value="dms">
|
||||||
<mdui-list>
|
<mdui-list id="dm-users"></mdui-list>
|
||||||
<mdui-list-item>
|
|
||||||
<div style="display:flex;gap:8px;align-items:center;width:100%">
|
|
||||||
<mdui-text-field id="dm-username" label="Username" variant="outlined" style="flex:0 0 160px"></mdui-text-field>
|
|
||||||
<mdui-text-field id="dm-input" label="Сообщение" variant="outlined" style="flex:1"></mdui-text-field>
|
|
||||||
<mdui-button id="dm-send">Отправить</mdui-button>
|
|
||||||
</div>
|
|
||||||
</mdui-list-item>
|
|
||||||
</mdui-list>
|
|
||||||
<div class="chat-messages" id="dm-messages" style="margin-top:8px"></div>
|
|
||||||
</mdui-tab-panel>
|
</mdui-tab-panel>
|
||||||
</mdui-tabs>
|
</mdui-tabs>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
+53
-19
@@ -70,7 +70,7 @@ export async function decryptDm(envelope: DmEnvelope, senderPublicKeyB64: string
|
|||||||
}
|
}
|
||||||
|
|
||||||
function appendDmMessage(text: string, isAuthor: boolean) {
|
function appendDmMessage(text: string, isAuthor: boolean) {
|
||||||
const container = document.getElementById("dm-messages")!;
|
const container = document.getElementById("chat-messages")!;
|
||||||
const div = document.createElement("div");
|
const div = document.createElement("div");
|
||||||
div.className = `message ${isAuthor ? "sent" : "received"}`;
|
div.className = `message ${isAuthor ? "sent" : "received"}`;
|
||||||
const inner = document.createElement("div");
|
const inner = document.createElement("div");
|
||||||
@@ -84,30 +84,64 @@ function appendDmMessage(text: string, isAuthor: boolean) {
|
|||||||
container.scrollTop = container.scrollHeight;
|
container.scrollTop = container.scrollHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function fetchRecipient(userName: string): Promise<{ id: number; publicKey: string | null } | null> {
|
// removed unused helper
|
||||||
const res = await fetch(`${API_BASE_URL}/profile/${encodeURIComponent(userName)}`);
|
|
||||||
if (!res.ok) return null;
|
let activeDm: { userId: number; username: string; publicKey: string | null } | null = null;
|
||||||
|
let usersLoaded = false;
|
||||||
|
|
||||||
|
async function loadUsers() {
|
||||||
|
const res = await fetch(`${API_BASE_URL}/users`, { headers: getAuthHeaders(true) });
|
||||||
|
if (!res.ok) return;
|
||||||
const data = await res.json();
|
const data = await res.json();
|
||||||
// This assumes an endpoint returns profile with id; adapt if different
|
const list = document.getElementById("dm-users")!;
|
||||||
const pkRes = await fetch(`${API_BASE_URL}/crypto/public-key`, { headers: getAuthHeaders(true) });
|
list.innerHTML = "";
|
||||||
// For simplicity, we reuse current user's endpoint; in real case, need GET by userId
|
(data.users || []).forEach((u: any) => {
|
||||||
// Minimal v1: assume recipient has same endpoint at /profile/public-key?userId=... (not implemented)
|
const item = document.createElement("mdui-list-item");
|
||||||
return { id: data.id, publicKey: null };
|
item.setAttribute("headline", u.username);
|
||||||
|
item.addEventListener("click", async () => {
|
||||||
|
activeDm = { userId: u.id, username: u.username, publicKey: null };
|
||||||
|
document.getElementById("chat-name")!.textContent = u.username;
|
||||||
|
(document.getElementById("chat-messages") as HTMLElement).innerHTML = "";
|
||||||
|
const resPk = await fetch(`${API_BASE_URL}/crypto/public-key/of/${u.id}`, { headers: getAuthHeaders(true) });
|
||||||
|
if (resPk.ok) {
|
||||||
|
const pkData = await resPk.json();
|
||||||
|
activeDm!.publicKey = pkData.publicKey;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
list.appendChild(item);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
document.addEventListener("DOMContentLoaded", () => {
|
document.addEventListener("DOMContentLoaded", () => {
|
||||||
const sendBtn = document.getElementById("dm-send");
|
const tabs = document.querySelector(".chat-tabs mdui-tabs");
|
||||||
if (!sendBtn) return;
|
const dmTab = tabs?.querySelector('mdui-tab[value="dms"]');
|
||||||
sendBtn.addEventListener("click", async () => {
|
function ensureUsersLoaded() {
|
||||||
const userEl = document.getElementById("dm-username") as HTMLInputElement;
|
if (!usersLoaded) {
|
||||||
const textEl = document.getElementById("dm-input") as HTMLInputElement;
|
usersLoaded = true;
|
||||||
const username = userEl.value.trim();
|
loadUsers();
|
||||||
const text = textEl.value.trim();
|
}
|
||||||
if (!username || !text) return;
|
}
|
||||||
// TODO: replace with real lookup for recipientId and publicKey
|
dmTab?.addEventListener("click", ensureUsersLoaded);
|
||||||
|
(tabs as any)?.addEventListener("change", (e: any) => {
|
||||||
|
if (e?.detail?.value === "dms") ensureUsersLoaded();
|
||||||
|
});
|
||||||
|
const form = document.getElementById("message-form");
|
||||||
|
if (form) {
|
||||||
|
form.addEventListener("submit", async (e) => {
|
||||||
|
if (!activeDm) return; // Let global chat handler proceed
|
||||||
|
e.preventDefault();
|
||||||
|
const input = document.getElementById("message-input") as HTMLInputElement;
|
||||||
|
const text = input.value.trim();
|
||||||
|
if (!text) return;
|
||||||
appendDmMessage(text, true);
|
appendDmMessage(text, true);
|
||||||
textEl.value = "";
|
input.value = "";
|
||||||
|
if (activeDm.publicKey) {
|
||||||
|
try {
|
||||||
|
await sendDm(activeDm.userId, activeDm.publicKey, text);
|
||||||
|
} catch {}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user