feat: Implement core chat page with channel navigation, direct messages, and voice chat integration.
All checks were successful
Build and Release / build-and-release (push) Successful in 9m12s

This commit is contained in:
Bryan1029384756
2026-02-11 17:44:50 -06:00
parent b0acf93059
commit b0f889cb68
17 changed files with 1075 additions and 142 deletions

View File

@@ -32,7 +32,7 @@ export const list = query({
_creationTime: v.number(),
name: v.string(),
type: v.string(),
category: v.optional(v.string()),
categoryId: v.optional(v.id("categories")),
topic: v.optional(v.string()),
position: v.optional(v.number()),
})
@@ -54,7 +54,7 @@ export const get = query({
_creationTime: v.number(),
name: v.string(),
type: v.string(),
category: v.optional(v.string()),
categoryId: v.optional(v.id("categories")),
topic: v.optional(v.string()),
position: v.optional(v.number()),
}),
@@ -70,7 +70,7 @@ export const create = mutation({
args: {
name: v.string(),
type: v.optional(v.string()),
category: v.optional(v.string()),
categoryId: v.optional(v.id("categories")),
topic: v.optional(v.string()),
position: v.optional(v.number()),
},
@@ -89,12 +89,26 @@ export const create = mutation({
throw new Error("Channel already exists");
}
// Auto-calculate position if not provided
let position = args.position;
if (position === undefined) {
const allChannels = await ctx.db.query("channels").collect();
const sameCategory = allChannels.filter(
(c) => c.categoryId === args.categoryId && c.type !== "dm"
);
const maxPos = sameCategory.reduce(
(max, c) => Math.max(max, c.position ?? 0),
-1000
);
position = maxPos + 1000;
}
const id = await ctx.db.insert("channels", {
name: args.name,
type: args.type || "text",
category: args.category,
categoryId: args.categoryId,
topic: args.topic,
position: args.position,
position,
});
return { id };
@@ -127,7 +141,7 @@ export const rename = mutation({
_creationTime: v.number(),
name: v.string(),
type: v.string(),
category: v.optional(v.string()),
categoryId: v.optional(v.id("categories")),
topic: v.optional(v.string()),
position: v.optional(v.number()),
}),
@@ -146,6 +160,48 @@ export const rename = mutation({
},
});
// Move a channel to a different category with a new position
export const moveChannel = mutation({
args: {
id: v.id("channels"),
categoryId: v.optional(v.id("categories")),
position: v.number(),
},
returns: v.null(),
handler: async (ctx, args) => {
const channel = await ctx.db.get(args.id);
if (!channel) throw new Error("Channel not found");
await ctx.db.patch(args.id, {
categoryId: args.categoryId,
position: args.position,
});
return null;
},
});
// Batch reorder channels
export const reorderChannels = mutation({
args: {
updates: v.array(
v.object({
id: v.id("channels"),
categoryId: v.optional(v.id("categories")),
position: v.number(),
})
),
},
returns: v.null(),
handler: async (ctx, args) => {
for (const u of args.updates) {
await ctx.db.patch(u.id, {
categoryId: u.categoryId,
position: u.position,
});
}
return null;
},
});
// Delete channel + cascade messages and keys
export const remove = mutation({
args: { id: v.id("channels") },