refactor: enhance chat components with type safety and response functionality

- Updated type definitions in ChatWindow and MessageList components for better type safety.
- Improved MessageInput to handle message responses, including a preview feature for replying to messages.
- Enhanced the chat message handling logic to support message references and improve user interaction.
- Refactored notification utility functions to support push notifications and rate limiting for email sending.
- Updated backend schema to accommodate new features related to message responses and notifications.
This commit is contained in:
2025-11-04 20:36:01 -03:00
parent 15374276d5
commit 12db52a8a7
23 changed files with 3195 additions and 503 deletions

View File

@@ -604,6 +604,19 @@ export default defineSchema({
descricao: v.string(),
}).index("by_chave", ["chave"]),
// Rate Limiting de Emails
rateLimitEmails: defineTable({
remetenteId: v.id("usuarios"),
timestamp: v.number(),
contador: v.number(), // quantidade de emails enviados neste período
periodo: v.union(
v.literal("minuto"), // último minuto
v.literal("hora") // última hora
),
})
.index("by_remetente_periodo", ["remetenteId", "periodo", "timestamp"])
.index("by_timestamp", ["timestamp"]),
// Sistema de Chat
conversas: defineTable({
tipo: v.union(v.literal("individual"), v.literal("grupo")),
@@ -628,10 +641,20 @@ export default defineSchema({
v.literal("imagem")
),
conteudo: v.string(), // texto ou nome do arquivo
conteudoBusca: v.optional(v.string()), // versão normalizada para busca
arquivoId: v.optional(v.id("_storage")),
arquivoNome: v.optional(v.string()),
arquivoTamanho: v.optional(v.number()),
arquivoTipo: v.optional(v.string()),
linkPreview: v.optional(
v.object({
url: v.string(),
titulo: v.optional(v.string()),
descricao: v.optional(v.string()),
imagem: v.optional(v.string()),
site: v.optional(v.string()),
})
),
reagiuPor: v.optional(
v.array(
v.object({
@@ -641,6 +664,7 @@ export default defineSchema({
)
),
mencoes: v.optional(v.array(v.id("usuarios"))),
respostaPara: v.optional(v.id("mensagens")), // ID da mensagem que está respondendo
agendadaPara: v.optional(v.number()), // timestamp
enviadaEm: v.number(),
editadaEm: v.optional(v.number()),
@@ -648,7 +672,8 @@ export default defineSchema({
})
.index("by_conversa", ["conversaId", "enviadaEm"])
.index("by_remetente", ["remetenteId"])
.index("by_agendamento", ["agendadaPara"]),
.index("by_agendamento", ["agendadaPara"])
.index("by_resposta", ["respostaPara"]),
leituras: defineTable({
conversaId: v.id("conversas"),
@@ -686,6 +711,37 @@ export default defineSchema({
.index("by_conversa", ["conversaId", "iniciouEm"])
.index("by_usuario", ["usuarioId"]),
// Push Notifications
pushSubscriptions: defineTable({
usuarioId: v.id("usuarios"),
endpoint: v.string(), // URL do serviço de push
keys: v.object({
p256dh: v.string(), // Chave pública
auth: v.string(), // Chave de autenticação
}),
userAgent: v.optional(v.string()),
criadoEm: v.number(),
ultimaAtividade: v.number(),
ativo: v.boolean(),
})
.index("by_usuario", ["usuarioId", "ativo"])
.index("by_endpoint", ["endpoint"]),
// Preferências de Notificação por Conversa
preferenciasNotificacaoConversa: defineTable({
usuarioId: v.id("usuarios"),
conversaId: v.id("conversas"),
pushAtivado: v.boolean(), // Receber push notifications
emailAtivado: v.boolean(), // Receber emails quando offline
somAtivado: v.boolean(), // Tocar som
silenciado: v.boolean(), // Silenciar completamente
apenasMencoes: v.boolean(), // Notificar apenas quando mencionado
criadoEm: v.number(),
atualizadoEm: v.number(),
})
.index("by_usuario_conversa", ["usuarioId", "conversaId"])
.index("by_conversa", ["conversaId"]),
// Tabelas de Monitoramento do Sistema
systemMetrics: defineTable({
timestamp: v.number(),