@@ -10,6 +10,7 @@ import {
1010 Lock ,
1111 Save ,
1212 Trash2 ,
13+ Users ,
1314} from "lucide-react" ;
1415import { toast } from "sonner" ;
1516import {
@@ -18,6 +19,11 @@ import {
1819 type ServerFormData ,
1920} from "@/shared/types" ;
2021import type { ChatboxMode , ChatboxSettings } from "@/hooks/useChatboxes" ;
22+ import {
23+ chatboxAccessPresetFromSettings ,
24+ settingsFromChatboxAccessPreset ,
25+ type ChatboxAccessPreset ,
26+ } from "@/lib/chatbox-access-presets" ;
2127import { useChatboxMutations } from "@/hooks/useChatboxes" ;
2228import { useServerMutations } from "@/hooks/useWorkspaces" ;
2329import { AddServerModal } from "@/components/connection/AddServerModal" ;
@@ -107,6 +113,7 @@ function isInsecureUrl(url: string | undefined): boolean {
107113interface ChatboxEditorProps {
108114 chatbox ?: ChatboxSettings | null ;
109115 workspaceId : string ;
116+ workspaceName ?: string | null ;
110117 workspaceServers : WorkspaceServerOption [ ] ;
111118 onBack : ( ) => void ;
112119 onSaved ?: ( chatbox : ChatboxSettings ) => void ;
@@ -130,6 +137,7 @@ function createPlaygroundId(): string {
130137export function ChatboxEditor ( {
131138 chatbox,
132139 workspaceId,
140+ workspaceName,
133141 workspaceServers,
134142 onBack,
135143 onSaved,
@@ -299,6 +307,18 @@ export function ChatboxEditor({
299307 [ workspaceServers ] ,
300308 ) ;
301309
310+ const workspaceAccessLabel = workspaceName ?. trim ( ) || "Workspace" ;
311+ const accessPreset = useMemo (
312+ ( ) => chatboxAccessPresetFromSettings ( mode , allowGuestAccess ) ,
313+ [ mode , allowGuestAccess ] ,
314+ ) ;
315+
316+ const applyCreateAccessPreset = ( preset : ChatboxAccessPreset ) => {
317+ const next = settingsFromChatboxAccessPreset ( preset ) ;
318+ setMode ( next . mode ) ;
319+ setAllowGuestAccess ( next . allowGuestAccess ) ;
320+ } ;
321+
302322 const previewToken = chatbox ?. link ?. token ?. trim ( ) || null ;
303323 const canPreview = Boolean ( previewToken ) ;
304324 const previewName = name . trim ( ) || chatbox ?. name || "Chatbox Preview" ;
@@ -489,23 +509,6 @@ export function ChatboxEditor({
489509 chatbox ,
490510 ] ) ;
491511
492- const handleServerOptionalChange = ( serverId : string , optional : boolean ) => {
493- const requiredIds = selectedServerIds . filter (
494- ( id ) => ! optionalServerIds . includes ( id ) ,
495- ) ;
496- if ( optional && requiredIds . length === 1 && requiredIds [ 0 ] === serverId ) {
497- toast . error (
498- "Add another required server or mark another as required first." ,
499- ) ;
500- return ;
501- }
502- setOptionalServerIds ( ( current ) =>
503- optional
504- ? [ ...new Set ( [ ...current , serverId ] ) ]
505- : current . filter ( ( id ) => id !== serverId ) ,
506- ) ;
507- } ;
508-
509512 const handleToggleServer = ( serverId : string , checked : boolean ) => {
510513 setSelectedServerIds ( ( current ) => {
511514 if ( checked ) {
@@ -901,9 +904,7 @@ export function ChatboxEditor({
901904 < ServerSelectionEditor
902905 workspaceServers = { workspaceServers as RemoteServer [ ] }
903906 selectedServerIds = { selectedServerIds }
904- optionalServerIds = { optionalServerIds }
905907 onToggleSelection = { handleToggleServer }
906- onOptionalChange = { handleServerOptionalChange }
907908 onOpenAdd = { ( ) => setIsAddServerOpen ( true ) }
908909 />
909910 </ div >
@@ -976,18 +977,6 @@ export function ChatboxEditor({
976977 onCheckedChange = { setRequireToolApproval }
977978 />
978979 </ div >
979- < div className = "flex items-center justify-between gap-3 rounded-md px-1 py-1.5" >
980- < div >
981- < p className = "text-sm" > Allow guest access</ p >
982- < p className = "text-[10px] text-muted-foreground" >
983- Unauthenticated visitors can use the chatbox link.
984- </ p >
985- </ div >
986- < Switch
987- checked = { allowGuestAccess }
988- onCheckedChange = { setAllowGuestAccess }
989- />
990- </ div >
991980 </ div >
992981 </ div >
993982 </ CollapsibleContent >
@@ -1001,7 +990,11 @@ export function ChatboxEditor({
1001990 < Label className = "text-xs font-medium text-muted-foreground" >
1002991 Sharing
1003992 </ Label >
1004- < ChatboxShareSection chatbox = { chatbox } onUpdated = { onSaved } />
993+ < ChatboxShareSection
994+ chatbox = { chatbox }
995+ workspaceName = { workspaceName }
996+ onUpdated = { onSaved }
997+ />
1005998 </ div >
1006999 ) }
10071000
@@ -1012,7 +1005,9 @@ export function ChatboxEditor({
10121005 < p className = "text-sm font-medium" > General access</ p >
10131006 < div className = "mt-2 flex items-start gap-3" >
10141007 < div className = "flex size-9 shrink-0 items-center justify-center rounded-full bg-muted" >
1015- { mode === "any_signed_in_with_link" ? (
1008+ { accessPreset === "workspace" ? (
1009+ < Users className = "size-4 text-muted-foreground" />
1010+ ) : accessPreset === "link_guests" ? (
10161011 < Globe className = "size-4 text-muted-foreground" />
10171012 ) : (
10181013 < Lock className = "size-4 text-muted-foreground" />
@@ -1025,39 +1020,70 @@ export function ChatboxEditor({
10251020 type = "button"
10261021 className = "flex items-center gap-1 rounded-md px-1 py-0.5 text-sm font-medium hover:bg-muted/50 transition-colors"
10271022 >
1028- { mode === "any_signed_in_with_link"
1029- ? "Anyone with the link"
1030- : "Invited users only" }
1023+ { accessPreset === "workspace"
1024+ ? workspaceAccessLabel
1025+ : accessPreset === "link_guests"
1026+ ? "Anyone with the link (guests included)"
1027+ : "Invited users only" }
10311028 < ChevronDown className = "size-3.5 text-muted-foreground" />
10321029 </ button >
10331030 </ PopoverTrigger >
1034- < PopoverContent className = "w-56 p-1" align = "start" >
1031+ < PopoverContent className = "w-72 p-1" align = "start" >
10351032 < button
10361033 type = "button"
1037- className = "flex w-full items-center justify-between rounded-md px-2 py-1.5 text-sm hover:bg-muted/50"
1038- onClick = { ( ) => setMode ( "any_signed_in_with_link ") }
1034+ className = "flex w-full flex-col items-start gap-0.5 rounded-md px-2 py-2 text-left text-sm hover:bg-muted/50"
1035+ onClick = { ( ) => applyCreateAccessPreset ( "workspace ") }
10391036 >
1040- < span > Anyone with the link</ span >
1041- { mode === "any_signed_in_with_link" && (
1042- < Check className = "size-3.5 text-muted-foreground" />
1043- ) }
1037+ < span className = "flex w-full items-center justify-between gap-2 font-medium" >
1038+ { workspaceAccessLabel }
1039+ { accessPreset === "workspace" ? (
1040+ < Check className = "size-3.5 shrink-0 text-muted-foreground" />
1041+ ) : null }
1042+ </ span >
1043+ < span className = "text-xs text-muted-foreground" >
1044+ Signed-in workspace members can use the link. Guests
1045+ cannot.
1046+ </ span >
10441047 </ button >
10451048 < button
10461049 type = "button"
1047- className = "flex w-full items-center justify-between rounded-md px-2 py-1.5 text-sm hover:bg-muted/50"
1048- onClick = { ( ) => setMode ( "invited_only" ) }
1050+ className = "flex w-full flex-col items-start gap-0.5 rounded-md px-2 py-2 text-left text-sm hover:bg-muted/50"
1051+ onClick = { ( ) => applyCreateAccessPreset ( "invited_only" ) }
10491052 >
1050- < span > Invited users only</ span >
1051- { mode === "invited_only" && (
1052- < Check className = "size-3.5 text-muted-foreground" />
1053- ) }
1053+ < span className = "flex w-full items-center justify-between gap-2 font-medium" >
1054+ Invited users only
1055+ { accessPreset === "invited_only" ? (
1056+ < Check className = "size-3.5 shrink-0 text-muted-foreground" />
1057+ ) : null }
1058+ </ span >
1059+ < span className = "text-xs text-muted-foreground" >
1060+ Only people you invite by email can open this chatbox.
1061+ </ span >
1062+ </ button >
1063+ < button
1064+ type = "button"
1065+ className = "flex w-full flex-col items-start gap-0.5 rounded-md px-2 py-2 text-left text-sm hover:bg-muted/50"
1066+ onClick = { ( ) => applyCreateAccessPreset ( "link_guests" ) }
1067+ >
1068+ < span className = "flex w-full items-center justify-between gap-2 font-medium" >
1069+ Anyone with the link (guests included)
1070+ { accessPreset === "link_guests" ? (
1071+ < Check className = "size-3.5 shrink-0 text-muted-foreground" />
1072+ ) : null }
1073+ </ span >
1074+ < span className = "text-xs text-muted-foreground" >
1075+ Anyone with the link, including guests without an
1076+ account.
1077+ </ span >
10541078 </ button >
10551079 </ PopoverContent >
10561080 </ Popover >
10571081 < p className = "mt-0.5 px-1 text-xs text-muted-foreground" >
1058- { mode === "any_signed_in_with_link"
1059- ? "Any signed-in user with the link can open this chatbox."
1060- : "Only people you've invited can access this chatbox." }
1082+ { accessPreset === "workspace"
1083+ ? "Signed-in members of this workspace can open the chatbox with the link."
1084+ : accessPreset === "link_guests"
1085+ ? "Anyone with the link can open this chatbox, including guests."
1086+ : "Only people you invite by email can open this chatbox." }
10611087 </ p >
10621088 </ div >
10631089 </ div >
0 commit comments