From c4f3a2cb89b72b59ad25f2cdad303f5f3d747eb3 Mon Sep 17 00:00:00 2001 From: Samuel Newman Date: Mon, 8 Jun 2026 19:26:23 +0300 Subject: [PATCH] [Chat] Rename invite route to /chat/ (#10782) --- __tests__/lib/strings/url-helpers.test.ts | 40 +++++++++---------- bskyweb/cmd/bskyweb/server.go | 6 +-- src/Navigation.tsx | 2 +- src/components/Post/Embed/ChatInviteEmbed.tsx | 2 +- src/components/dms/ChatInvite/Root.tsx | 2 +- src/lib/strings/url-helpers.ts | 2 +- .../Messages/components/InviteLinkDialog.tsx | 2 +- 7 files changed, 28 insertions(+), 28 deletions(-) diff --git a/__tests__/lib/strings/url-helpers.test.ts b/__tests__/lib/strings/url-helpers.test.ts index 23ffaa2875..dd1a096ef5 100644 --- a/__tests__/lib/strings/url-helpers.test.ts +++ b/__tests__/lib/strings/url-helpers.test.ts @@ -184,39 +184,39 @@ describe('getChatInviteCodeFromUrl', () => { type Case = [string, string | undefined] const cases: Case[] = [ - ['https://bsky.app/c/abcdefg', 'abcdefg'], - ['https://bsky.app/c/abcdefghij', 'abcdefghij'], + ['https://bsky.app/chat/abcdefg', 'abcdefg'], + ['https://bsky.app/chat/abcdefghij', 'abcdefghij'], // http is not recognized as a bsky.app url - ['http://bsky.app/c/abcdefg', undefined], - ['https://bsky.app/c/abcdefg?utm=foo', 'abcdefg'], - ['https://bsky.app/c/abcdefg#section', 'abcdefg'], - ['/c/abcdefg', 'abcdefg'], - ['/c/abcdefg?utm=foo', 'abcdefg'], - ['/c/abcdefg#section', 'abcdefg'], + ['http://bsky.app/chat/abcdefg', undefined], + ['https://bsky.app/chat/abcdefg?utm=foo', 'abcdefg'], + ['https://bsky.app/chat/abcdefg#section', 'abcdefg'], + ['/chat/abcdefg', 'abcdefg'], + ['/chat/abcdefg?utm=foo', 'abcdefg'], + ['/chat/abcdefg#section', 'abcdefg'], // too short - ['https://bsky.app/c/abcdef', undefined], - ['/c/abcdef', undefined], + ['https://bsky.app/chat/abcdef', undefined], + ['/chat/abcdef', undefined], // too long - ['https://bsky.app/c/abcdefghijk', undefined], - ['/c/abcdefghijk', undefined], + ['https://bsky.app/chat/abcdefghijk', undefined], + ['/chat/abcdefghijk', undefined], // invalid characters - ['https://bsky.app/c/abc-def', undefined], - ['/c/abc def', undefined], + ['https://bsky.app/chat/abc-def', undefined], + ['/chat/abc def', undefined], // trailing path - ['https://bsky.app/c/abcdefg/extra', undefined], - ['/c/abcdefg/extra', undefined], + ['https://bsky.app/chat/abcdefg/extra', undefined], + ['/chat/abcdefg/extra', undefined], // wrong path ['https://bsky.app/profile/abcdefg', undefined], - ['https://bsky.app/c', undefined], + ['https://bsky.app/chat', undefined], // wrong host - ['https://example.com/c/abcdefg', undefined], + ['https://example.com/chat/abcdefg', undefined], // not a url, not a path - ['c/abcdefg', undefined], + ['chat/abcdefg', undefined], ['abcdefg', undefined], ['', undefined], // malformed url - ['https://[invalid/c/abcdefg', undefined], + ['https://[invalid/chat/abcdefg', undefined], ] it.each(cases)('given input %p, returns %p', (input, expected) => { diff --git a/bskyweb/cmd/bskyweb/server.go b/bskyweb/cmd/bskyweb/server.go index cc5119e8d4..c4f31f20b4 100644 --- a/bskyweb/cmd/bskyweb/server.go +++ b/bskyweb/cmd/bskyweb/server.go @@ -88,7 +88,7 @@ func serve(cctx *cli.Context) error { Host: appviewHost, } - // optional client for the chat appview, used by /c/ for OG previews. + // optional client for the chat appview, used by /chat/ for OG previews. var chatXrpcc *xrpc.Client if chatHost != "" { chatXrpcc = &xrpc.Client{ @@ -367,7 +367,7 @@ func serve(cctx *cli.Context) error { e.GET("/start/:handleOrDID/:rkey", server.WebStarterPack) // chat invites - e.GET("/c/:code", server.WebChatInvite) + e.GET("/chat/:code", server.WebChatInvite) // bookmarks e.GET("/saved", server.WebGeneric) @@ -695,7 +695,7 @@ func (srv *Server) WebChatInvite(c echo.Context) error { data["title"] = preview.Name if srv.cfg.ogcardHost != "" { - // bskyogcard registers this route as /chat-invite/:code, not /c/:code. + // bskyogcard registers this route as /chat-invite/:code, not /chat/:code. data["imgThumbUrl"] = fmt.Sprintf("%s/chat-invite/%s", srv.cfg.ogcardHost, code) } return c.Render(http.StatusOK, "chatinvite.html", data) diff --git a/src/Navigation.tsx b/src/Navigation.tsx index efd1125295..ceebcf3986 100644 --- a/src/Navigation.tsx +++ b/src/Navigation.tsx @@ -804,7 +804,7 @@ const LINKING = { return buildStateObject('Flat', 'Home', params) } - // Chat invite URLs (`/c/:code`) are handled by `useIntentHandler`, which + // Chat invite URLs (`/chat/:code`) are handled by `useIntentHandler`, which // opens the GroupChatJoinDialog (or the logged-out join flow). Route the // path to Home so the dialog overlays Home instead of NotFound. On native, // react-navigation strips the `bluesky://` prefix and passes the path diff --git a/src/components/Post/Embed/ChatInviteEmbed.tsx b/src/components/Post/Embed/ChatInviteEmbed.tsx index 387c3cfd9c..16f05cbfea 100644 --- a/src/components/Post/Embed/ChatInviteEmbed.tsx +++ b/src/components/Post/Embed/ChatInviteEmbed.tsx @@ -8,7 +8,7 @@ import {JoinRequestEmbedBody} from '#/components/Post/Embed/JoinRequestEmbed' /** * Renders a chat invite link found in an `app.bsky.embed.external` embed (e.g. - * a `bsky.app/c/` link posted to the feed) as a join request card, + * a `bsky.app/chat/` link posted to the feed) as a join request card, * falling back to a plain external embed if the invite can't be resolved. */ export function ChatInviteEmbed({ diff --git a/src/components/dms/ChatInvite/Root.tsx b/src/components/dms/ChatInvite/Root.tsx index 025cae7a2e..ddfdec0d56 100644 --- a/src/components/dms/ChatInvite/Root.tsx +++ b/src/components/dms/ChatInvite/Root.tsx @@ -78,7 +78,7 @@ export function Root({ color: 'primary', disabled: false, onPress: () => { - void setStringAsync(`https://bsky.app/c/${preview.code}`) + void setStringAsync(`https://bsky.app/chat/${preview.code}`) Toast.show(l`Copied to clipboard`, {type: 'success'}) }, } diff --git a/src/lib/strings/url-helpers.ts b/src/lib/strings/url-helpers.ts index fd1a5ef7d9..38d3d70813 100644 --- a/src/lib/strings/url-helpers.ts +++ b/src/lib/strings/url-helpers.ts @@ -179,7 +179,7 @@ export function isBskyStarterPackUrl(url: string): boolean { } // Invite codes are 7 alphanumeric characters long, supporting up to 10 here to future-proof. -export const CHAT_INVITE_CODE_REGEX = /^\/c\/([a-zA-Z0-9]{7,10})$/ +export const CHAT_INVITE_CODE_REGEX = /^\/chat\/([a-zA-Z0-9]{7,10})$/ export function getChatInviteCodeFromUrl(url: string): string | undefined { let pathname: string diff --git a/src/screens/Messages/components/InviteLinkDialog.tsx b/src/screens/Messages/components/InviteLinkDialog.tsx index 02d4505af0..636e2be64e 100644 --- a/src/screens/Messages/components/InviteLinkDialog.tsx +++ b/src/screens/Messages/components/InviteLinkDialog.tsx @@ -292,7 +292,7 @@ export function InviteLinkDialog({ const linkEnabled = joinLink?.enabledStatus === 'enabled' const linkDisabled = joinLink?.enabledStatus === 'disabled' const joinLinkURI = joinLink?.code - ? `https://bsky.app/c/${joinLink.code}` + ? `https://bsky.app/chat/${joinLink.code}` : 'https://bsky.app/' const createdAt = joinLink ? new Date(joinLink.createdAt) : null const currentOption =