feat: Implement core Discord features including members list, direct messages, user presence, authentication, and chat UI.
Some checks failed
Build and Release / build-and-release (push) Has been cancelled
Some checks failed
Build and Release / build-and-release (push) Has been cancelled
This commit is contained in:
67
convex/_generated/api.d.ts
vendored
67
convex/_generated/api.d.ts
vendored
@@ -17,6 +17,7 @@ import type * as gifs from "../gifs.js";
|
||||
import type * as invites from "../invites.js";
|
||||
import type * as members from "../members.js";
|
||||
import type * as messages from "../messages.js";
|
||||
import type * as presence from "../presence.js";
|
||||
import type * as reactions from "../reactions.js";
|
||||
import type * as roles from "../roles.js";
|
||||
import type * as typing from "../typing.js";
|
||||
@@ -39,6 +40,7 @@ declare const fullApi: ApiFromModules<{
|
||||
invites: typeof invites;
|
||||
members: typeof members;
|
||||
messages: typeof messages;
|
||||
presence: typeof presence;
|
||||
reactions: typeof reactions;
|
||||
roles: typeof roles;
|
||||
typing: typeof typing;
|
||||
@@ -72,4 +74,67 @@ export declare const internal: FilterApi<
|
||||
FunctionReference<any, "internal">
|
||||
>;
|
||||
|
||||
export declare const components: {};
|
||||
export declare const components: {
|
||||
presence: {
|
||||
public: {
|
||||
disconnect: FunctionReference<
|
||||
"mutation",
|
||||
"internal",
|
||||
{ sessionToken: string },
|
||||
null
|
||||
>;
|
||||
heartbeat: FunctionReference<
|
||||
"mutation",
|
||||
"internal",
|
||||
{
|
||||
interval?: number;
|
||||
roomId: string;
|
||||
sessionId: string;
|
||||
userId: string;
|
||||
},
|
||||
{ roomToken: string; sessionToken: string }
|
||||
>;
|
||||
list: FunctionReference<
|
||||
"query",
|
||||
"internal",
|
||||
{ limit?: number; roomToken: string },
|
||||
Array<{
|
||||
data?: any;
|
||||
lastDisconnected: number;
|
||||
online: boolean;
|
||||
userId: string;
|
||||
}>
|
||||
>;
|
||||
listRoom: FunctionReference<
|
||||
"query",
|
||||
"internal",
|
||||
{ limit?: number; onlineOnly?: boolean; roomId: string },
|
||||
Array<{ lastDisconnected: number; online: boolean; userId: string }>
|
||||
>;
|
||||
listUser: FunctionReference<
|
||||
"query",
|
||||
"internal",
|
||||
{ limit?: number; onlineOnly?: boolean; userId: string },
|
||||
Array<{ lastDisconnected: number; online: boolean; roomId: string }>
|
||||
>;
|
||||
removeRoom: FunctionReference<
|
||||
"mutation",
|
||||
"internal",
|
||||
{ roomId: string },
|
||||
null
|
||||
>;
|
||||
removeRoomUser: FunctionReference<
|
||||
"mutation",
|
||||
"internal",
|
||||
{ roomId: string; userId: string },
|
||||
null
|
||||
>;
|
||||
updateRoomUser: FunctionReference<
|
||||
"mutation",
|
||||
"internal",
|
||||
{ data?: any; roomId: string; userId: string },
|
||||
null
|
||||
>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -198,6 +198,7 @@ export const getPublicKeys = query({
|
||||
username: v.string(),
|
||||
public_identity_key: v.string(),
|
||||
status: v.optional(v.string()),
|
||||
displayName: v.optional(v.string()),
|
||||
avatarUrl: v.optional(v.union(v.string(), v.null())),
|
||||
aboutMe: v.optional(v.string()),
|
||||
customStatus: v.optional(v.string()),
|
||||
@@ -215,7 +216,8 @@ export const getPublicKeys = query({
|
||||
id: u._id,
|
||||
username: u.username,
|
||||
public_identity_key: u.publicIdentityKey,
|
||||
status: u.status || "online",
|
||||
status: u.status || "offline",
|
||||
displayName: u.displayName,
|
||||
avatarUrl,
|
||||
aboutMe: u.aboutMe,
|
||||
customStatus: u.customStatus,
|
||||
@@ -229,6 +231,7 @@ export const getPublicKeys = query({
|
||||
export const updateProfile = mutation({
|
||||
args: {
|
||||
userId: v.id("userProfiles"),
|
||||
displayName: v.optional(v.string()),
|
||||
aboutMe: v.optional(v.string()),
|
||||
avatarStorageId: v.optional(v.id("_storage")),
|
||||
customStatus: v.optional(v.string()),
|
||||
@@ -236,6 +239,7 @@ export const updateProfile = mutation({
|
||||
returns: v.null(),
|
||||
handler: async (ctx, args) => {
|
||||
const patch: Record<string, unknown> = {};
|
||||
if (args.displayName !== undefined) patch.displayName = args.displayName;
|
||||
if (args.aboutMe !== undefined) patch.aboutMe = args.aboutMe;
|
||||
if (args.avatarStorageId !== undefined) patch.avatarStorageId = args.avatarStorageId;
|
||||
if (args.customStatus !== undefined) patch.customStatus = args.customStatus;
|
||||
|
||||
6
convex/convex.config.ts
Normal file
6
convex/convex.config.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
import { defineApp } from "convex/server";
|
||||
import presence from "@convex-dev/presence/convex.config.js";
|
||||
|
||||
const app = defineApp();
|
||||
app.use(presence);
|
||||
export default app;
|
||||
@@ -79,7 +79,7 @@ export const listDMs = query({
|
||||
channel_name: channel.name,
|
||||
other_user_id: otherUser._id as string,
|
||||
other_username: otherUser.username,
|
||||
other_user_status: otherUser.status || "online",
|
||||
other_user_status: otherUser.status || "offline",
|
||||
};
|
||||
})
|
||||
);
|
||||
|
||||
@@ -50,7 +50,7 @@ export const getChannelMembers = query({
|
||||
members.push({
|
||||
id: user._id,
|
||||
username: user.username,
|
||||
status: user.status || "online",
|
||||
status: user.status || "offline",
|
||||
roles: roles.sort((a, b) => b.position - a.position),
|
||||
avatarUrl,
|
||||
aboutMe: user.aboutMe,
|
||||
|
||||
32
convex/presence.ts
Normal file
32
convex/presence.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
import { mutation, query } from "./_generated/server";
|
||||
import { components } from "./_generated/api";
|
||||
import { v } from "convex/values";
|
||||
import { Presence } from "@convex-dev/presence";
|
||||
|
||||
const presence = new Presence(components.presence);
|
||||
|
||||
export const heartbeat = mutation({
|
||||
args: {
|
||||
roomId: v.string(),
|
||||
userId: v.string(),
|
||||
sessionId: v.string(),
|
||||
interval: v.number(),
|
||||
},
|
||||
handler: async (ctx, { roomId, userId, sessionId, interval }) => {
|
||||
return await presence.heartbeat(ctx, roomId, userId, sessionId, interval);
|
||||
},
|
||||
});
|
||||
|
||||
export const list = query({
|
||||
args: { roomToken: v.string() },
|
||||
handler: async (ctx, { roomToken }) => {
|
||||
return await presence.list(ctx, roomToken);
|
||||
},
|
||||
});
|
||||
|
||||
export const disconnect = mutation({
|
||||
args: { sessionToken: v.string() },
|
||||
handler: async (ctx, { sessionToken }) => {
|
||||
return await presence.disconnect(ctx, sessionToken);
|
||||
},
|
||||
});
|
||||
@@ -12,6 +12,7 @@ export default defineSchema({
|
||||
encryptedPrivateKeys: v.string(),
|
||||
isAdmin: v.boolean(),
|
||||
status: v.optional(v.string()),
|
||||
displayName: v.optional(v.string()),
|
||||
avatarStorageId: v.optional(v.id("_storage")),
|
||||
aboutMe: v.optional(v.string()),
|
||||
customStatus: v.optional(v.string()),
|
||||
|
||||
Reference in New Issue
Block a user