import { query, mutation } from "./_generated/server"; import { v } from "convex/values"; // Get read state for a single channel export const getReadState = query({ args: { userId: v.id("userProfiles"), channelId: v.id("channels"), }, returns: v.union( v.object({ lastReadTimestamp: v.number(), }), v.null() ), handler: async (ctx, args) => { const state = await ctx.db .query("channelReadState") .withIndex("by_user_and_channel", (q) => q.eq("userId", args.userId).eq("channelId", args.channelId) ) .unique(); if (!state) return null; return { lastReadTimestamp: state.lastReadTimestamp }; }, }); // Mark a channel as read up to a given timestamp export const markRead = mutation({ args: { userId: v.id("userProfiles"), channelId: v.id("channels"), lastReadTimestamp: v.number(), }, returns: v.null(), handler: async (ctx, args) => { const existing = await ctx.db .query("channelReadState") .withIndex("by_user_and_channel", (q) => q.eq("userId", args.userId).eq("channelId", args.channelId) ) .unique(); if (existing) { // Only update if timestamp is newer if (args.lastReadTimestamp > existing.lastReadTimestamp) { await ctx.db.patch(existing._id, { lastReadTimestamp: args.lastReadTimestamp, }); } } else { await ctx.db.insert("channelReadState", { userId: args.userId, channelId: args.channelId, lastReadTimestamp: args.lastReadTimestamp, }); } return null; }, }); // Get all read states for a user (used by Sidebar) export const getAllReadStates = query({ args: { userId: v.id("userProfiles"), }, returns: v.array( v.object({ channelId: v.id("channels"), lastReadTimestamp: v.number(), }) ), handler: async (ctx, args) => { const states = await ctx.db .query("channelReadState") .withIndex("by_user", (q) => q.eq("userId", args.userId)) .collect(); return states.map((s) => ({ channelId: s.channelId, lastReadTimestamp: s.lastReadTimestamp, })); }, }); // Get the latest message timestamp per channel (used by Sidebar) export const getLatestMessageTimestamps = query({ args: { channelIds: v.array(v.id("channels")), }, returns: v.array( v.object({ channelId: v.id("channels"), latestTimestamp: v.number(), }) ), handler: async (ctx, args) => { const results = []; for (const channelId of args.channelIds) { const latestMsg = await ctx.db .query("messages") .withIndex("by_channel", (q) => q.eq("channelId", channelId)) .order("desc") .first(); if (latestMsg) { results.push({ channelId, latestTimestamp: latestMsg._creationTime, }); } } return results; }, });