mirror of
https://github.com/J3vb/OwnCord.git
synced 2026-09-03 03:50:00 +03:00
fix: remove duplicate mute/deafen buttons from user bar, disable browser context menu
- Remove microphone and headphone buttons from UserBar (already in VoiceWidget) - Disable default browser right-click menu globally so only custom context menus show
This commit is contained in:
@@ -8,10 +8,7 @@ import type { MountableComponent } from "@lib/safe-render";
|
||||
import { authStore } from "@stores/auth.store";
|
||||
import { openSettings } from "@stores/ui.store";
|
||||
|
||||
export interface UserBarOptions {
|
||||
readonly onMuteToggle?: () => void;
|
||||
readonly onDeafenToggle?: () => void;
|
||||
}
|
||||
export type UserBarOptions = Record<string, never>;
|
||||
|
||||
export function createUserBar(options?: UserBarOptions): MountableComponent {
|
||||
const ac = new AbortController();
|
||||
@@ -63,32 +60,12 @@ export function createUserBar(options?: UserBarOptions): MountableComponent {
|
||||
|
||||
const buttons = createElement("div", { class: "ub-controls" });
|
||||
|
||||
const muteBtn = createElement(
|
||||
"button",
|
||||
{ title: "Mute", "aria-label": "Mute" },
|
||||
"\uD83C\uDFA4",
|
||||
);
|
||||
|
||||
const deafenBtn = createElement(
|
||||
"button",
|
||||
{ title: "Deafen", "aria-label": "Deafen" },
|
||||
"\uD83C\uDFA7",
|
||||
);
|
||||
|
||||
const settingsBtn = createElement(
|
||||
"button",
|
||||
{ title: "Settings", "aria-label": "Settings" },
|
||||
"\u2699",
|
||||
);
|
||||
|
||||
if (options?.onMuteToggle) {
|
||||
muteBtn.addEventListener("click", options.onMuteToggle, { signal: ac.signal });
|
||||
}
|
||||
|
||||
if (options?.onDeafenToggle) {
|
||||
deafenBtn.addEventListener("click", options.onDeafenToggle, { signal: ac.signal });
|
||||
}
|
||||
|
||||
settingsBtn.addEventListener(
|
||||
"click",
|
||||
() => {
|
||||
@@ -97,7 +74,7 @@ export function createUserBar(options?: UserBarOptions): MountableComponent {
|
||||
{ signal: ac.signal },
|
||||
);
|
||||
|
||||
appendChildren(buttons, muteBtn, deafenBtn, settingsBtn);
|
||||
buttons.appendChild(settingsBtn);
|
||||
appendChildren(root, avatarEl, info, buttons);
|
||||
|
||||
// Initial render
|
||||
|
||||
@@ -27,6 +27,13 @@ import type { CertTofuEvent } from "@lib/ws";
|
||||
|
||||
const log = createLogger("main");
|
||||
|
||||
// Disable the default browser context menu globally.
|
||||
// Custom context menus (e.g. channel edit/delete) call e.preventDefault()
|
||||
// themselves before the event reaches this handler.
|
||||
document.addEventListener("contextmenu", (e) => {
|
||||
e.preventDefault();
|
||||
});
|
||||
|
||||
// Install global error handlers first
|
||||
installGlobalErrorHandlers();
|
||||
|
||||
|
||||
@@ -561,22 +561,7 @@ export function createMainPage(options: MainPageOptions): MountableComponent {
|
||||
|
||||
// User bar
|
||||
const userBarSlot = createElement("div", {});
|
||||
const userBar = createUserBar({
|
||||
onMuteToggle: () => {
|
||||
if (voiceStore.getState().currentChannelId === null) return;
|
||||
if (!limiters.voice.tryConsume()) return;
|
||||
const next = !voiceStore.getState().localMuted;
|
||||
voiceSessionSetMuted(next);
|
||||
ws.send({ type: "voice_mute", payload: { muted: next } });
|
||||
},
|
||||
onDeafenToggle: () => {
|
||||
if (voiceStore.getState().currentChannelId === null) return;
|
||||
if (!limiters.voice.tryConsume()) return;
|
||||
const next = !voiceStore.getState().localDeafened;
|
||||
voiceSessionSetDeafened(next);
|
||||
ws.send({ type: "voice_deafen", payload: { deafened: next } });
|
||||
},
|
||||
});
|
||||
const userBar = createUserBar();
|
||||
userBar.mount(userBarSlot);
|
||||
children.push(userBar);
|
||||
sidebarWrapper.appendChild(userBarSlot);
|
||||
|
||||
@@ -101,49 +101,13 @@ describe("UserBar", () => {
|
||||
expect(openSettings).toHaveBeenCalledOnce();
|
||||
});
|
||||
|
||||
it("calls onMuteToggle when mute button clicked", () => {
|
||||
setAuthState({ username: "alice" }, true);
|
||||
const onMuteToggle = vi.fn();
|
||||
comp = createUserBar({ onMuteToggle });
|
||||
comp.mount(container);
|
||||
|
||||
const muteBtn = container.querySelector('[title="Mute"]') as HTMLButtonElement;
|
||||
muteBtn.click();
|
||||
expect(onMuteToggle).toHaveBeenCalledOnce();
|
||||
});
|
||||
|
||||
it("calls onDeafenToggle when deafen button clicked", () => {
|
||||
setAuthState({ username: "alice" }, true);
|
||||
const onDeafenToggle = vi.fn();
|
||||
comp = createUserBar({ onDeafenToggle });
|
||||
comp.mount(container);
|
||||
|
||||
const deafenBtn = container.querySelector('[title="Deafen"]') as HTMLButtonElement;
|
||||
deafenBtn.click();
|
||||
expect(onDeafenToggle).toHaveBeenCalledOnce();
|
||||
});
|
||||
|
||||
it("does not throw when mute/deafen clicked without callbacks", () => {
|
||||
it("does not render mute or deafen buttons", () => {
|
||||
setAuthState({ username: "alice" }, true);
|
||||
comp = createUserBar();
|
||||
comp.mount(container);
|
||||
|
||||
const muteBtn = container.querySelector('[title="Mute"]') as HTMLButtonElement;
|
||||
const deafenBtn = container.querySelector('[title="Deafen"]') as HTMLButtonElement;
|
||||
expect(() => muteBtn.click()).not.toThrow();
|
||||
expect(() => deafenBtn.click()).not.toThrow();
|
||||
});
|
||||
|
||||
it("stops responding to clicks after destroy", () => {
|
||||
setAuthState({ username: "alice" }, true);
|
||||
const onMuteToggle = vi.fn();
|
||||
comp = createUserBar({ onMuteToggle });
|
||||
comp.mount(container);
|
||||
|
||||
const muteBtn = container.querySelector('[title="Mute"]') as HTMLButtonElement;
|
||||
comp.destroy?.();
|
||||
muteBtn.click();
|
||||
expect(onMuteToggle).not.toHaveBeenCalled();
|
||||
expect(container.querySelector('[title="Mute"]')).toBeNull();
|
||||
expect(container.querySelector('[title="Deafen"]')).toBeNull();
|
||||
});
|
||||
|
||||
it("destroy removes DOM and unsubscribes", () => {
|
||||
|
||||
Reference in New Issue
Block a user