import { v } from 'convex/values'; import { mutation, query } from './_generated/server'; export const register = mutation({ args: { chatId: v.id('chats'), deviceId: v.string(), hasCamera: v.boolean() }, returns: v.id('devicePairings'), handler: async (ctx, args) => { const existing = await ctx.db .query('devicePairings') .withIndex('by_chat_id', (q) => q.eq('chatId', args.chatId)) .collect(); const device = existing.find((d) => d.deviceId === args.deviceId); if (device) { await ctx.db.patch(device._id, { hasCamera: args.hasCamera, lastSeen: Date.now() }); return device._id; } return await ctx.db.insert('devicePairings', { chatId: args.chatId, deviceId: args.deviceId, hasCamera: args.hasCamera, lastSeen: Date.now() }); } }); export const heartbeat = mutation({ args: { chatId: v.id('chats'), deviceId: v.string() }, returns: v.null(), handler: async (ctx, args) => { const devices = await ctx.db .query('devicePairings') .withIndex('by_chat_id', (q) => q.eq('chatId', args.chatId)) .collect(); const device = devices.find((d) => d.deviceId === args.deviceId); if (device) { await ctx.db.patch(device._id, { lastSeen: Date.now() }); } return null; } }); export const getMyDevice = query({ args: { chatId: v.id('chats'), deviceId: v.string() }, returns: v.union( v.object({ _id: v.id('devicePairings'), _creationTime: v.number(), chatId: v.id('chats'), deviceId: v.string(), hasCamera: v.boolean(), pairedWithDeviceId: v.optional(v.string()), lastSeen: v.number() }), v.null() ), handler: async (ctx, args) => { const devices = await ctx.db .query('devicePairings') .withIndex('by_chat_id', (q) => q.eq('chatId', args.chatId)) .collect(); return devices.find((d) => d.deviceId === args.deviceId) ?? null; } }); export const getPairedDevice = query({ args: { chatId: v.id('chats'), deviceId: v.string() }, returns: v.union( v.object({ _id: v.id('devicePairings'), _creationTime: v.number(), chatId: v.id('chats'), deviceId: v.string(), hasCamera: v.boolean(), pairedWithDeviceId: v.optional(v.string()), lastSeen: v.number() }), v.null() ), handler: async (ctx, args) => { const devices = await ctx.db .query('devicePairings') .withIndex('by_chat_id', (q) => q.eq('chatId', args.chatId)) .collect(); const myDevice = devices.find((d) => d.deviceId === args.deviceId); if (!myDevice?.pairedWithDeviceId) return null; const thirtySecondsAgo = Date.now() - 30000; const paired = devices.find( (d) => d.deviceId === myDevice.pairedWithDeviceId && d.lastSeen > thirtySecondsAgo ); return paired ?? null; } });