ausername-12345 commited on
Commit
eab9f14
Β·
1 Parent(s): 1e13409

auto-create dms on first message + notifications

Browse files
Files changed (2) hide show
  1. src/static/app.js +31 -9
  2. src/ws_manager.py +24 -1
src/static/app.js CHANGED
@@ -346,6 +346,15 @@ async function handleIncomingDm(msg) {
346
  const withPlain = { ...message, plaintext };
347
  msgCache[conversation_id].push(withPlain);
348
 
 
 
 
 
 
 
 
 
 
349
  // If this is the active chat, append the message
350
  if (currentChat && currentChat.type === "dm" && currentChat.id === conversation_id) {
351
  appendMessage(withPlain, currentChat.other_user);
@@ -627,12 +636,13 @@ async function sendDm(text) {
627
  const ciphertextForRecipient = await Crypto.encryptForRecipient(text, pubKeyCache[other.id]);
628
  const ciphertextForSender = myPubKey ? await Crypto.encryptForRecipient(text, myPubKey) : ciphertextForRecipient;
629
 
630
- ws.send(JSON.stringify({
631
- type: "dm",
632
- conversation_id: currentChat.id,
633
- ciphertext_for_recipient: ciphertextForRecipient,
634
- ciphertext_for_sender: ciphertextForSender
635
- }));
 
636
  }
637
 
638
  async function sendGroupMsg(text) {
@@ -724,12 +734,24 @@ async function searchUsers() {
724
  }, 300);
725
  }
726
 
 
 
 
 
 
 
 
 
727
  async function startDmWith(userId, user) {
728
  closeModal("modal-new-chat");
729
- const conv = await apiFetch(`/chat/conversations?target_user_id=${userId}`, token, "POST");
730
  setTab("dms");
731
- await loadChats();
732
- await openDmChat({ other_user: user });
 
 
 
 
 
733
  }
734
 
735
  // ── New Group ─────────────────────────────────────────────────────────────────
 
346
  const withPlain = { ...message, plaintext };
347
  msgCache[conversation_id].push(withPlain);
348
 
349
+ // For pending DM (no id yet), link it when we get the echo or a reply
350
+ if (currentChat && currentChat.type === "dm" && !currentChat.id) {
351
+ const matchesEcho = message.sender_id === me.id;
352
+ const matchesReply = message.sender_id === currentChat.other_user?.id;
353
+ if (matchesEcho || matchesReply) {
354
+ currentChat.id = conversation_id;
355
+ }
356
+ }
357
+
358
  // If this is the active chat, append the message
359
  if (currentChat && currentChat.type === "dm" && currentChat.id === conversation_id) {
360
  appendMessage(withPlain, currentChat.other_user);
 
636
  const ciphertextForRecipient = await Crypto.encryptForRecipient(text, pubKeyCache[other.id]);
637
  const ciphertextForSender = myPubKey ? await Crypto.encryptForRecipient(text, myPubKey) : ciphertextForRecipient;
638
 
639
+ const payload = { type: "dm", ciphertext_for_recipient: ciphertextForRecipient, ciphertext_for_sender: ciphertextForSender };
640
+ if (currentChat.id) {
641
+ payload.conversation_id = currentChat.id;
642
+ } else {
643
+ payload.target_user_id = other.id;
644
+ }
645
+ ws.send(JSON.stringify(payload));
646
  }
647
 
648
  async function sendGroupMsg(text) {
 
734
  }, 300);
735
  }
736
 
737
+ function showChatHeader(user) {
738
+ document.getElementById("chat-avatar").textContent = user.display_name[0].toUpperCase();
739
+ document.getElementById("chat-avatar").style.background = user.avatar_color;
740
+ document.getElementById("chat-name").textContent = user.display_name;
741
+ document.getElementById("chat-sub").textContent = "@" + user.username;
742
+ document.getElementById("group-settings-btn").classList.add("hidden");
743
+ }
744
+
745
  async function startDmWith(userId, user) {
746
  closeModal("modal-new-chat");
 
747
  setTab("dms");
748
+ currentChat = { type: "dm", id: null, other_user: user };
749
+ showChatHeader(user);
750
+ document.getElementById("empty-state").classList.add("hidden");
751
+ document.getElementById("chat-window").classList.remove("hidden");
752
+ document.getElementById("chat-window").classList.add("flex");
753
+ document.getElementById("messages").innerHTML = "";
754
+ document.getElementById("msg-input").focus();
755
  }
756
 
757
  // ── New Group ─────────────────────────────────────────────────────────────────
src/ws_manager.py CHANGED
@@ -28,10 +28,33 @@ class ConnectionManager:
28
 
29
  async def handle_dm(self, msg: dict, sender: User, db: Session):
30
  conversation_id = msg.get("conversation_id")
 
31
  ciphertext_for_recipient = msg.get("ciphertext_for_recipient")
32
  ciphertext_for_sender = msg.get("ciphertext_for_sender")
33
 
34
- if not conversation_id or not ciphertext_for_recipient:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
35
  return
36
 
37
  # Verify sender is in conversation
 
28
 
29
  async def handle_dm(self, msg: dict, sender: User, db: Session):
30
  conversation_id = msg.get("conversation_id")
31
+ target_user_id = msg.get("target_user_id")
32
  ciphertext_for_recipient = msg.get("ciphertext_for_recipient")
33
  ciphertext_for_sender = msg.get("ciphertext_for_sender")
34
 
35
+ if not ciphertext_for_recipient:
36
+ return
37
+
38
+ # Auto-create conversation if target_user_id is provided instead of conversation_id
39
+ if not conversation_id and target_user_id:
40
+ target = db.query(User).filter(User.id == target_user_id).first()
41
+ if not target:
42
+ return
43
+ my_ids = set(m.conversation_id for m in db.query(ConversationMember).filter(ConversationMember.user_id == sender.id).all())
44
+ their_ids = set(m.conversation_id for m in db.query(ConversationMember).filter(ConversationMember.user_id == target_user_id).all())
45
+ common = my_ids & their_ids
46
+ if common:
47
+ conversation_id = common.pop()
48
+ else:
49
+ conv = Conversation()
50
+ db.add(conv)
51
+ db.flush()
52
+ db.add(ConversationMember(conversation_id=conv.id, user_id=sender.id))
53
+ db.add(ConversationMember(conversation_id=conv.id, user_id=target_user_id))
54
+ db.flush()
55
+ conversation_id = conv.id
56
+
57
+ if not conversation_id:
58
  return
59
 
60
  # Verify sender is in conversation