Files
mumh5/electron/preload.ts
T
kibiandClaude Opus 5.5 9a3aeb29ad Add channel and permission management, sounds, themes and the public server list
- Channels: create, edit, delete, link and move (drag and drop for channels and
  people), right-click on free space in the channel list
- Permission editor with inherited rules, allow/deny per permission, groups and
  members; menus grey out actions the server does not allow
- Notification sounds for connection, channel, chat, mute and push-to-talk events;
  custom files and TeamSpeak 3 style sound packs (settings.ini), stored in IndexedDB
- Color schemes: Dark, Light, Midnight, Frost and Windows 95
- Public server list with live UDP ping, fetched through Chromium's network stack
- Kick, ban and connection-lost card with Reconnect
- Right-click menus for text fields, links, images and message authors
- Formatting toolbar in the message box, shared with the description editor
- Resizable channel list, menu headers, registration from the self menu only
- Fix: client-side pacing now mirrors Murmur's whole-second leaky bucket exactly,
  so quick actions are no longer dropped silently

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 00:54:03 +02:00

42 lines
2.6 KiB
TypeScript

import { contextBridge, ipcRenderer } from 'electron';
type Listener = (connId: string, ...args: any[]) => void;
const listeners = { secure: new Set<Listener>(), data: new Set<Listener>(), close: new Set<Listener>() };
for (const key of Object.keys(listeners) as (keyof typeof listeners)[]) {
ipcRenderer.on(`mumble:${key}`, (_e, connId: string, ...args: any[]) => {
for (const fn of listeners[key]) fn(connId, ...args);
});
}
// The only native surface the renderer gets
contextBridge.exposeInMainWorld('mumh5Native', {
platformInfo: () => ipcRenderer.invoke('platform:info'),
updateTray: (state: unknown) => ipcRenderer.send('tray:update', state),
linkPreview: (url: string) => ipcRenderer.invoke('preview:fetch', url),
publicServers: (url: string) => ipcRenderer.invoke('publist:fetch', url),
pingServer: (host: string, port: number) => ipcRenderer.invoke('publist:ping', host, port),
onContextMenu: (fn: (params: unknown) => void) => { ipcRenderer.on('context-menu', (_e, p) => fn(p)); },
editAction: (action: string, arg?: unknown) => ipcRenderer.send('edit:action', action, arg),
onTrayAction: (fn: (action: string) => void) => { ipcRenderer.on('tray:action', (_e, a: string) => fn(a)); },
describeCerts: (ders: Uint8Array[]) => ipcRenderer.invoke('certs:describe', ders),
identities: {
list: () => ipcRenderer.invoke('identities:list'),
create: (name: string, email: string) => ipcRenderer.invoke('identities:create', name, email),
importP12: (bytes: Uint8Array, password: string, name: string) => ipcRenderer.invoke('identities:import', bytes, password, name),
findMumble: () => ipcRenderer.invoke('identities:findMumble'),
importMumble: (name: string) => ipcRenderer.invoke('identities:importMumble', name),
exportP12: (id: string, password: string) => ipcRenderer.invoke('identities:export', id, password),
setDefault: (id: string) => ipcRenderer.invoke('identities:setDefault', id),
rename: (id: string, name: string) => ipcRenderer.invoke('identities:rename', id, name),
remove: (id: string) => ipcRenderer.invoke('identities:remove', id),
finishSetup: () => ipcRenderer.invoke('identities:finishSetup')
},
open: (connId: string, host: string, port: number, identityId?: string) => ipcRenderer.invoke('mumble:open', connId, host, port, identityId),
send: (connId: string, bytes: Uint8Array) => ipcRenderer.send('mumble:send', connId, bytes),
close: (connId: string) => ipcRenderer.send('mumble:close', connId),
on: (event: keyof typeof listeners, fn: Listener) => {
listeners[event].add(fn);
return () => listeners[event].delete(fn);
}
});