import { query, mutation } from "./_generated/server"; import { v } from "convex/values"; // Join voice channel 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) => { // Remove from any other voice channel first const existing = await ctx.db .query("voiceStates") .withIndex("by_user", (q) => q.eq("userId", args.userId)) .collect(); for (const vs of existing) { await ctx.db.delete(vs._id); } // Add to new channel await ctx.db.insert("voiceStates", { channelId: args.channelId, userId: args.userId, username: args.username, isMuted: args.isMuted, isDeafened: args.isDeafened, isScreenSharing: false, }); return null; }, }); // Leave voice channel export const leave = mutation({ args: { userId: v.id("userProfiles"), }, returns: v.null(), handler: async (ctx, args) => { const existing = await ctx.db .query("voiceStates") .withIndex("by_user", (q) => q.eq("userId", args.userId)) .collect(); for (const vs of existing) { await ctx.db.delete(vs._id); } return null; }, }); // Update mute/deafen/screenshare state 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)) .collect(); if (existing.length > 0) { const updates: Record = {}; if (args.isMuted !== undefined) updates.isMuted = args.isMuted; if (args.isDeafened !== undefined) updates.isDeafened = args.isDeafened; if (args.isScreenSharing !== undefined) updates.isScreenSharing = args.isScreenSharing; await ctx.db.patch(existing[0]._id, updates); } return null; }, }); // Get all voice states (reactive!) export const getAll = query({ args: {}, returns: v.any(), handler: async (ctx) => { const states = await ctx.db.query("voiceStates").collect(); // Group by channel const grouped: Record< string, Array<{ userId: string; username: string; isMuted: boolean; isDeafened: boolean; isScreenSharing: boolean; }> > = {}; for (const s of states) { const channelId = s.channelId; if (!grouped[channelId]) { grouped[channelId] = []; } grouped[channelId].push({ userId: s.userId, username: s.username, isMuted: s.isMuted, isDeafened: s.isDeafened, isScreenSharing: s.isScreenSharing, }); } return grouped; }, });