diff --git a/client/src/components/Chat/Header.tsx b/client/src/components/Chat/Header.tsx index 3901a0372..5988035d2 100644 --- a/client/src/components/Chat/Header.tsx +++ b/client/src/components/Chat/Header.tsx @@ -8,7 +8,9 @@ import { useGetStartupConfig } from '~/data-provider'; import ExportAndShareMenu from './ExportAndShareMenu'; import { useMediaQuery, useHasAccess } from '~/hooks'; import BookmarkMenu from './Menus/BookmarkMenu'; +import { TemporaryChat } from './TemporaryChat'; import AddMultiConvo from './AddMultiConvo'; + const defaultInterface = getConfigDefaults().interface; export default function Header() { @@ -42,13 +44,21 @@ export default function Header() { {hasAccessToBookmarks === true && } {hasAccessToMultiConvo === true && } {isSmallScreen && ( - + <> + + + )} {!isSmallScreen && ( - +
+ + +
)} {/* Empty div for spacing */} diff --git a/client/src/components/Chat/Input/BadgeRow.tsx b/client/src/components/Chat/Input/BadgeRow.tsx index 2d0765822..14309acf1 100644 --- a/client/src/components/Chat/Input/BadgeRow.tsx +++ b/client/src/components/Chat/Input/BadgeRow.tsx @@ -9,9 +9,9 @@ import React, { } from 'react'; import { useRecoilValue, useRecoilCallback } from 'recoil'; import type { LucideIcon } from 'lucide-react'; +import type { BadgeItem } from '~/common'; import { useChatBadges } from '~/hooks'; import { Badge } from '~/components/ui'; -import { BadgeItem } from '~/common'; import store from '~/store'; interface BadgeRowProps { diff --git a/client/src/components/Chat/Input/ChatForm.tsx b/client/src/components/Chat/Input/ChatForm.tsx index 26cc3c8ce..8d8714f68 100644 --- a/client/src/components/Chat/Input/ChatForm.tsx +++ b/client/src/components/Chat/Input/ChatForm.tsx @@ -1,7 +1,7 @@ import { memo, useRef, useMemo, useEffect, useState, useCallback } from 'react'; import { useWatch } from 'react-hook-form'; import { useRecoilState, useRecoilValue } from 'recoil'; -import { isAssistantsEndpoint } from 'librechat-data-provider'; +import { Constants, isAssistantsEndpoint } from 'librechat-data-provider'; import { useChatContext, useChatFormContext, @@ -50,6 +50,7 @@ const ChatForm = memo(({ index = 0 }: { index?: number }) => { const automaticPlayback = useRecoilValue(store.automaticPlayback); const maximizeChatSpace = useRecoilValue(store.maximizeChatSpace); const centerFormOnLanding = useRecoilValue(store.centerFormOnLanding); + const isTemporary = useRecoilValue(store.isTemporary); const [badges, setBadges] = useRecoilState(store.chatBadges); const [isEditingBadges, setIsEditingBadges] = useRecoilState(store.isEditingBadges); @@ -180,7 +181,7 @@ const ChatForm = memo(({ index = 0 }: { index?: number }) => { const baseClasses = useMemo( () => cn( - 'md:py-3.5 m-0 w-full resize-none py-[13px] bg-surface-chat placeholder-black/50 dark:placeholder-white/50 [&:has(textarea:focus)]:shadow-[0_2px_6px_rgba(0,0,0,.05)]', + 'md:py-3.5 m-0 w-full resize-none py-[13px] placeholder-black/50 bg-transparent dark:placeholder-white/50 [&:has(textarea:focus)]:shadow-[0_2px_6px_rgba(0,0,0,.05)]', isCollapsed ? 'max-h-[52px]' : 'max-h-[45vh] md:max-h-[55vh]', isMoreThanThreeRows ? 'pl-5' : 'px-5', ), @@ -191,9 +192,13 @@ const ChatForm = memo(({ index = 0 }: { index?: number }) => {
@@ -219,8 +224,11 @@ const ChatForm = memo(({ index = 0 }: { index?: number }) => {
diff --git a/client/src/components/Chat/TemporaryChat.tsx b/client/src/components/Chat/TemporaryChat.tsx new file mode 100644 index 000000000..3f40c5fed --- /dev/null +++ b/client/src/components/Chat/TemporaryChat.tsx @@ -0,0 +1,69 @@ +import React from 'react'; +import { motion } from 'framer-motion'; +import { MessageCircleDashed } from 'lucide-react'; +import { useRecoilState, useRecoilCallback } from 'recoil'; +import { TooltipAnchor } from '~/components/ui'; +import { useChatContext } from '~/Providers'; +import { useLocalize } from '~/hooks'; +import { cn } from '~/utils'; +import store from '~/store'; + +export function TemporaryChat() { + const localize = useLocalize(); + const [isTemporary, setIsTemporary] = useRecoilState(store.isTemporary); + const { conversation, isSubmitting } = useChatContext(); + + const temporaryBadge = { + id: 'temporary', + icon: MessageCircleDashed, + label: 'com_ui_temporary' as const, + atom: store.isTemporary, + isAvailable: true, + }; + + const handleBadgeToggle = useRecoilCallback( + () => () => { + setIsTemporary(!isTemporary); + }, + [isTemporary], + ); + + if ( + (Array.isArray(conversation?.messages) && conversation.messages.length >= 1) || + isSubmitting + ) { + return null; + } + + return ( +
+
+ + {temporaryBadge.icon && ( + + )} + + } + /> +
+
+ ); +} diff --git a/client/src/hooks/useChatBadges.ts b/client/src/hooks/useChatBadges.ts index a6d20626f..022f3f7a6 100644 --- a/client/src/hooks/useChatBadges.ts +++ b/client/src/hooks/useChatBadges.ts @@ -5,21 +5,22 @@ import type { BadgeItem } from '~/common'; import { useLocalize } from '~/hooks'; import store from '~/store'; -const badgeConfig = [ - { - id: '1', - icon: MessageCircleDashed, - label: 'com_ui_temporary', - atom: store.isTemporary, - }, +interface ChatBadgeConfig { + id: string; + icon: typeof Box; + label: string; + atom?: any; +} + +const badgeConfig: ReadonlyArray = [ // { - // id: '2', + // id: '1', // icon: Box, // label: 'com_ui_artifacts', // atom: store.codeArtifacts, // }, // TODO: add more badges here (missing store atoms) -] as const; +]; export default function useChatBadges(): BadgeItem[] { const localize = useLocalize(); diff --git a/client/src/hooks/useNewConvo.ts b/client/src/hooks/useNewConvo.ts index 158d0f153..3054f879e 100644 --- a/client/src/hooks/useNewConvo.ts +++ b/client/src/hooks/useNewConvo.ts @@ -50,6 +50,7 @@ const useNewConvo = (index = 0) => { const assistantsListMap = useAssistantListMap(); const { pauseGlobalAudio } = usePauseGlobalAudio(index); const saveDrafts = useRecoilValue(store.saveDrafts); + const resetBadges = useResetChatBadges(); const { mutateAsync } = useDeleteFilesMutation({ onSuccess: () => { @@ -198,7 +199,7 @@ const useNewConvo = (index = 0) => { } = {}) { pauseGlobalAudio(); if (!saveBadgesState) { - useResetChatBadges(); + resetBadges(); } const templateConvoId = _template.conversationId ?? ''; @@ -278,6 +279,7 @@ const useNewConvo = (index = 0) => { files, setFiles, mutateAsync, + resetBadges, ], ); diff --git a/client/src/locales/en/translation.json b/client/src/locales/en/translation.json index 78575bfa5..9b83d9065 100644 --- a/client/src/locales/en/translation.json +++ b/client/src/locales/en/translation.json @@ -810,7 +810,7 @@ "com_ui_storage": "Storage", "com_ui_submit": "Submit", "com_ui_teach_or_explain": "Learning", - "com_ui_temporary": "Temporary", + "com_ui_temporary": "Temporary Chat", "com_ui_terms_and_conditions": "Terms and Conditions", "com_ui_terms_of_service": "Terms of service", "com_ui_thinking": "Thinking...",