diff --git a/src/app/globals.scss b/src/app/globals.scss index f18b2be5..d2756489 100644 --- a/src/app/globals.scss +++ b/src/app/globals.scss @@ -386,7 +386,7 @@ body { } .scroll-button { - bottom: 5rem; + bottom: 4rem; z-index: 100; @media (max-width: 767px) { diff --git a/src/components/chat-history.tsx b/src/components/chat-history.tsx index 34dad7d4..43002b33 100644 --- a/src/components/chat-history.tsx +++ b/src/components/chat-history.tsx @@ -2,6 +2,9 @@ import { useCallback, useEffect, useState } from 'react' import { useChatHistory, ChatConversation } from '@/lib/hooks/chat-history' import { IconEdit, IconTrash, IconDownload, IconCheck, IconClose } from './ui/icons' import { cn, formatDate } from '@/lib/utils' +import { useAtomValue } from 'jotai' +import { historyAtom } from '@/state' +import { debug } from '@/lib/isomorphic' interface ConversationTheadProps { conversation: ChatConversation @@ -71,8 +74,11 @@ export function ConversationThead({ conversation, onRename, onDelete, onUpdate, } export function ChatHistory({ className, onExpaned }: { className?: string, onExpaned: (flag: boolean) => void }) { - const { chatHistory, refreshChats, deleteChat, renameChat, updateMessage, downloadMessage } = useChatHistory() + const historyEnabled = useAtomValue(historyAtom) + const { chatHistory, refreshChats, deleteChat, renameChat, updateMessage, downloadMessage } = useChatHistory(historyEnabled) useEffect(() => { + debug('historyEnabled', historyEnabled) + if (!historyEnabled) return refreshChats() .then(res =>{ if (res?.chats.length > 0) { diff --git a/src/components/settings.tsx b/src/components/settings.tsx index 80b8a2d3..097c004e 100644 --- a/src/components/settings.tsx +++ b/src/components/settings.tsx @@ -1,8 +1,8 @@ -import { useEffect, useState } from 'react' +import { useCallback, useEffect, useState } from 'react' import { useAtom } from 'jotai' import { Switch } from '@headlessui/react' import { toast } from 'react-hot-toast' -import { hashAtom, voiceAtom } from '@/state' +import { hashAtom, historyAtom, voiceAtom } from '@/state' import { Dialog, DialogContent, @@ -23,6 +23,7 @@ export function Settings() { const [loc, setLoc] = useAtom(hashAtom) const [curlValue, setCurlValue] = useState(extraCurlFromCookie(parseCookies(document.cookie, ChunkKeys))) const [imageOnly, setImageOnly] = useState(getCookie('IMAGE_ONLY') !== '0') + const [enabledHistory, setHistory] = useAtom(historyAtom) const [enableTTS, setEnableTTS] = useAtom(voiceAtom) useEffect(() => { @@ -31,6 +32,24 @@ export function Settings() { } }, [isCopied]) + const handleSwitchImageOnly = useCallback((checked: boolean) => { + let headerValue = curlValue + if (headerValue) { + try { + headerValue = atob(headerValue) + } catch (e) { } + if (!/^\s*curl ['"]https:\/\/(www|cn)\.bing\.com\/turing\/captcha\/challenge['"]/.test(headerValue)) { + toast.error('请先配置链接') + return + } + if (RegExp.$1 === 'cn' && checked === false) { + toast.error('你配置的中文域名 cn.bing.com 仅支持画图') + return + } + setImageOnly(checked) + } + }, [curlValue]) + if (loc === 'settings') { return ( setLoc('')} modal> @@ -61,18 +80,33 @@ export function Settings() { onChange={e => setCurlValue(e.target.value)} />
- 身份信息仅用于画图(推荐) setImageOnly(checked)} + onChange={(checked: boolean) => handleSwitchImageOnly(checked)} > + 身份信息仅用于画图
+ {!imageOnly && ( +
+ setHistory(checked)} + > + + + 启用历史记录 +
+ )} + diff --git a/src/lib/hooks/chat-history.ts b/src/lib/hooks/chat-history.ts index c6327a03..478c0cc6 100644 --- a/src/lib/hooks/chat-history.ts +++ b/src/lib/hooks/chat-history.ts @@ -22,7 +22,7 @@ export interface ChatHistory { } const proxyEndpoint = '/api/proxy' -const fetchProxy = (data: any) => { +const fetchProxy = (data: any, showError = true) => { return fetch(proxyEndpoint, { method: 'POST', headers: { @@ -31,13 +31,15 @@ const fetchProxy = (data: any) => { credentials: 'include', body: JSON.stringify(data), }).then(res => res.json()).catch(e => { - toast.error('Failed to operation') + if (showError) { + toast.error('Failed to operation') + } throw e }) } -export function useChatHistory(botId = 'bing') { - const chatAtom = useMemo(() => chatFamily({ botId: 'bing', page: 'singleton' }), [botId]) +export function useChatHistory(historyEnabled: boolean) { + const chatAtom = useMemo(() => chatFamily({ botId: 'bing', page: 'singleton' }), ['bing']) const [chatState, setChatState] = useAtom(chatAtom) const [chatHistory, setHistory] = useState() @@ -157,20 +159,18 @@ export function useChatHistory(botId = 'bing') { const data = await fetchProxy({ url: 'https://www.bing.com/turing/conversation/chats', method: 'GET', - }).catch(e => { - console.log(e) - return - }) + }, false) setHistory(data || {}) return data }, []) useEffect(() => { - if (chatState.generatingMessageId === '') { + if (!historyEnabled) return + if (chatState.generatingMessageId === '' && [3, 2].includes(chatState.messages.length)) { debug('refresh history') refreshChats() } - }, [chatState.generatingMessageId, chatState.messages?.[1]?.text]) + }, [historyEnabled, chatState.generatingMessageId, chatState.messages.length]) return { chatHistory, diff --git a/src/state/index.ts b/src/state/index.ts index d3a2265b..4c788b9c 100644 --- a/src/state/index.ts +++ b/src/state/index.ts @@ -26,6 +26,7 @@ export const GreetMessages = [ export const bingConversationStyleAtom = atomWithStorage('bingConversationStyle', BingConversationStyle.Balanced, undefined, { unstable_getOnInit: true }) export const voiceAtom = atomWithStorage('enableTTS', false, undefined, { unstable_getOnInit: true }) +export const historyAtom = atomWithStorage('enableHistory', false, undefined, { unstable_getOnInit: true }) type Param = { botId: BotId; page: string }