Skip to content

Commit

Permalink
feat: micro
Browse files Browse the repository at this point in the history
  • Loading branch information
YuChanGongzhu committed Nov 27, 2024
1 parent d8914b2 commit 287c61d
Show file tree
Hide file tree
Showing 3 changed files with 160 additions and 53 deletions.
127 changes: 98 additions & 29 deletions components/MainUI/Action/Action.tsx
Original file line number Diff line number Diff line change
@@ -1,49 +1,103 @@
import React, { useState, useEffect } from "react";
import React, { useState, useEffect, useRef } from "react";
import Image from "next/image";
import HandIcon from "@/assets/icons/v2/hand.svg";
import MicroIcon from "@/assets/icons/v2/micro.svg";
import GameIcon from "@/assets/icons/v2/game.svg";
import { authApis } from "@/app/normalApi";
import { useRouter } from "next/navigation";
import { Loader } from "lucide-react";
import router from "next/router";

interface ActionProps {
fetchUserData: () => void;
setIsPetting: (isPetting: boolean) => void;
petPet: () => void;
onVoiceMessage?: (text: string) => void;
handleSend: (text: string) => void;
setMessage: (message: string) => void;
}

export default function Action({
fetchUserData,
setIsPetting,
petPet,
}: {
fetchUserData: () => void;
setIsPetting: (isPetting: boolean) => void;
petPet: () => void;
}) {
const [isMicro, setIsMicro] = useState(true);
onVoiceMessage,
handleSend,
setMessage,
}: ActionProps) {
const [isRecording, setIsRecording] = useState(false);
const [isProcessing, setIsProcessing] = useState(false);
const [dots, setDots] = useState(".");
const recognition = useRef<any>(null);
const lastTranscript = useRef<string>("");

const handlePetTouch = async () => {
const initializeRecognition = () => {
const SpeechRecognition =
(window as any).SpeechRecognition ||
(window as any).webkitSpeechRecognition;
recognition.current = new SpeechRecognition();
recognition.current.continuous = true;
recognition.current.interimResults = true;
recognition.current.lang = "en-US";

recognition.current.onresult = (event: any) => {
const transcript = Array.from(event.results)
.map((result: any) => result[0])
.map((result: any) => result.transcript)
.join("");

console.log("Transcript:", transcript);
setMessage(transcript);
lastTranscript.current = transcript;
};

recognition.current.onend = () => {
if (!isRecording) {
setIsProcessing(true);
setMessage("");
if (lastTranscript.current && onVoiceMessage) {
onVoiceMessage(lastTranscript.current);
}
setTimeout(() => {
setIsProcessing(false);
}, 50);
}
};
};

const startRecording = async () => {
try {
setIsPetting(true);
// const response = await authApis.touchPet();
const response = await petPet();
console.log("touch pet success", response);
fetchUserData();
setIsPetting(false);
// console.log("touch pet success", response.data);
initializeRecognition();
lastTranscript.current = "";
recognition.current.start();
setIsRecording(true);
} catch (error) {
console.error("touch pet error", error);
console.error("Error starting recognition:", error);
setIsProcessing(false);
}
};

const router = useRouter();
const stopRecording = () => {
if (recognition.current && isRecording) {
setIsRecording(false);
if (lastTranscript.current) handleSend(lastTranscript.current);
recognition.current.stop();
recognition.current = null;
}
};

// 处理点击事件
const handleClick = () => {
setIsMicro(!isMicro);
const handleToggleRecording = () => {
if (isRecording) {
stopRecording();
} else {
startRecording();
}
};

// 当 isMicro 为 false 时,处理点的动画
// 处理点的动画
useEffect(() => {
let interval: NodeJS.Timeout;

if (!isMicro) {
if (isRecording) {
interval = setInterval(() => {
setDots((prev) => {
if (prev === ".") return "..";
Expand All @@ -52,17 +106,30 @@ export default function Action({
});
}, 500);
}

return () => {
if (interval) clearInterval(interval);
};
}, [isMicro]);
}, [isRecording]);

const handlePetTouch = async () => {
try {
setIsPetting(true);
// const response = await authApis.touchPet();
const response = await petPet();
console.log("touch pet success", response);
fetchUserData();
setIsPetting(false);
// console.log("touch pet success", response.data);
} catch (error) {
console.error("touch pet error", error);
}
};

return (
<div className="relative h-32 w-full mb-6">
<div className="absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2">
<div
onClick={handleClick}
onClick={handleToggleRecording}
className={`
w-12 h-12
flex items-center justify-center
Expand All @@ -72,10 +139,12 @@ export default function Action({
cursor-pointer
`}
>
{isMicro ? (
<Image src={MicroIcon} alt="Micro" className="w-10 h-10" />
) : (
{isProcessing ? (
<Loader className="w-8 h-8 text-white animate-spin" />
) : isRecording ? (
<span className="text-white text-xs font-bold">{dots}</span>
) : (
<Image src={MicroIcon} alt="Micro" className="w-10 h-10" />
)}
</div>
</div>
Expand Down
54 changes: 54 additions & 0 deletions components/MainUI/Init.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ import { useSolanaProvider, usePublicKey } from "@/solana/provider";
import { showTxErrorModal } from "@/utils/solana";
import TxError from "../SolanaPopups/TxError";
import InitializeGameAccount from "../SolanaPopups/Initialize";
import { extractKeywords, findRelatedEmojis } from "@/utils/emojiUtils";
import { callOpenRouterAPI, separateEmojisAndText } from "@/utils/reply";

export type PageState = "chat" | "shop" | "info" | "user";

Expand Down Expand Up @@ -45,6 +47,11 @@ export default function Init({
const { publicKey } = usePublicKey();
const { provider } = useSolanaProvider();

const [messages, setMessages] = useState([
{ text: "🐶 🐶 🥰 Hi!", isMe: false },
]);
const [message, setMessage] = useState("");

useEffect(() => {
console.log("publicKey changed", publicKey);
}, [publicKey]);
Expand Down Expand Up @@ -231,6 +238,47 @@ export default function Init({
}
};

const handleSend = async (voiceText?: string) => {
// 使用 voiceText 或 message
const textToSend = voiceText || message;

if (textToSend.trim()) {
const newMessages = [...messages, { text: textToSend, isMe: true }];
setMessages(newMessages);
localStorage.setItem("chatMessages", JSON.stringify(newMessages));
setMessage("");

try {
setLoading(true);
const raw_reply = await callOpenRouterAPI(textToSend);
const { reply_text, reply_emojis } = separateEmojisAndText(raw_reply);
setLoading(false);
setEmojisContent(reply_emojis.join(" "));

const updatedMessages = [
...newMessages,
{
text: reply_text,
// text: "Sorry, I'm having trouble connecting to the server. Please try again later.",
isMe: false,
},
];
setMessages(updatedMessages);
localStorage.setItem("chatMessages", JSON.stringify(updatedMessages));

fetchUserData();
} catch (error) {
console.error("发送消息失败:", error);
const keywords = extractKeywords(textToSend);
const localEmojis = await findRelatedEmojis(keywords);
const replyEmojis = localEmojis.join(" ");

setLoading(false);
setEmojisContent(replyEmojis);
}
}
};

const renderPage = () => {
switch (currentPage) {
case "chat":
Expand All @@ -240,6 +288,10 @@ export default function Init({
setLoading={setLoading}
fetchUserData={fetchUserData}
setEmojisContent={setEmojisContent}
messages={messages}
setMessages={setMessages}
message={message}
setMessage={setMessage}
/>
);
case "shop":
Expand Down Expand Up @@ -289,6 +341,8 @@ export default function Init({
fetchUserData={fetchUserData}
setIsPetting={setIsPetting}
petPet={petPet}
handleSend={handleSend}
setMessage={setMessage}
/>
);
}
Expand Down
32 changes: 8 additions & 24 deletions components/MainUI/SlideUI/ChatPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,21 @@ export default function ChatPage({
setLoading,
fetchUserData,
setEmojisContent,
messages,
setMessages,
message,
setMessage,
}: {
loading: boolean;
setLoading: (loading: boolean) => void;
fetchUserData: () => void;
setEmojisContent: (emojisContent: string) => void;
messages: any[];
setMessages: (messages: any[]) => void;
message: string;
setMessage: (message: string) => void;
}) {
const { navHeight } = useNavHeight();
const [message, setMessage] = useState("");
const [messages, setMessages] = useState([
{ text: "🐶 🐶 🥰 Hi!", isMe: false },
]);

useEffect(() => {
const savedMessages = localStorage.getItem("chatMessages");
Expand All @@ -43,26 +47,6 @@ export default function ChatPage({
setMessage("");

try {
// setLoading(true);
// const response = await authApis.getReply(textToSend);
// let replyEmojis = response.data.data.emojis;
// let replyText = response.data.data.response;

// if (!replyEmojis) {
// const keywords = extractKeywords(message);
// const localEmojis = await findRelatedEmojis(keywords);
// replyEmojis = localEmojis.join(" ");
// }

// setLoading(false);
// setEmojisContent(replyEmojis);
// const updatedMessages = [
// ...newMessages,
// { text: replyText, isMe: false },
// ];
// setMessages(updatedMessages);
// localStorage.setItem("chatMessages", JSON.stringify(updatedMessages));

setLoading(true);
const raw_reply = await callOpenRouterAPI(textToSend);
const { reply_text, reply_emojis } = separateEmojisAndText(raw_reply);
Expand Down

0 comments on commit 287c61d

Please sign in to comment.