feat: Add initial Electron frontend package.json with dependencies, scripts, and build configuration.

This commit is contained in:
Bryan1029384756
2026-02-12 02:38:06 -06:00
parent 1952a1fedf
commit e790db7029
14 changed files with 95 additions and 29 deletions

View File

@@ -22,6 +22,7 @@ import type * as presence from "../presence.js";
import type * as reactions from "../reactions.js";
import type * as readState from "../readState.js";
import type * as roles from "../roles.js";
import type * as storageUrl from "../storageUrl.js";
import type * as typing from "../typing.js";
import type * as voice from "../voice.js";
import type * as voiceState from "../voiceState.js";
@@ -47,6 +48,7 @@ declare const fullApi: ApiFromModules<{
reactions: typeof reactions;
readState: typeof readState;
roles: typeof roles;
storageUrl: typeof storageUrl;
typing: typeof typing;
voice: typeof voice;
voiceState: typeof voiceState;

View File

@@ -1,5 +1,6 @@
import { query, mutation } from "./_generated/server";
import { v } from "convex/values";
import { getPublicStorageUrl } from "./storageUrl";
async function sha256Hex(input: string): Promise<string> {
const buffer = await crypto.subtle.digest(
@@ -210,7 +211,7 @@ export const getPublicKeys = query({
for (const u of users) {
let avatarUrl: string | null = null;
if (u.avatarStorageId) {
avatarUrl = await ctx.storage.getUrl(u.avatarStorageId);
avatarUrl = await getPublicStorageUrl(ctx, u.avatarStorageId);
}
results.push({
id: u._id,

View File

@@ -1,5 +1,6 @@
import { query, mutation } from "./_generated/server";
import { v } from "convex/values";
import { getPublicStorageUrl } from "./storageUrl";
export const openDM = mutation({
args: {
@@ -76,7 +77,7 @@ export const listDMs = query({
if (!otherUser) return null;
const avatarUrl = otherUser.avatarStorageId
? await ctx.storage.getUrl(otherUser.avatarStorageId)
? await getPublicStorageUrl(ctx, otherUser.avatarStorageId)
: null;
return {

View File

@@ -1,12 +1,14 @@
import { mutation, query } from "./_generated/server";
import { v } from "convex/values";
import { getPublicStorageUrl, rewriteToPublicUrl } from "./storageUrl";
// Generate upload URL for client-side uploads
export const generateUploadUrl = mutation({
args: {},
returns: v.string(),
handler: async (ctx) => {
return await ctx.storage.generateUploadUrl();
const url = await ctx.storage.generateUploadUrl();
return rewriteToPublicUrl(url);
},
});
@@ -15,6 +17,6 @@ export const getFileUrl = query({
args: { storageId: v.id("_storage") },
returns: v.union(v.string(), v.null()),
handler: async (ctx, args) => {
return await ctx.storage.getUrl(args.storageId);
return await getPublicStorageUrl(ctx, args.storageId);
},
});

View File

@@ -1,5 +1,6 @@
import { query } from "./_generated/server";
import { v } from "convex/values";
import { getPublicStorageUrl } from "./storageUrl";
export const getChannelMembers = query({
args: {
@@ -44,7 +45,7 @@ export const getChannelMembers = query({
let avatarUrl: string | null = null;
if (user.avatarStorageId) {
avatarUrl = await ctx.storage.getUrl(user.avatarStorageId);
avatarUrl = await getPublicStorageUrl(ctx, user.avatarStorageId);
}
members.push({

View File

@@ -1,6 +1,7 @@
import { query, mutation } from "./_generated/server";
import { paginationOptsValidator } from "convex/server";
import { v } from "convex/values";
import { getPublicStorageUrl } from "./storageUrl";
export const list = query({
args: {
@@ -22,7 +23,7 @@ export const list = query({
let avatarUrl: string | null = null;
if (sender?.avatarStorageId) {
avatarUrl = await ctx.storage.getUrl(sender.avatarStorageId);
avatarUrl = await getPublicStorageUrl(ctx, sender.avatarStorageId);
}
const reactionDocs = await ctx.db
@@ -51,7 +52,7 @@ export const list = query({
replyToContent = repliedMsg.ciphertext;
replyToNonce = repliedMsg.nonce;
if (repliedSender?.avatarStorageId) {
replyToAvatarUrl = await ctx.storage.getUrl(repliedSender.avatarStorageId);
replyToAvatarUrl = await getPublicStorageUrl(ctx, repliedSender.avatarStorageId);
}
}
}

28
convex/storageUrl.ts Normal file
View File

@@ -0,0 +1,28 @@
import { Id } from "./_generated/dataModel";
// Change this if your public IP changes
const PUBLIC_CONVEX_URL = "http://72.26.56.3:3210";
/** Rewrite any URL to use the public hostname/port/protocol */
export function rewriteToPublicUrl(url: string): string {
try {
const original = new URL(url);
const target = new URL(PUBLIC_CONVEX_URL);
original.hostname = target.hostname;
original.port = target.port;
original.protocol = target.protocol;
return original.toString();
} catch {
return url;
}
}
/** Get a storage file URL rewritten to the public address */
export async function getPublicStorageUrl(
ctx: { storage: { getUrl: (id: Id<"_storage">) => Promise<string | null> } },
storageId: Id<"_storage">
): Promise<string | null> {
const url = await ctx.storage.getUrl(storageId);
if (!url) return null;
return rewriteToPublicUrl(url);
}

View File

@@ -1,5 +1,6 @@
import { query, mutation } from "./_generated/server";
import { v } from "convex/values";
import { getPublicStorageUrl } from "./storageUrl";
async function removeUserVoiceStates(ctx: any, userId: any) {
const existing = await ctx.db
@@ -92,7 +93,7 @@ export const getAll = query({
const user = await ctx.db.get(s.userId);
let avatarUrl: string | null = null;
if (user?.avatarStorageId) {
avatarUrl = await ctx.storage.getUrl(user.avatarStorageId);
avatarUrl = await getPublicStorageUrl(ctx, user.avatarStorageId);
}
(grouped[s.channelId] ??= []).push({