fix: support setting visibility on initial chat creation (#975)

This commit is contained in:
Jeremy 2025-05-01 17:47:48 -07:00 committed by GitHub
parent a3221fbcdc
commit 575c12503c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
15 changed files with 158 additions and 32 deletions

View file

@ -27,6 +27,7 @@ import { sheetArtifact } from '@/artifacts/sheet/client';
import { textArtifact } from '@/artifacts/text/client';
import equal from 'fast-deep-equal';
import type { UseChatHelpers } from '@ai-sdk/react';
import type { VisibilityType } from './visibility-selector';
export const artifactDefinitions = [
textArtifact,
@ -66,6 +67,7 @@ function PureArtifact({
reload,
votes,
isReadonly,
selectedVisibilityType,
}: {
chatId: string;
input: string;
@ -81,6 +83,7 @@ function PureArtifact({
handleSubmit: UseChatHelpers['handleSubmit'];
reload: UseChatHelpers['reload'];
isReadonly: boolean;
selectedVisibilityType: VisibilityType;
}) {
const { artifact, setArtifact, metadata, setMetadata } = useArtifact();
@ -335,6 +338,7 @@ function PureArtifact({
append={append}
className="bg-background dark:bg-muted"
setMessages={setMessages}
selectedVisibilityType={selectedVisibilityType}
/>
</form>
</div>
@ -503,6 +507,8 @@ export const Artifact = memo(PureArtifact, (prevProps, nextProps) => {
if (!equal(prevProps.votes, nextProps.votes)) return false;
if (prevProps.input !== nextProps.input) return false;
if (!equal(prevProps.messages, nextProps.messages.length)) return false;
if (prevProps.selectedVisibilityType !== nextProps.selectedVisibilityType)
return false;
return true;
});

View file

@ -17,26 +17,32 @@ import { getChatHistoryPaginationKey } from './sidebar-history';
import { toast } from './toast';
import type { Session } from 'next-auth';
import { useSearchParams } from 'next/navigation';
import { useChatVisibility } from '@/hooks/use-chat-visibility';
export function Chat({
id,
initialMessages,
selectedChatModel,
selectedVisibilityType,
initialChatModel,
initialVisibilityType,
isReadonly,
session,
autoResume,
}: {
id: string;
initialMessages: Array<UIMessage>;
selectedChatModel: string;
selectedVisibilityType: VisibilityType;
initialChatModel: string;
initialVisibilityType: VisibilityType;
isReadonly: boolean;
session: Session;
autoResume: boolean;
}) {
const { mutate } = useSWRConfig();
const { visibilityType } = useChatVisibility({
chatId: id,
initialVisibilityType,
});
const {
messages,
setMessages,
@ -57,7 +63,8 @@ export function Chat({
experimental_prepareRequestBody: (body) => ({
id,
message: body.messages.at(-1),
selectedChatModel,
selectedChatModel: initialChatModel,
selectedVisibilityType: visibilityType,
}),
onFinish: () => {
mutate(unstable_serialize(getChatHistoryPaginationKey));
@ -109,8 +116,8 @@ export function Chat({
<div className="flex flex-col min-w-0 h-dvh bg-background">
<ChatHeader
chatId={id}
selectedModelId={selectedChatModel}
selectedVisibilityType={selectedVisibilityType}
selectedModelId={initialChatModel}
selectedVisibilityType={initialVisibilityType}
isReadonly={isReadonly}
session={session}
/>
@ -140,6 +147,7 @@ export function Chat({
messages={messages}
setMessages={setMessages}
append={append}
selectedVisibilityType={visibilityType}
/>
)}
</form>
@ -160,6 +168,7 @@ export function Chat({
reload={reload}
votes={votes}
isReadonly={isReadonly}
selectedVisibilityType={visibilityType}
/>
</>
);

View file

@ -26,6 +26,7 @@ import type { UseChatHelpers } from '@ai-sdk/react';
import { AnimatePresence, motion } from 'framer-motion';
import { ArrowDown } from 'lucide-react';
import { useScrollToBottom } from '@/hooks/use-scroll-to-bottom';
import type { VisibilityType } from './visibility-selector';
function PureMultimodalInput({
chatId,
@ -40,6 +41,7 @@ function PureMultimodalInput({
append,
handleSubmit,
className,
selectedVisibilityType,
}: {
chatId: string;
input: UseChatHelpers['input'];
@ -53,6 +55,7 @@ function PureMultimodalInput({
append: UseChatHelpers['append'];
handleSubmit: UseChatHelpers['handleSubmit'];
className?: string;
selectedVisibilityType: VisibilityType;
}) {
const textareaRef = useRef<HTMLTextAreaElement>(null);
const { width } = useWindowSize();
@ -220,7 +223,11 @@ function PureMultimodalInput({
{messages.length === 0 &&
attachments.length === 0 &&
uploadQueue.length === 0 && (
<SuggestedActions append={append} chatId={chatId} />
<SuggestedActions
append={append}
chatId={chatId}
selectedVisibilityType={selectedVisibilityType}
/>
)}
<input
@ -309,6 +316,8 @@ export const MultimodalInput = memo(
if (prevProps.input !== nextProps.input) return false;
if (prevProps.status !== nextProps.status) return false;
if (!equal(prevProps.attachments, nextProps.attachments)) return false;
if (prevProps.selectedVisibilityType !== nextProps.selectedVisibilityType)
return false;
return true;
},

View file

@ -1,4 +1,4 @@
import { Chat } from '@/lib/db/schema';
import type { Chat } from '@/lib/db/schema';
import {
SidebarMenuAction,
SidebarMenuButton,
@ -39,7 +39,7 @@ const PureChatItem = ({
}) => {
const { visibilityType, setVisibilityType } = useChatVisibility({
chatId: chat.id,
initialVisibility: chat.visibility,
initialVisibilityType: chat.visibility,
});
return (

View file

@ -3,14 +3,20 @@
import { motion } from 'framer-motion';
import { Button } from './ui/button';
import { memo } from 'react';
import { UseChatHelpers } from '@ai-sdk/react';
import type { UseChatHelpers } from '@ai-sdk/react';
import type { VisibilityType } from './visibility-selector';
interface SuggestedActionsProps {
chatId: string;
append: UseChatHelpers['append'];
selectedVisibilityType: VisibilityType;
}
function PureSuggestedActions({ chatId, append }: SuggestedActionsProps) {
function PureSuggestedActions({
chatId,
append,
selectedVisibilityType,
}: SuggestedActionsProps) {
const suggestedActions = [
{
title: 'What are the advantages',
@ -71,4 +77,13 @@ function PureSuggestedActions({ chatId, append }: SuggestedActionsProps) {
);
}
export const SuggestedActions = memo(PureSuggestedActions, () => true);
export const SuggestedActions = memo(
PureSuggestedActions,
(prevProps, nextProps) => {
if (prevProps.chatId !== nextProps.chatId) return false;
if (prevProps.selectedVisibilityType !== nextProps.selectedVisibilityType)
return false;
return true;
},
);

View file

@ -1,6 +1,6 @@
'use client';
import { ReactNode, useMemo, useState } from 'react';
import { type ReactNode, useMemo, useState } from 'react';
import { Button } from '@/components/ui/button';
import {
DropdownMenu,
@ -9,7 +9,6 @@ import {
DropdownMenuTrigger,
} from '@/components/ui/dropdown-menu';
import { cn } from '@/lib/utils';
import {
CheckCircleFillIcon,
ChevronDownIcon,
@ -52,7 +51,7 @@ export function VisibilitySelector({
const { visibilityType, setVisibilityType } = useChatVisibility({
chatId,
initialVisibility: selectedVisibilityType,
initialVisibilityType: selectedVisibilityType,
});
const selectedVisibility = useMemo(
@ -70,6 +69,7 @@ export function VisibilitySelector({
)}
>
<Button
data-testid="visibility-selector"
variant="outline"
className="hidden md:flex md:px-2 md:h-[34px]"
>
@ -82,6 +82,7 @@ export function VisibilitySelector({
<DropdownMenuContent align="start" className="min-w-[300px]">
{visibilities.map((visibility) => (
<DropdownMenuItem
data-testid={`visibility-selector-item-${visibility.id}`}
key={visibility.id}
onSelect={() => {
setVisibilityType(visibility.id);