- Adiciona ConvexMachineProvider para autenticacao via machine token - Cria hooks customizados (useMachineSessions, useMachineMessages, etc) - Refatora ChatWidget e ChatHubWidget para usar useQuery/useMutation - Remove polling e dependencia de Tauri events para mensagens - Adiciona copia local dos arquivos _generated do Convex - Remove componentes obsoletos (ChatSessionItem, ChatSessionList) Beneficios: - Tempo real verdadeiro via WebSocket (sem polling) - Melhor escalabilidade e performance - Codigo mais simples e maintivel - Consistencia de estado entre multiplas janelas 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
146 lines
3.9 KiB
TypeScript
146 lines
3.9 KiB
TypeScript
/**
|
|
* ConvexMachineProvider - Provider Convex para autenticacao via token de maquina
|
|
*
|
|
* Este provider inicializa o ConvexReactClient usando o token da maquina
|
|
* armazenado no Tauri Store, permitindo subscriptions reativas em tempo real.
|
|
*
|
|
* Arquitetura:
|
|
* - Carrega o token do Tauri Store na montagem
|
|
* - Inicializa o ConvexReactClient com a URL do Convex
|
|
* - Disponibiliza o cliente para componentes filhos via Context
|
|
* - Reconecta automaticamente quando o token muda
|
|
*/
|
|
|
|
import { createContext, useContext, useEffect, useState, type ReactNode } from "react"
|
|
import { ConvexReactClient } from "convex/react"
|
|
import { getMachineStoreConfig } from "./machineStore"
|
|
|
|
// URL do Convex - em producao, usa o dominio personalizado
|
|
const CONVEX_URL = import.meta.env.MODE === "production"
|
|
? "https://convex.esdrasrenan.com.br"
|
|
: (import.meta.env.VITE_CONVEX_URL ?? "https://convex.esdrasrenan.com.br")
|
|
|
|
type MachineAuthState = {
|
|
token: string | null
|
|
apiBaseUrl: string | null
|
|
isLoading: boolean
|
|
error: string | null
|
|
}
|
|
|
|
type ConvexMachineContextValue = {
|
|
client: ConvexReactClient | null
|
|
machineToken: string | null
|
|
apiBaseUrl: string | null
|
|
isReady: boolean
|
|
error: string | null
|
|
reload: () => Promise<void>
|
|
}
|
|
|
|
const ConvexMachineContext = createContext<ConvexMachineContextValue | null>(null)
|
|
|
|
export function useConvexMachine() {
|
|
const ctx = useContext(ConvexMachineContext)
|
|
if (!ctx) {
|
|
throw new Error("useConvexMachine must be used within ConvexMachineProvider")
|
|
}
|
|
return ctx
|
|
}
|
|
|
|
export function useMachineToken() {
|
|
const { machineToken } = useConvexMachine()
|
|
return machineToken
|
|
}
|
|
|
|
interface ConvexMachineProviderProps {
|
|
children: ReactNode
|
|
}
|
|
|
|
export function ConvexMachineProvider({ children }: ConvexMachineProviderProps) {
|
|
const [authState, setAuthState] = useState<MachineAuthState>({
|
|
token: null,
|
|
apiBaseUrl: null,
|
|
isLoading: true,
|
|
error: null,
|
|
})
|
|
|
|
const [client, setClient] = useState<ConvexReactClient | null>(null)
|
|
|
|
// Funcao para carregar configuracao do Tauri Store
|
|
const loadConfig = async () => {
|
|
setAuthState(prev => ({ ...prev, isLoading: true, error: null }))
|
|
|
|
try {
|
|
const config = await getMachineStoreConfig()
|
|
|
|
if (!config.token) {
|
|
setAuthState({
|
|
token: null,
|
|
apiBaseUrl: config.apiBaseUrl,
|
|
isLoading: false,
|
|
error: "Token da maquina nao encontrado",
|
|
})
|
|
return
|
|
}
|
|
|
|
setAuthState({
|
|
token: config.token,
|
|
apiBaseUrl: config.apiBaseUrl,
|
|
isLoading: false,
|
|
error: null,
|
|
})
|
|
} catch (err) {
|
|
const message = err instanceof Error ? err.message : String(err)
|
|
setAuthState({
|
|
token: null,
|
|
apiBaseUrl: null,
|
|
isLoading: false,
|
|
error: message || "Erro ao carregar configuracao",
|
|
})
|
|
}
|
|
}
|
|
|
|
// Carregar configuracao na montagem
|
|
useEffect(() => {
|
|
loadConfig()
|
|
}, [])
|
|
|
|
// Inicializar/reinicializar cliente Convex quando token muda
|
|
useEffect(() => {
|
|
if (!authState.token) {
|
|
// Limpar cliente se nao tem token
|
|
if (client) {
|
|
client.close()
|
|
setClient(null)
|
|
}
|
|
return
|
|
}
|
|
|
|
// Criar novo cliente Convex
|
|
const newClient = new ConvexReactClient(CONVEX_URL, {
|
|
// Desabilitar retry agressivo para evitar loops infinitos
|
|
unsavedChangesWarning: false,
|
|
})
|
|
|
|
setClient(newClient)
|
|
|
|
// Cleanup ao desmontar ou trocar token
|
|
return () => {
|
|
newClient.close()
|
|
}
|
|
}, [authState.token]) // eslint-disable-line react-hooks/exhaustive-deps
|
|
|
|
const contextValue: ConvexMachineContextValue = {
|
|
client,
|
|
machineToken: authState.token,
|
|
apiBaseUrl: authState.apiBaseUrl,
|
|
isReady: !authState.isLoading && !!client && !!authState.token,
|
|
error: authState.error,
|
|
reload: loadConfig,
|
|
}
|
|
|
|
return (
|
|
<ConvexMachineContext.Provider value={contextValue}>
|
|
{children}
|
|
</ConvexMachineContext.Provider>
|
|
)
|
|
}
|