import { query, mutation } from "./_generated/server"; import { v } from "convex/values"; import { getPublicStorageUrl } from "./storageUrl"; async function removeUserVoiceStates(ctx: any, userId: any) { const existing = await ctx.db .query("voiceStates") .withIndex("by_user", (q: any) => q.eq("userId", userId)) .collect(); for (const vs of existing) { await ctx.db.delete(vs._id); } } export const join = mutation({ args: { channelId: v.id("channels"), userId: v.id("userProfiles"), username: v.string(), isMuted: v.boolean(), isDeafened: v.boolean(), }, returns: v.null(), handler: async (ctx, args) => { await removeUserVoiceStates(ctx, args.userId); await ctx.db.insert("voiceStates", { channelId: args.channelId, userId: args.userId, username: args.username, isMuted: args.isMuted, isDeafened: args.isDeafened, isScreenSharing: false, }); return null; }, }); export const leave = mutation({ args: { userId: v.id("userProfiles"), }, returns: v.null(), handler: async (ctx, args) => { await removeUserVoiceStates(ctx, args.userId); return null; }, }); export const updateState = mutation({ args: { userId: v.id("userProfiles"), isMuted: v.optional(v.boolean()), isDeafened: v.optional(v.boolean()), isScreenSharing: v.optional(v.boolean()), }, returns: v.null(), handler: async (ctx, args) => { const existing = await ctx.db .query("voiceStates") .withIndex("by_user", (q) => q.eq("userId", args.userId)) .first(); if (existing) { const { userId: _, ...updates } = args; const filtered = Object.fromEntries( Object.entries(updates).filter(([, val]) => val !== undefined) ); await ctx.db.patch(existing._id, filtered); } return null; }, }); export const getAll = query({ args: {}, returns: v.any(), handler: async (ctx) => { const states = await ctx.db.query("voiceStates").collect(); const grouped: Record> = {}; for (const s of states) { const user = await ctx.db.get(s.userId); let avatarUrl: string | null = null; if (user?.avatarStorageId) { avatarUrl = await getPublicStorageUrl(ctx, user.avatarStorageId); } (grouped[s.channelId] ??= []).push({ userId: s.userId, username: s.username, isMuted: s.isMuted, isDeafened: s.isDeafened, isScreenSharing: s.isScreenSharing, avatarUrl, }); } return grouped; }, });