cheogram-www
created pr with
cheogram-www/multi-dm.1
changed pr name to
New UI for starting chats with multiDM support
added cheogram-www/multi-dm.2
1: 8f55142 < -: ------- Add UI to create private channel
2: ea160a8 ! 1: e758cfd New UI for starting chats
3: faa9d23 = 2: eb5c50d Special case for group texts
4: 0d9f850 = 3: 2217816 Only enable non-group-text multiDM experimentally
cmds
checkout latest patchset:
ssh pr.pico.sh pull cheogram-www:multi-dm | git am -3checkout specific patchset revision:
ssh pr.pico.sh pull cheogram-www:multi-dm [rev] | git am -3add changes to patch request:
git format-patch main --stdout | ssh pr.pico.sh cheogram-www:multi-dmadd comment to patch request:
ssh pr.pico.sh comment cheogram-www:multi-dm "lgtm!"
Patchset
cheogram-www/multi-dm.2
Only enable non-group-text multiDM experimentally
Stephen Paul Weber
2026-11-10T19:07:02ZSemantic diff summary
0 added,
3 modified,
0 signature changed,
0 removed
across 2 analyzed files
+18
-2
src/components/NewChatDialog.test.tsx
#
| ... | ... | @@ -8,10 +8,11 @@ import { | |
| 8 | 8 | screen, | |
| 9 | 9 | waitFor, | |
| 10 | 10 | } from "@testing-library/react"; | |
| 11 | - | import { afterEach, describe, expect, it, vi } from "vitest"; | |
| 11 | + | import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; | |
| 12 | 12 | import { mock } from "vitest-mock-extended"; | |
| 13 | 13 | import { NewChatDialog } from "./NewChatDialog"; | |
| 14 | 14 | ||
| 15 | + | beforeEach(() => localStorage.clear()); | |
| 15 | 16 | afterEach(cleanup); | |
| 16 | 17 | ||
| 17 | 18 | const availableChat = ( |
| ... | ... | @@ -108,7 +109,8 @@ describe("NewChatDialog", () => { | |
| 108 | 109 | expect(startChat).toHaveBeenCalledWith(alice); | |
| 109 | 110 | }); | |
| 110 | 111 | ||
| 111 | - | it("starts a multiDM when more than one result is selected", async () => { | |
| 112 | + | it("starts a multiDM when EXPERIMENTAL is set", async () => { | |
| 113 | + | localStorage.setItem("EXPERIMENTAL", "1"); | |
| 112 | 114 | const alice = availableChat("alice@example.com", "Alice"); | |
| 113 | 115 | const bob = availableChat("bob@example.com", "Bob"); | |
| 114 | 116 | const { startMultiChat, onStarted, multiChat } = setup([alice, bob]); |
| ... | ... | @@ -121,6 +123,20 @@ describe("NewChatDialog", () => { | |
| 121 | 123 | expect(startMultiChat).toHaveBeenCalledWith([alice, bob]); | |
| 122 | 124 | }); | |
| 123 | 125 | ||
| 126 | + | it("replaces non-Cheogram selections when EXPERIMENTAL is not set", async () => { | |
| 127 | + | const alice = availableChat("alice@example.com", "Alice"); | |
| 128 | + | const bob = availableChat("bob@example.com", "Bob"); | |
| 129 | + | const { startChat, startMultiChat, onStarted, chat } = setup([alice, bob]); | |
| 130 | + | ||
| 131 | + | fireEvent.click(await search("example.com", "Alice")); | |
| 132 | + | fireEvent.click(screen.getByText("Bob")); | |
| 133 | + | fireEvent.click(screen.getByRole("button", { name: "Start Chat" })); | |
| 134 | + | ||
| 135 | + | await waitFor(() => expect(onStarted).toHaveBeenCalledWith(chat)); | |
| 136 | + | expect(startChat).toHaveBeenCalledWith(bob); | |
| 137 | + | expect(startMultiChat).not.toHaveBeenCalled(); | |
| 138 | + | }); | |
| 139 | + | ||
| 124 | 140 | it("does not offer the current account as a counterpart", async () => { | |
| 125 | 141 | const me = availableChat("me@example.com", "Me"); | |
| 126 | 142 | const alice = availableChat("alice@example.com", "Alice"); |
+7
-3
src/components/NewChatDialog.tsx
#
| ... | ... | @@ -116,10 +116,14 @@ export const NewChatDialog = ({ | |
| 116 | 116 | return existing.filter((c) => c.chatId !== availableChat.chatId); | |
| 117 | 117 | } | |
| 118 | 118 | ||
| 119 | - | // A multiDM cannot include a channel, and Cheogram contacts can only be | |
| 120 | - | // grouped with other Cheogram contacts, so an incompatible selection | |
| 121 | - | // replaces any other selections. | |
| 119 | + | // MultiDMs are experimental, and cannot include a channel. Cheogram | |
| 120 | + | // contacts can only be grouped with other Cheogram contacts, so an | |
| 121 | + | // incompatible selection replaces any other selections. | |
| 122 | + | const multiDMEnabled = | |
| 123 | + | isCheogramChat(availableChat) || | |
| 124 | + | localStorage.getItem("EXPERIMENTAL") !== null; | |
| 122 | 125 | if ( | |
| 126 | + | !multiDMEnabled || | |
| 123 | 127 | availableChat.isChannel() || | |
| 124 | 128 | existing.some((c) => c.isChannel()) || | |
| 125 | 129 | (existing.length > 0 && |