gbclient/app/chat/providers/chat-provider.tsx

112 lines
No EOL
3.3 KiB
TypeScript

"use client";
import React, { createContext, useContext, useState, useEffect } from 'react';
import { User, ChatInstance } from '../types';
interface ChatContextType {
line: any;
user: User;
instance: ChatInstance | null;
sendActivity: (activity: any) => Promise<void>;
selectedVoice: any;
setVoice: (voice: any) => void;
}
const ChatContext = createContext<ChatContextType | undefined>(undefined);
// Unified API caller that works in both environments
async function apiFetch(endpoint: string, options?: RequestInit) {
const baseUrl = 'http://localhost:4242/'; //typeof window !== 'undefined' ? window.location.origin : '';
if (typeof window !== 'undefined' && '__TAURI__' in window) {
// Tauri environment - use HTTP module for better security
const { http } = await import('@tauri-apps/api');
return http.fetch(`${baseUrl}${endpoint}`, options);
}
// Web environment - standard fetch
return fetch(`${baseUrl}${endpoint}`, options);
}
export function ChatProvider({ children }: { children: React.ReactNode }) {
const [line, setLine] = useState<any>(null);
const [instance, setInstance] = useState<ChatInstance | null>(null);
const [selectedVoice, setSelectedVoice] = useState(null);
const [user] = useState<User>({
id: `user_${Math.random().toString(36).slice(2)}`,
name: 'You'
});
useEffect(() => {
const initializeChat = async () => {
try {
const botId = 'doula'; // window.location.pathname.split('/')[1] || 'default';
// Get instance from REST API
const response = await apiFetch(`/instances/${botId}`);
if (!response.ok) throw new Error('Failed to get chat instance');
const instanceData = await response.json();
setInstance(instanceData);
// Initialize chat service
const chatService = {
activity$: { subscribe: () => {} },
postActivity: (activity: any) => ({
subscribe: (observer: any) => {
// Handle real-time updates if needed
return { unsubscribe: () => {} };
}
})
};
setLine(chatService);
} catch (error) {
console.error('Failed to initialize chat:', error);
}
};
initializeChat();
}, []);
const sendActivity = async (activity: any) => {
try {
const fullActivity = {
...activity,
from: user,
timestamp: new Date().toISOString()
};
// Send activity via REST API
const response = await apiFetch('/activities', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(fullActivity)
});
if (!response.ok) throw new Error('Failed to send activity');
// Notify local chat service
line?.postActivity(fullActivity).subscribe();
} catch (error) {
console.error('Failed to send activity:', error);
}
};
const setVoice = (voice: any) => {
setSelectedVoice(voice);
};
return (
<ChatContext.Provider value={{ line, user, instance, sendActivity, selectedVoice, setVoice }}>
{children}
</ChatContext.Provider>
);
}
export function useChat() {
const context = useContext(ChatContext);
if (!context) {
throw new Error('useChat must be used within ChatProvider');
}
return context;
}