[Future] Saved messages: a DM with yourself (Telegram-style) #97

Open
opened 2026-10-07 23:31:28 +00:00 by robocub · 1 comment
Member

Tester request (10-07): "Can I DM myself like in Telegram?" — a "Saved messages" / note-to-self chat for personal notes, links and files you want on every device. Workaround today: make a private room and invite nobody. That works, but it shows up as a room, not in the DM list.

Upstream check: nothing matching in Commet's issues, PRs or branches (searched "note to self", "saved messages", "message yourself", "self dm").

How hard is it?

Small. Matrix already allows it: m.direct is keyed by user ID, and your own ID is a valid key. The work is mostly making the current code not trip over "my DM partner is me".

What breaks if we just add it naively (checked against testing a1a21432 + SDK vommet-v6.1.1-ss.3):

  1. Creating it. createDirectMessage → SDK startDirectChat(me) calls createRoom(invite: [me], isDirect: true). Inviting yourself fails, so the room can't be made that way. Instead: createRoom with no invite, preset: private_chat, encryption on, then addToDirectChat(me).
  2. Finding it again. startDirectChat / getDirectChatFromUserId(me) would find it once it's in m.direct (it only looks at joined rooms, and you are joined), so a second tap reuses it. Good.
  3. Calls. The room header's call button sends startCall(room, voice, userId: partner). With partner = me, that rings yourself. Hide call buttons when the partner is your own ID.
  4. Name and avatar. In a 1-member room the SDK's computed name is "Empty chat" or similar. Show a fixed label ("Saved messages" / "Notes") and your own avatar with a bookmark badge. Rename stays allowed.
  5. "Switch to/from DM" menu (directMessageCandidate) needs exactly 2 members, so it never offers it for a 1-member room. Fine — the self chat gets its own entry point instead.
  6. Encryption. A room with only you still uses Megolm and shares keys with your own verified devices, so it reads on every device you've verified. Nothing to add. Unverified new devices won't decrypt old notes until key backup restores them — same as every other room.
  7. Other clients. They see a normal private room with one member. Some list it under people (because of m.direct), some under rooms. Harmless either way.

Entry points: a pinned "Saved messages" row at the top of the DM list, and "Message yourself" on your own profile (today the profile's "Message" button calls startDirectChat on yourself and fails).

Telegram extras for later (not v1): "Save to Saved messages" in the message menu (forward a copy with a link back to the original), and share-to-Vommet from Android landing there.

Raised in the same discussion. Today:

  • The DM list (directMessageRooms) is one row per room. Two DM rooms with Alice give two "Alice" rows, with nothing to tell them apart.
  • Opening a DM from someone's profile picks existingRooms.first — which one depends on list order, not on which one is in use.
  • The SDK's startDirectChat picks the one with the newest message. Two code paths, two different answers.

This happens more than you'd think: both sides press "Message" at once, one side's client crashes during creation, an old DM was left and a new one made, or a bridge creates its own.

Proposed:

  • One row per person in the DM list. The row opens the room with the newest activity; unread counts add up across all of them.
  • When there's more than one, the row gets a small count and a dropdown (or a "Conversations" section on the person's profile) listing every room: name, last message, created date, encrypted or not.
  • Profile "Message" uses the same rule as the SDK (newest activity), so it's always the same room.
  • Optional "Merge" helper later: it can't actually merge history in Matrix, but it can post a pointer ("continued in …") and remove the old room from m.direct so it falls back to a normal room.
  • Group DMs (3+ people) stay separate rows; grouping is only for 1:1 rooms.
  • Your self-chat follows the same rule — several self rooms become one "Saved messages" row.

The grouping key is the m.direct user ID (getDirectMessagePartnerId), so it's a UI change in the list and profile code. The data model stays the same.

Open questions for the operator

  • Name: "Saved messages" (Telegram) or "Notes" or "Note to self"?
  • Should the self chat be created on first use only, or pinned in the list from the start (created when first opened)?
  • Grouped row: dropdown in the list, or only on the profile?
