From e2680e3f96e8934dc2d1750a8735a37c968c7196 Mon Sep 17 00:00:00 2001 From: MasonTao <yingchun_tao@163.com> Date: Tue, 11 Jun 2024 14:18:34 +0800 Subject: [PATCH] fix: fix subdmain bugs --- components/Chat/Chat.tsx | 2 +- components/Chat/SystemNodes.tsx | 25 +- components/Settings/QueryUrl.tsx | 130 ++--- hooks/useHost.ts | 6 + pages/api/home/home.tsx | 935 +++++++++++++++++-------------- 5 files changed, 577 insertions(+), 521 deletions(-) diff --git a/components/Chat/Chat.tsx b/components/Chat/Chat.tsx index d6f812f..8dc5ee1 100644 --- a/components/Chat/Chat.tsx +++ b/components/Chat/Chat.tsx @@ -535,7 +535,7 @@ export const Chat = memo(({ stopConversationRef }: Props) => { ref={chatContainerRef} onScroll={handleScroll} > - <div className="sticky z-10 top-0 flex w-full items-center justify-end gap-3 h-[84px] bg-white border-b border-[rgba(0,0,0,0.15)] pr-5"> + <div className="sticky z-10 top-0 flex w-full items-center justify-end gap-3 h-[84px] bg-white border-b border-[rgba(0,0,0,0.15)] pl-4 md:pl-0 pr-4 md:pr-5"> {/* <div className="inline-flex items-center justify-center rounded-lg px-3 h-[44px] text-[13px] bg-white text-black border border-[rgba(0, 0, 0, 0.08)] cursor-pointer hover:border-black transition-all"> <p>{selectedConversation?.model?.id || defaultModelId}</p> </div> */} diff --git a/components/Chat/SystemNodes.tsx b/components/Chat/SystemNodes.tsx index 60256d3..bd46844 100644 --- a/components/Chat/SystemNodes.tsx +++ b/components/Chat/SystemNodes.tsx @@ -8,8 +8,6 @@ import React, { useState, } from 'react'; -import { useRouter } from 'next/router'; - import { dappHosts } from '@/hooks/useHost'; import HomeContext from '@/pages/api/home/home.context'; @@ -18,10 +16,9 @@ const SystemNodes: React.FC = () => { const [tippyInstance, setTippyInstance] = useState<any>(null); const [nodes, setNodes] = useState<any[]>([]); const [searchWords, setSearchWords] = useState(''); - const { query } = useRouter(); const { - state: { api, selectedConversation, defaultModelId }, + state: { api, selectedConversation, modelError }, dispatch: homeDispatch, } = useContext(HomeContext); @@ -66,22 +63,6 @@ const SystemNodes: React.FC = () => { fetchNodes(); }, [channelIsDapp]); - useEffect(() => { - if (typeof window === 'undefined' || !channelIsDapp) return; - if (query?.subdomain) { - handleApiChange(`https://${query?.subdomain}`); - } else { - if (api === '' || api === '..') { - const host = window.location.host; - if (host === 'gaianet.ai' || host === 'www.gaianet.ai') { - handleApiChange(`https://knowledge.gaianet.network`); - } else { - handleApiChange(`https://knowledge.gaianet.xyz`); - } - } - } - }, [api, channelIsDapp, handleApiChange, query?.subdomain]); - const handleSearch = (e: any) => { setSearchWords(e.target.value || ''); }; @@ -173,13 +154,13 @@ const SystemNodes: React.FC = () => { onCreate={(instance) => setTippyInstance(instance)} className="gaianet-tippy" > - <div className="inline-flex items-center justify-between rounded-lg gap-3 px-3 w-[405px] h-[44px] text-[13px] bg-white text-black border border-[rgba(0, 0, 0, 0.08)] cursor-pointer hover:border-black transition-all"> + <div className="inline-flex items-center justify-between rounded-lg gap-3 px-3 w-auto md:min-w-[405px] h-[44px] text-[13px] bg-white text-black border border-[rgba(0, 0, 0, 0.08)] cursor-pointer hover:border-black transition-all"> <div className="flex flex-col"> <p className="text-[13px] leading-[16px] "> {selectedModelSubdomin || '-'} </p> <p className="text-[10px] leading-[13px] uppercase mt-[2px] text-[#888888]"> - {selectedConversation?.model?.id || defaultModelId} + {modelError ? '-' : selectedConversation?.model?.id} </p> </div> <IconChevronDown size="18" color="#C0C0C0" /> diff --git a/components/Settings/QueryUrl.tsx b/components/Settings/QueryUrl.tsx index 37ef7fb..76f4f3e 100644 --- a/components/Settings/QueryUrl.tsx +++ b/components/Settings/QueryUrl.tsx @@ -1,79 +1,81 @@ -import {IconCheck, IconLink, IconX} from '@tabler/icons-react'; -import {FC, KeyboardEvent, useEffect, useRef, useState} from 'react'; +import { IconCheck, IconLink, IconX } from '@tabler/icons-react'; +import { FC, KeyboardEvent, useEffect, useRef, useState } from 'react'; -import {useTranslation} from 'next-i18next'; +import { useTranslation } from 'next-i18next'; -import {SidebarButton} from '../Sidebar/SidebarButton'; +import { SidebarButton } from '../Sidebar/SidebarButton'; interface Props { - api: string; - onApiChange: (apiKey: string) => void; + api: string; + onApiChange: (apiKey: string) => void; } -export const QueryUrl: FC<Props> = ({api, onApiChange}) => { - const {t} = useTranslation('sidebar'); - const [isChanging, setIsChanging] = useState(false); - const [newKey, setNewKey] = useState(api); - const inputRef = useRef<HTMLInputElement>(null); +export const QueryUrl: FC<Props> = ({ api, onApiChange }) => { + const { t } = useTranslation('sidebar'); + const [isChanging, setIsChanging] = useState(false); +// const [newKey, setNewKey] = useState(api); + const inputRef = useRef<HTMLInputElement>(null); - const handleEnterDown = (e: KeyboardEvent<HTMLDivElement>) => { - if (e.key === 'Enter') { - e.preventDefault(); - handleUpdateKey(newKey); - } - }; + const handleEnterDown = (e: KeyboardEvent<HTMLDivElement>) => { + if (e.key === 'Enter') { + e.preventDefault(); + if (inputRef.current?.value) + handleUpdateKey(inputRef.current?.value?.trim()); + } + }; - const handleUpdateKey = (newKey: string) => { - onApiChange(newKey.trim()); - setIsChanging(false); - }; + const handleUpdateKey = (newKey: string) => { + onApiChange(newKey.trim()); + setIsChanging(false); + }; - useEffect(() => { - if (isChanging) { - inputRef.current?.focus(); - } - }, [isChanging]); + useEffect(() => { + if (isChanging) { + inputRef.current?.focus(); + } + }, [isChanging]); - return isChanging ? ( - <div - className="duration:200 flex w-full cursor-pointer items-center rounded-md py-[11px] px-4 transition-colors hover:bg-gray-500/10"> - <IconLink size={18} color="#322221" /> + return isChanging ? ( + <div className="duration:200 flex w-full cursor-pointer items-center rounded-md py-[11px] px-4 transition-colors hover:bg-gray-500/10"> + <IconLink size={18} color="#322221" /> - <input - ref={inputRef} - className="ml-2 h-[20px] flex-1 overflow-hidden overflow-ellipsis border-b border-neutral-400 bg-transparent pr-1 text-[12.5px] leading-3 text-left text-[#322221] outline-none focus:border-neutral-100" - value={newKey} - onChange={(e) => setNewKey(e.target.value)} - onKeyDown={handleEnterDown} - placeholder={t('API Url') || 'API Url'} - /> + <input + ref={inputRef} + className="ml-2 h-[20px] flex-1 overflow-hidden overflow-ellipsis border-b border-neutral-400 bg-transparent pr-1 text-[12.5px] leading-3 text-left text-[#322221] outline-none focus:border-neutral-100" + // value={newKey} + defaultValue={api} + // onChange={(e) => setNewKey(e.target.value)} + onKeyDown={handleEnterDown} + placeholder={t('API Url') || 'API Url'} + /> - <div className="flex w-[40px]"> - <IconCheck - className="ml-auto min-w-[20px] text-neutral-400 hover:text-[#322221]" - size={18} - onClick={(e) => { - e.stopPropagation(); - handleUpdateKey(newKey); - }} - /> + <div className="flex w-[40px]"> + <IconCheck + className="ml-auto min-w-[20px] text-neutral-400 hover:text-[#322221]" + size={18} + onClick={(e) => { + e.stopPropagation(); + if (inputRef.current?.value) + handleUpdateKey(inputRef.current?.value?.trim()); + }} + /> - <IconX - className="ml-auto min-w-[20px] text-neutral-400 hover:text-[#322221]" - size={18} - onClick={(e) => { - e.stopPropagation(); - setIsChanging(false); - setNewKey(api); - }} - /> - </div> - </div> - ) : ( - <SidebarButton - text={t('Chat API Url')} - icon={<IconLink size={18}/>} - onClick={() => setIsChanging(true)} + <IconX + className="ml-auto min-w-[20px] text-neutral-400 hover:text-[#322221]" + size={18} + onClick={(e) => { + e.stopPropagation(); + setIsChanging(false); + // setNewKey(api); + }} /> - ); + </div> + </div> + ) : ( + <SidebarButton + text={t('Chat API Url')} + icon={<IconLink size={18} />} + onClick={() => setIsChanging(true)} + /> + ); }; diff --git a/hooks/useHost.ts b/hooks/useHost.ts index e16008c..7be5814 100644 --- a/hooks/useHost.ts +++ b/hooks/useHost.ts @@ -24,3 +24,9 @@ export const dappHosts = [ apiUrl: 'https://api.gaianet-test.link/', }, ]; + +export const useChannelIsPortal = () => { + if (typeof window === 'undefined') return false; + const host = window.location.host; + if (dappHosts.find((item) => item?.host === host)) return true; +}; diff --git a/pages/api/home/home.tsx b/pages/api/home/home.tsx index 96e0bd1..04fa871 100644 --- a/pages/api/home/home.tsx +++ b/pages/api/home/home.tsx @@ -1,499 +1,566 @@ -import {useEffect, useRef} from 'react'; +import { useCallback, useEffect, useRef } from 'react'; -import {GetStaticProps} from 'next'; -import {useTranslation} from 'next-i18next'; -import {serverSideTranslations} from 'next-i18next/serverSideTranslations'; +import { GetStaticProps } from 'next'; +import { useTranslation } from 'next-i18next'; +import { serverSideTranslations } from 'next-i18next/serverSideTranslations'; import Head from 'next/head'; +import { useRouter } from 'next/router'; -import {useCreateReducer} from '@/hooks/useCreateReducer'; -import useApiService from '@/services/useApiService'; - -import {cleanConversationHistory, cleanSelectedConversation,} from '@/utils/app/clean'; -import {DEFAULT_TEMPERATURE} from '@/utils/app/const'; -import {saveConversation, saveConversations, updateConversation,} from '@/utils/app/conversation'; -import {saveFolders} from '@/utils/app/folders'; -import {savePrompts} from '@/utils/app/prompts'; -import {getSettings} from '@/utils/app/settings'; +import { useCreateReducer } from '@/hooks/useCreateReducer'; +import { useChannelIsPortal } from '@/hooks/useHost'; -import {Conversation} from '@/types/chat'; -import {KeyValuePair} from '@/types/data'; -import {FolderInterface, FolderType} from '@/types/folder'; -import {fallbackModelID, OpenAIModel, OpenAIModelID} from '@/types/openai'; -import {Prompt} from '@/types/prompt'; +import useApiService from '@/services/useApiService'; -import {Chat} from '@/components/Chat/Chat'; -import {Chatbar} from '@/components/Chatbar/Chatbar'; -import {Navbar} from '@/components/Mobile/Navbar'; +import { + cleanConversationHistory, + cleanSelectedConversation, +} from '@/utils/app/clean'; +import { DEFAULT_TEMPERATURE } from '@/utils/app/const'; +import { + saveConversation, + saveConversations, + updateConversation, +} from '@/utils/app/conversation'; +import { saveFolders } from '@/utils/app/folders'; +import { savePrompts } from '@/utils/app/prompts'; +import { getSettings } from '@/utils/app/settings'; + +import { Conversation } from '@/types/chat'; +import { KeyValuePair } from '@/types/data'; +import { FolderInterface, FolderType } from '@/types/folder'; +import { OpenAIModel, OpenAIModelID, fallbackModelID } from '@/types/openai'; +import { Prompt } from '@/types/prompt'; + +import { Chat } from '@/components/Chat/Chat'; +import { promptsList } from '@/components/Chat/PromptsList'; +import { Chatbar } from '@/components/Chatbar/Chatbar'; +import { Navbar } from '@/components/Mobile/Navbar'; import HomeContext from './home.context'; -import {HomeInitialState, initialState} from './home.state'; +import { HomeInitialState, initialState } from './home.state'; -import {v4 as uuidv4} from 'uuid'; -import {promptsList} from "@/components/Chat/PromptsList"; +import { v4 as uuidv4 } from 'uuid'; interface Props { - serverSideApiKeyIsSet: boolean; - serverSidePluginKeysSet: boolean; - defaultModelId: OpenAIModelID; + serverSideApiKeyIsSet: boolean; + serverSidePluginKeysSet: boolean; + defaultModelId: OpenAIModelID; } interface DispatchData { - id: String; - name: String | null; - messages: []; - model?: Object; - prompt?: String; - promptState?: Number; - temperature: Number; - folderId: String | null; + id: String; + name: String | null; + messages: []; + model?: Object; + prompt?: String; + promptState?: Number; + temperature: Number; + folderId: String | null; } const Home = ({ - serverSideApiKeyIsSet, - serverSidePluginKeysSet, - defaultModelId, - }: Props) => { - const {t} = useTranslation('chat'); - const {getModels} = useApiService(); - - const contextValue = useCreateReducer<HomeInitialState>({ - initialState, - }); - - const { - state: { - api, - apiKey, - lightMode, - folders, - conversations, - selectedConversation, - prompts, - modelError, - models - }, - dispatch, - } = contextValue; - - const stopConversationRef = useRef<boolean>(false); - - const getData = async () => { - try { - const data = await getModels( - { - url: api, - key: apiKey, - }, - ); - if (dispatch) { - dispatch({field: 'models', value: data}); - } - } catch (e) { - if (dispatch && !modelError) { - dispatch({field: 'modelError', value: {code: "500", title: "false", messageLines: []}}); - } - console.log(e) - } - } - - useEffect(() => { - if (models && (!conversations || conversations && conversations.length === 0) && handleNewConversation) { - handleNewConversation() - } - }, [models]) - - useEffect(() => { - if (typeof window !== 'undefined' && api) { - getData() - } - }, [api]) - - // FETCH MODELS ---------------------------------------------- - - const handleSelectConversation = (conversation: Conversation) => { + serverSideApiKeyIsSet, + serverSidePluginKeysSet, + defaultModelId, +}: Props) => { + const { t } = useTranslation('chat'); + const { getModels } = useApiService(); + const { query } = useRouter(); + const channelIsPortal = useChannelIsPortal(); + + const contextValue = useCreateReducer<HomeInitialState>({ + initialState, + }); + + const { + state: { + api, + apiKey, + lightMode, + folders, + conversations, + selectedConversation, + prompts, + modelError, + models, + }, + dispatch, + } = contextValue; + + const stopConversationRef = useRef<boolean>(false); + + const getData = async () => { + try { + const data = await getModels({ + url: api, + key: apiKey, + }); + if (dispatch) { + dispatch({ field: 'models', value: data }); dispatch({ - field: 'selectedConversation', - value: conversation, + field: 'modelError', + value: null, }); - - saveConversation(conversation); - }; - - // FOLDER OPERATIONS -------------------------------------------- - - function checkObjectExistence(objectList: OpenAIModel[], object: OpenAIModel): boolean { - for (let obj of objectList) { - if (obj.id === object.id) { - return true; - } - } - return false; + } + } catch (e) { + if (dispatch && !modelError) { + dispatch({ + field: 'modelError', + value: { code: '500', title: 'false', messageLines: [] }, + }); + } + console.log(e); } + }; + + useEffect(() => { + if ( + models && + (!conversations || (conversations && conversations.length === 0)) && + handleNewConversation + ) { + handleNewConversation(); + } + }, [models]); - const handleCreateFolder = async (name: string, type: FolderType) => { - const newFolder: FolderInterface = { - id: uuidv4(), - name, - type, - }; - - const updatedFolders = [...folders, newFolder]; + useEffect(() => { + if (typeof window !== 'undefined' && api) { + getData(); + } + }, [api]); - dispatch({field: 'folders', value: updatedFolders}); - saveFolders(updatedFolders); - }; + // FETCH MODELS ---------------------------------------------- - const handleDeleteFolder = (folderId: string) => { - const updatedFolders = folders.filter((f) => f.id !== folderId); - dispatch({field: 'folders', value: updatedFolders}); - saveFolders(updatedFolders); + const handleSelectConversation = (conversation: Conversation) => { + dispatch({ + field: 'selectedConversation', + value: conversation, + }); - const updatedConversations: Conversation[] = conversations.map((c) => { - if (c.folderId === folderId) { - return { - ...c, - folderId: null, - }; - } + saveConversation(conversation); + }; - return c; - }); + // FOLDER OPERATIONS -------------------------------------------- - dispatch({field: 'conversations', value: updatedConversations}); - saveConversations(updatedConversations); + function checkObjectExistence( + objectList: OpenAIModel[], + object: OpenAIModel, + ): boolean { + for (let obj of objectList) { + if (obj.id === object.id) { + return true; + } + } + return false; + } + + const handleCreateFolder = async (name: string, type: FolderType) => { + const newFolder: FolderInterface = { + id: uuidv4(), + name, + type, + }; - const updatedPrompts: Prompt[] = prompts.map((p) => { - if (p.folderId === folderId) { - return { - ...p, - folderId: null, - }; - } + const updatedFolders = [...folders, newFolder]; - return p; - }); + dispatch({ field: 'folders', value: updatedFolders }); + saveFolders(updatedFolders); + }; - dispatch({field: 'prompts', value: updatedPrompts}); - savePrompts(updatedPrompts); - }; + const handleDeleteFolder = (folderId: string) => { + const updatedFolders = folders.filter((f) => f.id !== folderId); + dispatch({ field: 'folders', value: updatedFolders }); + saveFolders(updatedFolders); - const handleUpdateFolder = (folderId: string, name: string) => { - const updatedFolders = folders.map((f) => { - if (f.id === folderId) { - return { - ...f, - name, - }; - } + const updatedConversations: Conversation[] = conversations.map((c) => { + if (c.folderId === folderId) { + return { + ...c, + folderId: null, + }; + } - return f; - }); + return c; + }); - dispatch({field: 'folders', value: updatedFolders}); + dispatch({ field: 'conversations', value: updatedConversations }); + saveConversations(updatedConversations); - saveFolders(updatedFolders); - }; + const updatedPrompts: Prompt[] = prompts.map((p) => { + if (p.folderId === folderId) { + return { + ...p, + folderId: null, + }; + } - // CONVERSATION OPERATIONS -------------------------------------------- - - const handleNewConversation = async () => { - await getData() - const lastConversation = conversations[conversations.length - 1]; - let getPrompt - if (models && models.length > 0) { - await fetch('/config_pub.json') - .then(response => response.json()) - .then(data => { - getPrompt = data.system_prompt; - }) - .catch(error => console.error('Error fetching JSON:', error)); - const newConversation: Conversation = { - id: uuidv4(), - name: t('New Conversation'), - messages: [], - model: (lastConversation?.model && checkObjectExistence(models, lastConversation?.model) && lastConversation?.model) || models[0], - prompt: getPrompt || promptsList.find(prompt => - prompt.id?.toLowerCase() === models[0].name?.toLowerCase() - )?.content || "", - promptState: promptsList.find(prompt => - prompt.id?.toLowerCase() === models[0].name?.toLowerCase() - )?.controlState || 0, - temperature: lastConversation?.temperature ?? DEFAULT_TEMPERATURE, - folderId: null, - }; - - const updatedConversations = [...conversations, newConversation]; - - dispatch({field: 'selectedConversation', value: newConversation}); - dispatch({field: 'conversations', value: updatedConversations}); - - saveConversation(newConversation); - saveConversations(updatedConversations); - - dispatch({field: 'loading', value: false}); - } + return p; + }); - }; + dispatch({ field: 'prompts', value: updatedPrompts }); + savePrompts(updatedPrompts); + }; - const handleUpdateConversation = ( - conversation: Conversation, - data: KeyValuePair, - ) => { - const updatedConversation = { - ...conversation, - [data.key]: data.value, + const handleUpdateFolder = (folderId: string, name: string) => { + const updatedFolders = folders.map((f) => { + if (f.id === folderId) { + return { + ...f, + name, }; + } - const {single, all} = updateConversation( - updatedConversation, - conversations, - ); + return f; + }); - dispatch({field: 'selectedConversation', value: single}); - dispatch({field: 'conversations', value: all}); + dispatch({ field: 'folders', value: updatedFolders }); + + saveFolders(updatedFolders); + }; + + // CONVERSATION OPERATIONS -------------------------------------------- + + const handleNewConversation = async () => { + await getData(); + const lastConversation = conversations[conversations.length - 1]; + let getPrompt; + if (models && models.length > 0) { + await fetch('/config_pub.json') + .then((response) => response.json()) + .then((data) => { + getPrompt = data.system_prompt; + }) + .catch((error) => console.error('Error fetching JSON:', error)); + const newConversation: Conversation = { + id: uuidv4(), + name: t('New Conversation'), + messages: [], + model: + (lastConversation?.model && + checkObjectExistence(models, lastConversation?.model) && + lastConversation?.model) || + models[0], + prompt: + getPrompt || + promptsList.find( + (prompt) => + prompt.id?.toLowerCase() === models[0].name?.toLowerCase(), + )?.content || + '', + promptState: + promptsList.find( + (prompt) => + prompt.id?.toLowerCase() === models[0].name?.toLowerCase(), + )?.controlState || 0, + temperature: lastConversation?.temperature ?? DEFAULT_TEMPERATURE, + folderId: null, + }; + + const updatedConversations = [...conversations, newConversation]; + + dispatch({ field: 'selectedConversation', value: newConversation }); + dispatch({ field: 'conversations', value: updatedConversations }); + + saveConversation(newConversation); + saveConversations(updatedConversations); + + dispatch({ field: 'loading', value: false }); + } + }; + + const handleUpdateConversation = ( + conversation: Conversation, + data: KeyValuePair, + ) => { + const updatedConversation = { + ...conversation, + [data.key]: data.value, }; - const handleUpdateConversationAll = ( - conversation: Conversation, - data: KeyValuePair[], - ) => { - const updatedConversation = Object.assign(conversation) - data.forEach(item => { - updatedConversation[item.key] = item.value - } - ) - - const {single, all} = updateConversation( - updatedConversation, - conversations, - ); - - dispatch({field: 'selectedConversation', value: single}); - dispatch({field: 'conversations', value: all}); - }; + const { single, all } = updateConversation( + updatedConversation, + conversations, + ); - // EFFECTS -------------------------------------------- + dispatch({ field: 'selectedConversation', value: single }); + dispatch({ field: 'conversations', value: all }); + }; + + const handleUpdateConversationAll = ( + conversation: Conversation, + data: KeyValuePair[], + ) => { + const updatedConversation = Object.assign(conversation); + data.forEach((item) => { + updatedConversation[item.key] = item.value; + }); - useEffect(() => { - if (window.innerWidth < 640) { - dispatch({field: 'showChatbar', value: false}); - } - }, [selectedConversation]); + const { single, all } = updateConversation( + updatedConversation, + conversations, + ); - useEffect(() => { - serverSideApiKeyIsSet && - dispatch({ - field: 'serverSideApiKeyIsSet', - value: serverSideApiKeyIsSet, - }); - serverSidePluginKeysSet && - dispatch({ - field: 'serverSidePluginKeysSet', - value: serverSidePluginKeysSet, - }); - }, [serverSideApiKeyIsSet, serverSidePluginKeysSet]); + dispatch({ field: 'selectedConversation', value: single }); + dispatch({ field: 'conversations', value: all }); + }; - // ON LOAD -------------------------------------------- + // EFFECTS -------------------------------------------- - useEffect(() => { - const settings = getSettings(); - if (settings.theme) { - dispatch({ - field: 'lightMode', - value: settings.theme, - }); - } - if (settings.isStream) { - dispatch({ - field: 'isStream', - value: settings.isStream, - }); - } + useEffect(() => { + if (window.innerWidth < 640) { + dispatch({ field: 'showChatbar', value: false }); + } + }, [selectedConversation]); + + useEffect(() => { + serverSideApiKeyIsSet && + dispatch({ + field: 'serverSideApiKeyIsSet', + value: serverSideApiKeyIsSet, + }); + serverSidePluginKeysSet && + dispatch({ + field: 'serverSidePluginKeysSet', + value: serverSidePluginKeysSet, + }); + }, [serverSideApiKeyIsSet, serverSidePluginKeysSet]); + + // ON LOAD -------------------------------------------- + + useEffect(() => { + const settings = getSettings(); + if (settings.theme) { + dispatch({ + field: 'lightMode', + value: settings.theme, + }); + } + if (settings.isStream) { + dispatch({ + field: 'isStream', + value: settings.isStream, + }); + } - const api = localStorage.getItem('api'); - const apiKey = localStorage.getItem('apiKey'); + const apiKey = localStorage.getItem('apiKey'); - if (serverSideApiKeyIsSet) { - dispatch({field: 'apiKey', value: ''}); + if (serverSideApiKeyIsSet) { + dispatch({ field: 'apiKey', value: '' }); - localStorage.removeItem('apiKey'); - } else if (apiKey) { - dispatch({field: 'apiKey', value: apiKey}); - } + localStorage.removeItem('apiKey'); + } else if (apiKey) { + dispatch({ field: 'apiKey', value: apiKey }); + } - if (api) { - dispatch({field: 'api', value: api}); - } + const pluginKeys = localStorage.getItem('pluginKeys'); + if (serverSidePluginKeysSet) { + dispatch({ field: 'pluginKeys', value: [] }); + localStorage.removeItem('pluginKeys'); + } else if (pluginKeys) { + dispatch({ field: 'pluginKeys', value: pluginKeys }); + } - const pluginKeys = localStorage.getItem('pluginKeys'); - if (serverSidePluginKeysSet) { - dispatch({field: 'pluginKeys', value: []}); - localStorage.removeItem('pluginKeys'); - } else if (pluginKeys) { - dispatch({field: 'pluginKeys', value: pluginKeys}); - } + if (window.innerWidth < 640) { + dispatch({ field: 'showChatbar', value: false }); + } - if (window.innerWidth < 640) { - dispatch({field: 'showChatbar', value: false}); - } + const showChatbar = localStorage.getItem('showChatbar'); + if (showChatbar) { + dispatch({ field: 'showChatbar', value: showChatbar === 'true' }); + } - const showChatbar = localStorage.getItem('showChatbar'); - if (showChatbar) { - dispatch({field: 'showChatbar', value: showChatbar === 'true'}); - } + const folders = localStorage.getItem('folders'); + if (folders) { + dispatch({ field: 'folders', value: JSON.parse(folders) }); + } - const folders = localStorage.getItem('folders'); - if (folders) { - dispatch({field: 'folders', value: JSON.parse(folders)}); - } + const prompts = localStorage.getItem('prompts'); + if (prompts) { + dispatch({ field: 'prompts', value: JSON.parse(prompts) }); + } - const prompts = localStorage.getItem('prompts'); - if (prompts) { - dispatch({field: 'prompts', value: JSON.parse(prompts)}); - } + const conversationHistory = localStorage.getItem('conversationHistory'); + if (conversationHistory) { + const parsedConversationHistory: Conversation[] = + JSON.parse(conversationHistory); + const cleanedConversationHistory = cleanConversationHistory( + parsedConversationHistory, + ); - const conversationHistory = localStorage.getItem('conversationHistory'); - if (conversationHistory) { - const parsedConversationHistory: Conversation[] = - JSON.parse(conversationHistory); - const cleanedConversationHistory = cleanConversationHistory( - parsedConversationHistory, - ); + dispatch({ field: 'conversations', value: cleanedConversationHistory }); + } - dispatch({field: 'conversations', value: cleanedConversationHistory}); + const selectedConversation = localStorage.getItem('selectedConversation'); + if (selectedConversation) { + const parsedSelectedConversation: Conversation = + JSON.parse(selectedConversation); + const cleanedSelectedConversation = cleanSelectedConversation( + parsedSelectedConversation, + ); + + if (cleanedSelectedConversation.model && models && models.length > 0) { + const haveThisSelectedModels = models.filter( + (model) => model.id === cleanedSelectedConversation.model.id, + ); + if (!haveThisSelectedModels || haveThisSelectedModels.length === 0) { + cleanedSelectedConversation.model = models[0]; + cleanedSelectedConversation.prompt = + promptsList.find( + (prompt) => + prompt.id?.toLowerCase() === models[0]?.name?.toLowerCase(), + )?.content || ''; + cleanedSelectedConversation.promptState = + promptsList.find( + (prompt) => + prompt.id?.toLowerCase() === models[0]?.name?.toLowerCase(), + )?.controlState || 0; } + } + + dispatch({ + field: 'selectedConversation', + value: cleanedSelectedConversation, + }); + } else { + const lastConversation = conversations[conversations.length - 1]; + let dispatchData: DispatchData = { + id: uuidv4(), + name: t('New Conversation'), + messages: [], + temperature: lastConversation?.temperature ?? DEFAULT_TEMPERATURE, + folderId: null, + }; + if (models && models.length > 0) { + dispatchData.model = models[0]; + dispatchData.prompt = + promptsList.find( + (prompt) => + prompt.id?.toLowerCase() === models[0]?.name?.toLowerCase(), + )?.content || ''; + dispatchData.promptState = + promptsList.find( + (prompt) => + prompt.id?.toLowerCase() === models[0]?.name?.toLowerCase(), + )?.controlState || 0; + } + dispatch({ + field: 'selectedConversation', + value: dispatchData, + }); + } + }, [dispatch, models, serverSideApiKeyIsSet, serverSidePluginKeysSet]); + + useEffect(() => { + const localStorageApi = localStorage.getItem('api'); + if (query?.subdomain && channelIsPortal) { + dispatch({ field: 'api', value: `https://${query?.subdomain}` }); + localStorage.setItem('api', `https://${query?.subdomain}`); + return; + } - const selectedConversation = localStorage.getItem('selectedConversation'); - if (selectedConversation) { - const parsedSelectedConversation: Conversation = - JSON.parse(selectedConversation); - const cleanedSelectedConversation = cleanSelectedConversation( - parsedSelectedConversation, - ); - - if (cleanedSelectedConversation.model && models && models.length > 0) { - const haveThisSelectedModels = models.filter(model => model.id === cleanedSelectedConversation.model.id) - if (!haveThisSelectedModels || haveThisSelectedModels.length === 0) { - cleanedSelectedConversation.model = models[0] - cleanedSelectedConversation.prompt = promptsList.find(prompt => - prompt.id?.toLowerCase() === models[0]?.name?.toLowerCase() - )?.content || "" - cleanedSelectedConversation.promptState = promptsList.find(prompt => - prompt.id?.toLowerCase() === models[0]?.name?.toLowerCase() - )?.controlState || 0 - } - } - - dispatch({ - field: 'selectedConversation', - value: cleanedSelectedConversation, - }); + if (localStorageApi) + return dispatch({ field: 'api', value: localStorageApi }); + + if (!localStorageApi) { + if (channelIsPortal) { + const host = window.location.host; + if (host === 'gaianet.ai' || host === 'www.gaianet.ai') { + dispatch({ + field: 'api', + value: 'https://knowledge.gaianet.network', + }); + localStorage.setItem('api', 'https://knowledge.gaianet.network'); } else { - const lastConversation = conversations[conversations.length - 1]; - let dispatchData: DispatchData = { - id: uuidv4(), - name: t('New Conversation'), - messages: [], - temperature: lastConversation?.temperature ?? DEFAULT_TEMPERATURE, - folderId: null, - } - if (models && models.length > 0) { - dispatchData.model = models[0] - dispatchData.prompt = promptsList.find(prompt => - prompt.id?.toLowerCase() === models[0]?.name?.toLowerCase() - )?.content || "" - dispatchData.promptState = promptsList.find(prompt => - prompt.id?.toLowerCase() === models[0]?.name?.toLowerCase() - )?.controlState || 0 - } - dispatch({ - field: 'selectedConversation', value: dispatchData - }); + dispatch({ field: 'api', value: 'https://knowledge.gaianet.xyz' }); + localStorage.setItem('api', 'https://knowledge.gaianet.xyz'); + } + } else { + const host = window.location.host; + if (!host.startsWith('localhost')) { + dispatch({ field: 'api', value: `https://${host}` }); + localStorage.setItem('api', `https://${host}`); } - }, [ - dispatch, - models, - serverSideApiKeyIsSet, - serverSidePluginKeysSet, - ]); - - return ( - <HomeContext.Provider - value={{ - ...contextValue, - handleNewConversation, - handleCreateFolder, - handleDeleteFolder, - handleUpdateFolder, - handleSelectConversation, - handleUpdateConversation, - handleUpdateConversationAll - }} + } + } + }, [channelIsPortal, dispatch, query?.subdomain]); + + return ( + <HomeContext.Provider + value={{ + ...contextValue, + handleNewConversation, + handleCreateFolder, + handleDeleteFolder, + handleUpdateFolder, + handleSelectConversation, + handleUpdateConversation, + handleUpdateConversationAll, + }} + > + <Head> + <title>GaiaNet</title> + <meta name="description" content="ChatGPT but better." /> + <meta + name="viewport" + content="height=device-height ,width=device-width, initial-scale=1, user-scalable=no" + /> + <link rel="icon" href="./favicon.png" /> + </Head> + {selectedConversation && ( + <main + className={`flex h-screen w-screen flex-col text-sm text-white dark:text-white ${lightMode}`} > - <Head> - <title>GaiaNet</title> - <meta name="description" content="ChatGPT but better."/> - <meta - name="viewport" - content="height=device-height ,width=device-width, initial-scale=1, user-scalable=no" - /> - <link rel="icon" href="./favicon.png"/> - </Head> - {selectedConversation && ( - <main - className={`flex h-screen w-screen flex-col text-sm text-white dark:text-white ${lightMode}`} - > - <div className="fixed top-0 w-full sm:hidden "> - <Navbar - selectedConversation={selectedConversation} - onNewConversation={handleNewConversation} - /> - </div> - - <div className="flex h-full w-full pt-[49px] sm:pt-0"> - <Chatbar/> - - <div className="flex flex-1"> - <Chat stopConversationRef={stopConversationRef}/> - </div> - </div> - </main> - )} - </HomeContext.Provider> - ); + <div className="fixed top-0 w-full sm:hidden "> + <Navbar + selectedConversation={selectedConversation} + onNewConversation={handleNewConversation} + /> + </div> + + <div className="flex h-full w-full pt-[49px] sm:pt-0"> + <Chatbar /> + + <div className="flex flex-1"> + <Chat stopConversationRef={stopConversationRef} /> + </div> + </div> + </main> + )} + </HomeContext.Provider> + ); }; export default Home; -export const getStaticProps: GetStaticProps = async ({locale}) => { - const defaultModelId = - (process.env.DEFAULT_MODEL && - Object.values(OpenAIModelID).includes( - process.env.DEFAULT_MODEL as OpenAIModelID, - ) && - process.env.DEFAULT_MODEL) || - fallbackModelID; - - let serverSidePluginKeysSet = false; - - const googleApiKey = process.env.GOOGLE_API_KEY; - const googleCSEId = process.env.GOOGLE_CSE_ID; - - if (googleApiKey && googleCSEId) { - serverSidePluginKeysSet = true; - } - - return { - props: { - serverSideApiKeyIsSet: !!process.env.OPENAI_API_KEY, - defaultModelId, - serverSidePluginKeysSet, - ...(await serverSideTranslations(locale ?? 'en', [ - 'common', - 'chat', - 'sidebar', - 'markdown', - 'settings', - ])), - }, - }; +export const getStaticProps: GetStaticProps = async ({ locale }) => { + const defaultModelId = + (process.env.DEFAULT_MODEL && + Object.values(OpenAIModelID).includes( + process.env.DEFAULT_MODEL as OpenAIModelID, + ) && + process.env.DEFAULT_MODEL) || + fallbackModelID; + + let serverSidePluginKeysSet = false; + + const googleApiKey = process.env.GOOGLE_API_KEY; + const googleCSEId = process.env.GOOGLE_CSE_ID; + + if (googleApiKey && googleCSEId) { + serverSidePluginKeysSet = true; + } + + return { + props: { + serverSideApiKeyIsSet: !!process.env.OPENAI_API_KEY, + defaultModelId, + serverSidePluginKeysSet, + ...(await serverSideTranslations(locale ?? 'en', [ + 'common', + 'chat', + 'sidebar', + 'markdown', + 'settings', + ])), + }, + }; };