Files
kibiandClaude Opus 5.5 6d29ee1485 Initial commit: mumh5, a modern Mumble client
Electron desktop app with a Svelte 5 interface for any Mumble server.

- Mumble protocol core: TLS, handshake, channels, users, text, plugin data,
  client-side pacing of Murmur's rate limits
- Voice: WebCodecs Opus over the TCP tunnel, voice activity, push to talk,
  always-on, devices, per-user volume and local mute
- Several servers at once, voice on one; server rail with icons and ordering
- Chat: channels, direct messages, side chat, file sharing through f0ckm,
  inline images without it, click-to-play YouTube
- Profiles with rich descriptions, registration, rename, nicknames,
  connection information and moderation menus
- Identity wizard, multiple identities, PKCS#12 import/export, desktop
  Mumble certificate import, certificate pinning and viewer
- Tray icon with voice state
- Unit, server and end-to-end tests against a real Murmur

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 23:28:43 +02:00

29 lines
1.0 KiB
JavaScript

import { spawn } from 'node:child_process';
import * as esbuild from 'esbuild';
import { createServer } from 'vite';
import electronPath from 'electron';
import { options } from './build-electron.mjs';
// Vite dev server for the renderer, esbuild watch for main/preload, Electron restarted on main changes.
const server = await createServer();
await server.listen();
const url = server.resolvedUrls.local[0];
let child = null;
const startElectron = () => {
if (child) {
child.removeAllListeners('exit');
child.kill();
}
// ELECTRON_RUN_AS_NODE (set by some editor terminals) would start Electron as plain Node
const { ELECTRON_RUN_AS_NODE, ...env } = process.env;
child = spawn(electronPath, ['.'], { stdio: 'inherit', env: { ...env, VITE_DEV_SERVER_URL: url } });
child.on('exit', () => { server.close(); process.exit(0); });
};
const ctx = await esbuild.context({
...options,
plugins: [{ name: 'restart', setup(b) { b.onEnd(r => { if (!r.errors.length) startElectron(); }); } }]
});
await ctx.watch();