Tester request (10-07): "Can I DM myself like in Telegram?" — a "Saved messages" / note-to-self chat for personal notes, links and files you want on every device. Workaround today: make a private room and invite nobody. That works, but it shows up as a room, not in the DM list. Upstream check: nothing matching in Commet's issues, PRs or branches (searched "note to self", "saved messages", "message yourself", "self dm"). ## How hard is it? Small. Matrix already allows it: `m.direct` is keyed by user ID, and your own ID is a valid key. The work is mostly making the current code not trip over "my DM partner is me". **What breaks if we just add it naively** (checked against testing `a1a21432` + SDK `vommet-v6.1.1-ss.3`): 1. **Creating it.** `createDirectMessage` → SDK `startDirectChat(me)` calls `createRoom(invite: [me], isDirect: true)`. Inviting yourself fails, so the room can't be made that way. Instead: `createRoom` with no invite, `preset: private_chat`, encryption on, then `addToDirectChat(me)`. 2. **Finding it again.** `startDirectChat` / `getDirectChatFromUserId(me)` would find it once it's in `m.direct` (it only looks at joined rooms, and you are joined), so a second tap reuses it. Good. 3. **Calls.** The room header's call button sends `startCall(room, voice, userId: partner)`. With partner = me, that rings yourself. Hide call buttons when the partner is your own ID. 4. **Name and avatar.** In a 1-member room the SDK's computed name is "Empty chat" or similar. Show a fixed label ("Saved messages" / "Notes") and your own avatar with a bookmark badge. Rename stays allowed. 5. **"Switch to/from DM" menu** (`directMessageCandidate`) needs exactly 2 members, so it never offers it for a 1-member room. Fine — the self chat gets its own entry point instead. 6. **Encryption.** A room with only you still uses Megolm and shares keys with your own verified devices, so it reads on every device you've verified. Nothing to add. Unverified new devices won't decrypt old notes until key backup restores them — same as every other room. 7. **Other clients.** They see a normal private room with one member. Some list it under people (because of `m.direct`), some under rooms. Harmless either way. **Entry points:** a pinned "Saved messages" row at the top of the DM list, and "Message yourself" on your own profile (today the profile's "Message" button calls `startDirectChat` on yourself and fails). **Telegram extras for later (not v1):** "Save to Saved messages" in the message menu (forward a copy with a link back to the original), and share-to-Vommet from Android landing there. ## Related: grouping several DMs with the same person Raised in the same discussion. Today: - The DM list (`directMessageRooms`) is one row per room. Two DM rooms with Alice give two "Alice" rows, with nothing to tell them apart. - Opening a DM from someone's profile picks `existingRooms.first` — which one depends on list order, not on which one is in use. - The SDK's `startDirectChat` picks the one with the newest message. Two code paths, two different answers. This happens more than you'd think: both sides press "Message" at once, one side's client crashes during creation, an old DM was left and a new one made, or a bridge creates its own. Proposed: - **One row per person** in the DM list. The row opens the room with the newest activity; unread counts add up across all of them. - When there's more than one, the row gets a small count and a dropdown (or a "Conversations" section on the person's profile) listing every room: name, last message, created date, encrypted or not. - **Profile "Message" uses the same rule** as the SDK (newest activity), so it's always the same room. - Optional "Merge" helper later: it can't actually merge history in Matrix, but it can post a pointer ("continued in …") and remove the old room from `m.direct` so it falls back to a normal room. - Group DMs (3+ people) stay separate rows; grouping is only for 1:1 rooms. - Your self-chat follows the same rule — several self rooms become one "Saved messages" row. The grouping key is the `m.direct` user ID (`getDirectMessagePartnerId`), so it's a UI change in the list and profile code. The data model stays the same. ## Open questions for the operator - Name: "Saved messages" (Telegram) or "Notes" or "Note to self"? - Should the self chat be created on first use only, or pinned in the list from the start (created when first opened)? - Grouped row: dropdown in the list, or only on the profile?
Author
Member

On ice (operator, 10-07): Saved messages is a future task. The "several DMs with the same person" part is split into its own issue so it can be done sooner: see the new issue #99.

**On ice (operator, 10-07):** Saved messages is a future task. The "several DMs with the same person" part is split into its own issue so it can be done sooner: see the new issue #99.
robocub changed title from Saved messages: a DM with yourself (Telegram-style), and one row per person when you have several DMs with them to [Future] Saved messages: a DM with yourself (Telegram-style) 2026-10-07 23:36:15 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
nether/vommet#97
No description provided.