From 6578e2cf53308075ed944b253d4169a584ee7acd Mon Sep 17 00:00:00 2001 From: agrim saxena Date: Sun, 17 Dec 2023 17:00:00 +0530 Subject: [PATCH 1/2] enhancement-implemented --- src/components/settings.tsx | 6 +- src/components/settings/common.tsx | 10 +- src/components/shareModal.tsx | 716 +++++++++++++++++++++++++++++ src/pages/index.tsx | 20 +- 4 files changed, 738 insertions(+), 14 deletions(-) create mode 100644 src/components/shareModal.tsx diff --git a/src/components/settings.tsx b/src/components/settings.tsx index a1f5641a..8b7fe0f7 100644 --- a/src/components/settings.tsx +++ b/src/components/settings.tsx @@ -23,7 +23,7 @@ import { ViewerContext } from "@/features/vrmViewer/viewerContext"; import { config, updateConfig } from "@/utils/config"; -import { Link } from "./settings/common"; +import { CustomLink } from "./settings/common"; import { MenuPage } from './settings/MenuPage'; import { ResetSettingsPage } from './settings/ResetSettingsPage'; @@ -68,7 +68,7 @@ export const Settings = ({ useKeyboardShortcut("Escape", onClickClose); const [page, setPage] = useState('main_menu'); - const [breadcrumbs, setBreadcrumbs] = useState([]); + const [breadcrumbs, setBreadcrumbs] = useState([]); const [showNotification, setShowNotification] = useState(false); const [settingsUpdated, setSettingsUpdated] = useState(false); @@ -218,7 +218,7 @@ export const Settings = ({ ]); - function handleMenuClick(link: Link) { + function handleMenuClick(link: CustomLink) { setPage(link.key) setBreadcrumbs([...breadcrumbs, link]); } diff --git a/src/components/settings/common.tsx b/src/components/settings/common.tsx index 2d81afc3..ba4b606a 100644 --- a/src/components/settings/common.tsx +++ b/src/components/settings/common.tsx @@ -90,7 +90,7 @@ export function thumbPrefix(path: string) { return a.join("/"); } -export type Link = { +export type CustomLink = { key: string; label: string; icon?: JSX.Element; @@ -106,8 +106,8 @@ export function getLinkFromPage(page: string) { }; } -export function pagesToLinks(keys: string[]): Link[] { - const links: Link[] = []; +export function pagesToLinks(keys: string[]): CustomLink[] { + const links: CustomLink[] = []; for (const key of keys) { links.push(getLinkFromPage(key)); } @@ -116,8 +116,8 @@ export function pagesToLinks(keys: string[]): Link[] { export type PageProps = { setPage: (page: string) => void; - breadcrumbs: Link[]; - setBreadcrumbs: (breadcrumbs: Link[]) => void; + breadcrumbs: CustomLink[]; + setBreadcrumbs: (breadcrumbs: CustomLink[]) => void; } export function getIconFromPage(page: string): JSX.Element { diff --git a/src/components/shareModal.tsx b/src/components/shareModal.tsx new file mode 100644 index 00000000..3350a8e3 --- /dev/null +++ b/src/components/shareModal.tsx @@ -0,0 +1,716 @@ +import React, { + Fragment, + useCallback, + useContext, + useEffect, + useState, + useRef, + } from "react"; + import { Transition } from '@headlessui/react' + import { + ArrowUturnLeftIcon, + XMarkIcon, + } from '@heroicons/react/20/solid'; + + import { CheckCircleIcon } from '@heroicons/react/24/outline'; + + import { useKeyboardShortcut } from "@/hooks/useKeyboardShortcut"; + import { IconButton } from "@/components/iconButton"; + import { TextButton } from "@/components/textButton"; + import { ViewerContext } from "@/features/vrmViewer/viewerContext"; + import { config, updateConfig } from "@/utils/config"; + + import { FilePond, registerPlugin } from 'react-filepond'; + import { createHash } from 'crypto'; + + import FilePondPluginImagePreview from 'filepond-plugin-image-preview'; + import FilePondPluginFileValidateType from 'filepond-plugin-file-validate-type'; + import VrmDemo from "@/components/vrmDemo"; + import { loadVRMAnimation } from "@/lib/VRMAnimation/loadVRMAnimation"; + + import 'filepond/dist/filepond.min.css'; + import 'filepond-plugin-image-preview/dist/filepond-plugin-image-preview.css'; + + + import { CustomLink } from "./settings/common"; +import isTauri from "@/utils/isTauri"; +import { t } from "i18next"; +import Link from "next/dist/client/link"; + + registerPlugin( + FilePondPluginImagePreview, + FilePondPluginFileValidateType, + ); + + async function hashFile(file: File): Promise { + const buffer = await file.arrayBuffer(); + const hashValue = createHash('sha256') + .update(Buffer.from(buffer)) + .digest('hex'); + return hashValue; + } + + async function updateVrmAvatar(viewer: any, url: string) { + try { + await viewer.loadVrm(url); + } catch (e) { + console.error(e); + } + } + + function vrmDetector(source: File, type: string): Promise { + return new Promise((resolve, reject) => { + console.log(source); + (async () => { + const ab = await source.arrayBuffer(); + const buf = Buffer.from(ab); + if (buf.slice(0, 4).toString() === "glTF") { + resolve("model/gltf-binary"); + } else { + resolve("unknown"); + } + })(); + }) + } + + export const ShareModal = ({ + + onClickClose, + }: { + onClickClose: () => void; + }) => { + const { viewer } = useContext(ViewerContext); + useKeyboardShortcut("Escape", onClickClose); + + const [page, setPage] = useState('main_menu'); + const [breadcrumbs, setBreadcrumbs] = useState([]); + const [showNotification, setShowNotification] = useState(false); + const [settingsUpdated, setSettingsUpdated] = useState(false); + + const [chatbotBackend, setChatbotBackend] = useState(config("chatbot_backend")); + const [openAIApiKey, setOpenAIApiKey] = useState(config("openai_apikey")); + const [openAIUrl, setOpenAIUrl] = useState(config("openai_url")); + const [openAIModel, setOpenAIModel] = useState(config("openai_model")); + const [llamaCppUrl, setLlamaCppUrl] = useState(config("llamacpp_url")); + const [ollamaUrl, setOllamaUrl] = useState(config("ollama_url")); + const [ollamaModel, setOllamaModel] = useState(config("ollama_model")); + const [koboldAiUrl, setKoboldAiUrl] = useState(config("koboldai_url")); + const [koboldAiUseExtra, setKoboldAiUseExtra] = useState(config("koboldai_use_extra") === 'true' ? true : false); + + const [ttsBackend, setTTSBackend] = useState(config("tts_backend")); + const [elevenlabsApiKey, setElevenlabsApiKey] = useState(config("elevenlabs_apikey")); + const [elevenlabsVoiceId, setElevenlabsVoiceId] = useState(config("elevenlabs_voiceid")); + + const [speechT5SpeakerEmbeddingsUrl, setSpeechT5SpeakerEmbeddingsUrl] = useState(config("speecht5_speaker_embedding_url")); + + const [coquiApiKey, setCoquiApiKey] = useState(config("coqui_apikey")); + const [coquiVoiceId, setCoquiVoiceId] = useState(config("coqui_voice_id")); + + const [openAITTSApiKey, setOpenAITTSApiKey] = useState(config("openai_tts_apikey")); + const [openAITTSUrl, setOpenAITTSUrl] = useState(config("openai_tts_url")); + const [openAITTSModel, setOpenAITTSModel] = useState(config("openai_tts_model")); + const [openAITTSVoice, setOpenAITTSVoice] = useState(config("openai_tts_voice")); + + const [visionBackend, setVisionBackend] = useState(config("vision_backend")); + const [visionLlamaCppUrl, setVisionLlamaCppUrl] = useState(config("vision_llamacpp_url")); + const [visionOllamaUrl, setVisionOllamaUrl] = useState(config("vision_ollama_url")); + const [visionOllamaModel, setVisionOllamaModel] = useState(config("vision_ollama_model")); + + const [bgColor, setBgColor] = useState(config("bg_color")); + const [youtubeVideoID, setYoutubeVideoID] = useState(config("youtube_videoid")); + + const [sttBackend, setSTTBackend] = useState(config("stt_backend")); + const [whisperOpenAIUrl, setWhisperOpenAIUrl] = useState(config("openai_whisper_url")); + const [whisperOpenAIApiKey, setWhisperOpenAIApiKey] = useState(config("openai_whisper_apikey")); + const [whisperOpenAIModel, setWhisperOpenAIModel] = useState(config("openai_whisper_model")); + const [whisperCppUrl, setWhisperCppUrl] = useState(config("whispercpp_url")); + + const [name, setName] = useState(config("name")); + const [systemPrompt, setSystemPrompt] = useState(config("system_prompt")); + const [description, setDescription] = useState(''); + const [isRegistering, setIsRegistering] = useState(false); + const [visionSystemPrompt, setVisionSystemPrompt] = useState(''); + const [bgUrl, setBgUrl] = useState(''); + const [youtubeVideoId, setYoutubeVideoId] = useState(''); + const [voiceUrl, setVoiceUrl] = useState(''); + + const [bgFiles, setBgFiles] = useState([]); + const [vrmFiles, setVrmFiles] = useState([]); + const [animationFiles, setAnimationFiles] = useState([]); + const [voiceFiles, setVoiceFiles] = useState([]); + const [vrmUrl, setVrmUrl] = useState(''); + const [animationUrl, setAnimationUrl] = useState(''); + + const [vrmLoaded, setVrmLoaded] = useState(false); + + const [sqid, setSqid] = useState(''); + + useEffect(() => { + setName(config('name')); + setSystemPrompt(config('system_prompt')); + setVisionSystemPrompt(config('vision_system_prompt')); + if (! config('bg_url').startsWith('data')) { + setBgUrl(config('bg_url')); + } + setYoutubeVideoId(config('youtube_videoid')); + setVrmUrl(config('vrm_url')); + setAnimationUrl(config('animation_url')); + setVoiceUrl(config('voice_url')); + }, []); + + function registerCharacter() { + setIsRegistering(true); + + async function register() { + const res = await fetch(`${process.env.NEXT_PUBLIC_AMICA_API_URL}/api/add_character`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + description, + name, + system_prompt: systemPrompt, + vision_system_prompt: visionSystemPrompt, + bg_url: bgUrl, + youtube_videoid: youtubeVideoId, + vrm_url: vrmUrl, + animation_url: animationUrl, + voice_url: voiceUrl, + }), + }); + + const data = await res.json(); + console.log('response', data); + + setSqid(data.sqid); + + setIsRegistering(false); + } + + register(); + } + + + const vrmFileInputRef = useRef(null); + const handleClickOpenVrmFile = useCallback(() => { + vrmFileInputRef.current?.click(); + }, []); + + const bgImgFileInputRef = useRef(null); + const handleClickOpenBgImgFile = useCallback(() => { + bgImgFileInputRef.current?.click(); + }, []); + + + + useEffect(() => { + const timeOutId = setTimeout(() => { + if (settingsUpdated) { + setShowNotification(true); + setTimeout(() => { + setShowNotification(false); + }, 5000); + } + }, 1000); + return () => clearTimeout(timeOutId); + }, [ + chatbotBackend, + openAIApiKey, openAIUrl, openAIModel, + llamaCppUrl, + ollamaUrl, ollamaModel, + koboldAiUrl, koboldAiUseExtra, + ttsBackend, + elevenlabsApiKey, elevenlabsVoiceId, + speechT5SpeakerEmbeddingsUrl, + coquiApiKey, coquiVoiceId, + openAITTSApiKey, openAITTSUrl, openAITTSModel, openAITTSVoice, + visionBackend, + visionLlamaCppUrl, + visionOllamaUrl, visionOllamaModel, + visionSystemPrompt, + bgColor, + bgUrl, vrmUrl, youtubeVideoID, animationUrl, + sttBackend, + whisperOpenAIApiKey, whisperOpenAIModel, whisperOpenAIUrl, + whisperCppUrl, + name, + systemPrompt, + ]); + + + function renderPage() { + return ( +
+
+

{t("Character Creator")}

+ { isTauri() && ( +

+ {t("Wrong place?")} + {' '} + {t('Go home')} +

+ ) } +
+ +
+
+
+ +
+