TeaWeb/shared/js/ui/frames/control-bar/index.tsx

747 lines
No EOL
31 KiB
TypeScript

import * as React from "react";
import {Button} from "./button";
import {DropdownEntry} from "tc-shared/ui/frames/control-bar/dropdown";
import {Translatable} from "tc-shared/ui/react-elements/i18n";
import {ReactComponentBase} from "tc-shared/ui/react-elements/ReactComponentBase";
import {ConnectionEvents, ConnectionHandler, ConnectionStateUpdateType} from "tc-shared/ConnectionHandler";
import {Event, EventHandler, ReactEventHandler, Registry} from "tc-shared/events";
import {ConnectionManagerEvents, server_connections} from "tc-shared/ui/frames/connection_handlers";
import {Settings, settings} from "tc-shared/settings";
import {
add_server_to_bookmarks,
Bookmark,
bookmarks,
BookmarkType,
boorkmak_connect,
DirectoryBookmark,
find_bookmark
} from "tc-shared/bookmarks";
import {icon_cache_loader, IconManager} from "tc-shared/FileManager";
import * as contextmenu from "tc-shared/ui/elements/ContextMenu";
import {createInputModal} from "tc-shared/ui/elements/Modal";
import {default_recorder} from "tc-shared/voice/RecorderProfile";
import {global_client_actions} from "tc-shared/events/GlobalEvents";
const cssStyle = require("./index.scss");
const cssButtonStyle = require("./button.scss");
export interface ConnectionState {
connected: boolean;
connectedAnywhere: boolean;
}
@ReactEventHandler(obj => obj.props.event_registry)
class ConnectButton extends ReactComponentBase<{ multiSession: boolean; event_registry: Registry<InternalControlBarEvents> }, ConnectionState> {
protected defaultState(): ConnectionState {
return {
connected: false,
connectedAnywhere: false
}
}
render() {
let subentries = [];
if(this.props.multiSession) {
if(!this.state.connected) {
subentries.push(
<DropdownEntry key={"connect-server"} icon={"client-connect"} text={<Translatable message={"Connect to a server"} />}
onClick={ () => global_client_actions.fire("action_open_window_connect", {new_tab: false }) } />
);
} else {
subentries.push(
<DropdownEntry key={"disconnect-current-a"} icon={"client-disconnect"} text={<Translatable message={"Disconnect from current server"} />}
onClick={ () => this.props.event_registry.fire("action_disconnect", { globally: false }) }/>
);
}
if(this.state.connectedAnywhere) {
subentries.push(
<DropdownEntry key={"disconnect-current-b"} icon={"client-disconnect"} text={<Translatable message={"Disconnect from all servers"} />}
onClick={ () => this.props.event_registry.fire("action_disconnect", { globally: true }) }/>
);
}
subentries.push(
<DropdownEntry key={"connect-new-tab"} icon={"client-connect"} text={<Translatable message={"Connect to a server in another tab"} />}
onClick={ () => global_client_actions.fire("action_open_window_connect", { new_tab: true }) } />
);
}
if(!this.state.connected) {
return (
<Button colorTheme={"default"} autoSwitch={false} iconNormal={"client-connect"} tooltip={tr("Connect to a server")}
onToggle={ () => global_client_actions.fire("action_open_window_connect", { new_tab: false }) }>
{subentries}
</Button>
);
} else {
return (
<Button colorTheme={"default"} autoSwitch={false} iconNormal={"client-disconnect"} tooltip={tr("Disconnect from server")}
onToggle={ () => this.props.event_registry.fire("action_disconnect", { globally: false }) }>
{subentries}
</Button>
);
}
}
@EventHandler<InternalControlBarEvents>("update_connect_state")
private handleStateUpdate(state: ConnectionState) {
this.setState(state);
}
}
@ReactEventHandler(obj => obj.props.event_registry)
class BookmarkButton extends ReactComponentBase<{ event_registry: Registry<InternalControlBarEvents> }, {}> {
private button_ref: React.RefObject<Button>;
protected initialize() {
this.button_ref = React.createRef();
}
protected defaultState() {
return {};
}
render() {
const marks = bookmarks().content.map(e => e.type === BookmarkType.DIRECTORY ? this.renderDirectory(e) : this.renderBookmark(e));
if(marks.length)
marks.splice(0, 0, <hr key={"hr"} />);
return (
<Button ref={this.button_ref} dropdownButtonExtraClass={cssButtonStyle.buttonBookmarks} autoSwitch={false} iconNormal={"client-bookmark_manager"}>
<DropdownEntry icon={"client-bookmark_manager"} text={<Translatable message={"Manage bookmarks"} />}
onClick={() => this.props.event_registry.fire("action_open_window", { window: "bookmark-manage" })} />
<DropdownEntry icon={"client-bookmark_add"} text={<Translatable message={"Add current server to bookmarks"} />}
onClick={() => this.props.event_registry.fire("action_add_current_server_to_bookmarks")} />
{marks}
</Button>
)
}
private renderBookmark(bookmark: Bookmark) {
return (
<DropdownEntry key={bookmark.unique_id}
icon={icon_cache_loader.load_icon(bookmark.last_icon_id, bookmark.last_icon_server_id)}
text={bookmark.display_name}
onClick={BookmarkButton.onBookmarkClick.bind(undefined, bookmark.unique_id)}
onContextMenu={this.onBookmarkContextMenu.bind(this, bookmark.unique_id)}/>
);
}
private renderDirectory(directory: DirectoryBookmark) {
return (
<DropdownEntry key={directory.unique_id} text={directory.display_name} >
{directory.content.map(e => e.type === BookmarkType.DIRECTORY ? this.renderDirectory(e) : this.renderBookmark(e))}
</DropdownEntry>
)
}
private static onBookmarkClick(bookmark_id: string) {
const bookmark = find_bookmark(bookmark_id) as Bookmark;
if(!bookmark) return;
boorkmak_connect(bookmark, false);
}
private onBookmarkContextMenu(bookmark_id: string, event: MouseEvent) {
event.preventDefault();
const bookmark = find_bookmark(bookmark_id) as Bookmark;
if(!bookmark) return;
this.button_ref.current?.setState({ dropdownForceShow: true });
contextmenu.spawn_context_menu(event.pageX, event.pageY, {
type: contextmenu.MenuEntryType.ENTRY,
name: tr("Connect"),
icon_class: 'client-connect',
callback: () => boorkmak_connect(bookmark, false)
}, {
type: contextmenu.MenuEntryType.ENTRY,
name: tr("Connect in a new tab"),
icon_class: 'client-connect',
callback: () => boorkmak_connect(bookmark, true),
visible: !settings.static_global(Settings.KEY_DISABLE_MULTI_SESSION)
}, contextmenu.Entry.CLOSE(() => {
this.button_ref.current?.setState({ dropdownForceShow: false });
}));
}
@EventHandler<InternalControlBarEvents>("update_bookmarks")
private handleStateUpdate() {
this.forceUpdate();
}
}
export interface AwayState {
away: boolean;
awayAnywhere: boolean;
awayAll: boolean;
}
@ReactEventHandler(obj => obj.props.event_registry)
class AwayButton extends ReactComponentBase<{ event_registry: Registry<InternalControlBarEvents> }, AwayState> {
protected defaultState(): AwayState {
return {
away: false,
awayAnywhere: false,
awayAll: false
};
}
render() {
let dropdowns = [];
if(this.state.away) {
dropdowns.push(<DropdownEntry key={"cgo"} icon={"client-present"} text={<Translatable message={"Go online"} />}
onClick={() => this.props.event_registry.fire("action_disable_away", { globally: false })} />);
} else {
dropdowns.push(<DropdownEntry key={"sas"} icon={"client-away"} text={<Translatable message={"Set away on this server"} />}
onClick={() => this.props.event_registry.fire("action_set_away", { globally: false, prompt_reason: false })} />);
}
dropdowns.push(<DropdownEntry key={"sam"} icon={"client-away"} text={<Translatable message={"Set away message on this server"} />}
onClick={() => this.props.event_registry.fire("action_set_away", { globally: false, prompt_reason: true })} />);
dropdowns.push(<hr key={"-hr"} />);
if(this.state.awayAnywhere) {
dropdowns.push(<DropdownEntry key={"goa"} icon={"client-present"} text={<Translatable message={"Go online for all servers"} />}
onClick={() => this.props.event_registry.fire("action_disable_away", { globally: true })} />);
}
if(!this.state.awayAll) {
dropdowns.push(<DropdownEntry key={"saa"} icon={"client-away"} text={<Translatable message={"Set away on all servers"} />}
onClick={() => this.props.event_registry.fire("action_set_away", { globally: true, prompt_reason: false })} />);
}
dropdowns.push(<DropdownEntry key={"sama"} icon={"client-away"} text={<Translatable message={"Set away message for all servers"} />}
onClick={() => this.props.event_registry.fire("action_set_away", { globally: true, prompt_reason: true })} />);
/* switchable because we're switching it manually */
return (
<Button autoSwitch={false} switched={this.state.away} iconNormal={this.state.away ? "client-present" : "client-away"} onToggle={this.handleButtonToggled.bind(this)}>
{dropdowns}
</Button>
);
}
private handleButtonToggled(state: boolean) {
if(state)
this.props.event_registry.fire("action_set_away", { globally: false, prompt_reason: false });
else
this.props.event_registry.fire("action_disable_away");
}
@EventHandler<InternalControlBarEvents>("update_away_state")
private handleStateUpdate(state: AwayState) {
this.setState(state);
}
}
export interface ChannelSubscribeState {
subscribeEnabled: boolean;
}
@ReactEventHandler(obj => obj.props.event_registry)
class ChannelSubscribeButton extends ReactComponentBase<{ event_registry: Registry<InternalControlBarEvents> }, ChannelSubscribeState> {
protected defaultState(): ChannelSubscribeState {
return { subscribeEnabled: false };
}
render() {
return <Button switched={this.state.subscribeEnabled} autoSwitch={false} iconNormal={"client-unsubscribe_from_all_channels"} iconSwitched={"client-subscribe_to_all_channels"}
onToggle={flag => this.props.event_registry.fire("action_set_subscribe", { subscribe: flag })}/>;
}
@EventHandler<InternalControlBarEvents>("update_subscribe_state")
private handleStateUpdate(state: ChannelSubscribeState) {
this.setState(state);
}
}
export interface MicrophoneState {
enabled: boolean;
muted: boolean;
}
@ReactEventHandler(obj => obj.props.event_registry)
class MicrophoneButton extends ReactComponentBase<{ event_registry: Registry<InternalControlBarEvents> }, MicrophoneState> {
protected defaultState(): MicrophoneState {
return {
enabled: false,
muted: false
};
}
render() {
if(!this.state.enabled)
return <Button autoSwitch={false} iconNormal={"client-activate_microphone"} tooltip={tr("Enable your microphone on this server")}
onToggle={() => this.props.event_registry.fire("action_enable_microphone")} />;
if(this.state.muted)
return <Button switched={true} colorTheme={"red"} autoSwitch={false} iconNormal={"client-input_muted"} tooltip={tr("Unmute microphone")}
onToggle={() => this.props.event_registry.fire("action_enable_microphone")} />;
return <Button colorTheme={"red"} autoSwitch={false} iconNormal={"client-input_muted"} tooltip={tr("Mute microphone")}
onToggle={() => this.props.event_registry.fire("action_disable_microphone")} />;
}
@EventHandler<InternalControlBarEvents>("update_microphone_state")
private handleStateUpdate(state: MicrophoneState) {
this.setState(state);
}
}
export interface SpeakerState {
muted: boolean;
}
@ReactEventHandler(obj => obj.props.event_registry)
class SpeakerButton extends ReactComponentBase<{ event_registry: Registry<InternalControlBarEvents> }, SpeakerState> {
protected defaultState(): SpeakerState {
return {
muted: false
};
}
render() {
if(this.state.muted)
return <Button switched={true} colorTheme={"red"} autoSwitch={false} iconNormal={"client-output_muted"} tooltip={tr("Unmute headphones")}
onToggle={() => this.props.event_registry.fire("action_enable_speaker")}/>;
return <Button colorTheme={"red"} autoSwitch={false} iconNormal={"client-output_muted"} tooltip={tr("Mute headphones")}
onToggle={() => this.props.event_registry.fire("action_disable_speaker")}/>;
}
@EventHandler<InternalControlBarEvents>("update_speaker_state")
private handleStateUpdate(state: SpeakerState) {
this.setState(state);
}
}
export interface QueryState {
queryShown: boolean;
}
@ReactEventHandler(obj => obj.props.event_registry)
class QueryButton extends ReactComponentBase<{ event_registry: Registry<InternalControlBarEvents> }, QueryState> {
protected defaultState() {
return {
queryShown: false
};
}
render() {
let toggle;
if(this.state.queryShown)
toggle = <DropdownEntry key={"query-show"} icon={"client-toggle_server_query_clients"} text={<Translatable message={"Hide server queries"} />}
onClick={() => this.props.event_registry.fire("action_toggle_query", { shown: false })}/>;
else
toggle = <DropdownEntry key={"query-hide"} icon={"client-toggle_server_query_clients"} text={<Translatable message={"Show server queries"} />}
onClick={() => this.props.event_registry.fire("action_toggle_query", { shown: true })}/>;
return (
<Button switched={this.state.queryShown} autoSwitch={false} iconNormal={"client-server_query"}
onToggle={flag => this.props.event_registry.fire("action_toggle_query", { shown: flag })}>
{toggle}
<DropdownEntry icon={"client-server_query"} text={<Translatable message={"Manage server queries"} />}
onClick={() => this.props.event_registry.fire("action_open_window", { window: "query-manage" })}/>
</Button>
)
}
@EventHandler<InternalControlBarEvents>("update_query_state")
private handleStateUpdate(state: QueryState) {
this.setState(state);
}
}
export interface HostButtonState {
url?: string;
title?: string;
target_url?: string;
}
@ReactEventHandler(obj => obj.props.event_registry)
class HostButton extends ReactComponentBase<{ event_registry: Registry<InternalControlBarEvents> }, HostButtonState> {
protected defaultState() {
return {
url: undefined,
target_url: undefined
};
}
render() {
if(!this.state.url)
return null;
return (
<a
className={this.classList(cssButtonStyle.button, cssButtonStyle.buttonHostbutton)}
title={this.state.title || tr("Hostbutton")}
href={this.state.target_url || this.state.url}
target={"_blank"} /* just to ensure */
onClick={this.onClick.bind(this)}>
<img alt={tr("Hostbutton")} src={this.state.url} />
</a>
);
}
private onClick(event: MouseEvent) {
window.open(this.state.target_url || this.state.url, '_blank');
event.preventDefault();
}
@EventHandler<InternalControlBarEvents>("update_host_button")
private handleStateUpdate(state: HostButtonState) {
this.setState(state);
}
}
export interface ControlBarProperties {
multiSession: boolean;
}
@ReactEventHandler<ControlBar>(obj => obj.event_registry)
export class ControlBar extends React.Component<ControlBarProperties, {}> {
private readonly event_registry: Registry<InternalControlBarEvents>;
private connection: ConnectionHandler;
private connection_handler_callbacks = {
notify_state_updated: this.handleConnectionHandlerStateChange.bind(this),
notify_connection_state_changed: this.handleConnectionHandlerConnectionStateChange.bind(this)
};
private connection_manager_callbacks = {
active_handler_changed: this.handleActiveConnectionHandlerChanged.bind(this)
};
constructor(props) {
super(props);
this.event_registry = new Registry<InternalControlBarEvents>();
this.event_registry.enable_debug("control-bar");
initialize(this.event_registry);
}
events() : Registry<InternalControlBarEvents> { return this.event_registry; }
render() {
return (
<div className={cssStyle.controlBar}>
<ConnectButton event_registry={this.event_registry} multiSession={this.props.multiSession} />
<BookmarkButton event_registry={this.event_registry} />
<div className={cssStyle.divider} />
<AwayButton event_registry={this.event_registry} />
<MicrophoneButton event_registry={this.event_registry} />
<SpeakerButton event_registry={this.event_registry} />
<div className={cssStyle.divider} />
<ChannelSubscribeButton event_registry={this.event_registry} />
<QueryButton event_registry={this.event_registry} />
<div className={cssStyle.spacer} />
<HostButton event_registry={this.event_registry} />
</div>
)
}
private handleActiveConnectionHandlerChanged(event: ConnectionManagerEvents["notify_active_handler_changed"]) {
if(event.old_handler)
this.unregisterConnectionHandlerEvents(event.old_handler);
this.connection = event.new_handler;
if(event.new_handler)
this.registerConnectionHandlerEvents(event.new_handler);
this.event_registry.fire("set_connection_handler", { handler: this.connection });
this.event_registry.fire("update_state_all");
}
private unregisterConnectionHandlerEvents(target: ConnectionHandler) {
const events = target.events();
events.off("notify_state_updated", this.connection_handler_callbacks.notify_state_updated);
events.off("notify_connection_state_changed", this.connection_handler_callbacks.notify_connection_state_changed);
//FIXME: Add the host button here!
}
private registerConnectionHandlerEvents(target: ConnectionHandler) {
const events = target.events();
events.on("notify_state_updated", this.connection_handler_callbacks.notify_state_updated);
events.on("notify_connection_state_changed", this.connection_handler_callbacks.notify_connection_state_changed);
}
componentDidMount(): void {
server_connections.events().on("notify_active_handler_changed", this.connection_manager_callbacks.active_handler_changed);
this.event_registry.fire("set_connection_handler", { handler: server_connections.active_connection() });
}
componentWillUnmount(): void {
server_connections.events().off("notify_active_handler_changed", this.connection_manager_callbacks.active_handler_changed);
}
/* Active server connection handler events */
private handleConnectionHandlerStateChange(event: ConnectionEvents["notify_state_updated"]) {
const type_mapping: {[T in ConnectionStateUpdateType]:ControlStateUpdateType[]} = {
"microphone": ["microphone"],
"speaker": ["speaker"],
"away": ["away"],
"subscribe": ["subscribe-mode"],
"query": ["query"]
};
for(const type of type_mapping[event.state] || [])
this.event_registry.fire("update_state", { state: type });
}
private handleConnectionHandlerConnectionStateChange(/* event: ConnectionEvents["notify_connection_state_changed"] */) {
this.event_registry.fire("update_state", { state: "connect-state" });
}
/* own update & state gathering events */
@EventHandler<InternalControlBarEvents>(["update_state_all", "update_state"])
private updateStateHostButton(event: Event<InternalControlBarEvents>) {
if(event.type === "update_state")
if(event.as<"update_state">().state !== "host-button" && event.as<"update_state">().state !== "connect-state")
return;
const server_props = this.connection?.channelTree.server?.properties;
if(!this.connection?.connected || !server_props || !server_props.virtualserver_hostbutton_gfx_url) {
this.event_registry.fire("update_host_button", {
url: undefined,
target_url: undefined,
title: undefined
});
return;
}
this.event_registry.fire("update_host_button", {
url: server_props.virtualserver_hostbutton_gfx_url,
target_url: server_props.virtualserver_hostbutton_url,
title: server_props.virtualserver_hostbutton_tooltip
});
}
@EventHandler<InternalControlBarEvents>(["update_state_all", "update_state"])
private updateStateSubscribe(event: Event<InternalControlBarEvents>) {
if(event.type === "update_state")
if(event.as<"update_state">().state !== "subscribe-mode")
return;
this.event_registry.fire("update_subscribe_state", {
subscribeEnabled: !!this.connection?.isSubscribeToAllChannels()
});
}
@EventHandler<InternalControlBarEvents>(["update_state_all", "update_state"])
private updateStateConnect(event: Event<InternalControlBarEvents>) {
if(event.type === "update_state")
if(event.as<"update_state">().state !== "connect-state")
return;
this.event_registry.fire("update_connect_state", {
connectedAnywhere: server_connections.all_connections().findIndex(e => e.connected) !== -1,
connected: !!this.connection?.connected
});
}
@EventHandler<InternalControlBarEvents>(["update_state_all", "update_state"])
private updateStateAway(event: Event<InternalControlBarEvents>) {
if(event.type === "update_state")
if(event.as<"update_state">().state !== "away")
return;
const connections = server_connections.all_connections();
const away_connections = server_connections.all_connections().filter(e => e.isAway());
const away_status = !!this.connection?.isAway();
this.event_registry.fire("update_away_state", {
awayAnywhere: away_connections.length > 0,
away: away_status,
awayAll: connections.length === away_connections.length
});
}
@EventHandler<InternalControlBarEvents>(["update_state_all", "update_state"])
private updateStateMicrophone(event: Event<InternalControlBarEvents>) {
if(event.type === "update_state")
if(event.as<"update_state">().state !== "microphone")
return;
this.event_registry.fire("update_microphone_state", {
enabled: !this.connection?.isMicrophoneDisabled(),
muted: !!this.connection?.isMicrophoneMuted()
});
}
@EventHandler<InternalControlBarEvents>(["update_state_all", "update_state"])
private updateStateSpeaker(event: Event<InternalControlBarEvents>) {
if(event.type === "update_state")
if(event.as<"update_state">().state !== "speaker")
return;
this.event_registry.fire("update_speaker_state", {
muted: !!this.connection?.isSpeakerMuted()
});
}
@EventHandler<InternalControlBarEvents>(["update_state_all", "update_state"])
private updateStateQuery(event: Event<InternalControlBarEvents>) {
if(event.type === "update_state")
if(event.as<"update_state">().state !== "query")
return;
this.event_registry.fire("update_query_state", {
queryShown: !!this.connection?.areQueriesShown()
});
}
@EventHandler<InternalControlBarEvents>(["update_state_all", "update_state"])
private updateStateBookmarks(event: Event<InternalControlBarEvents>) {
if(event.type === "update_state")
if(event.as<"update_state">().state !== "bookmarks")
return;
this.event_registry.fire("update_bookmarks");
}
}
let react_reference_: React.RefObject<ControlBar>;
export function react_reference() { return react_reference_ || (react_reference_ = React.createRef()); }
export function control_bar_instance() : ControlBar | undefined {
return react_reference_?.current;
}
export type ControlStateUpdateType = "host-button" | "bookmarks" | "subscribe-mode" | "connect-state" | "away" | "microphone" | "speaker" | "query";
export interface ControlBarEvents {
update_state: {
state: "host-button" | "bookmarks" | "subscribe-mode" | "connect-state" | "away" | "microphone" | "speaker" | "query"
},
server_updated: {
handler: ConnectionHandler,
category: "audio" | "settings-initialized" | "connection-state" | "away-status" | "hostbanner"
}
}
export interface InternalControlBarEvents extends ControlBarEvents {
/* update the UI */
update_host_button: HostButtonState;
update_subscribe_state: ChannelSubscribeState;
update_connect_state: ConnectionState;
update_away_state: AwayState;
update_microphone_state: MicrophoneState;
update_speaker_state: SpeakerState;
update_query_state: QueryState;
update_bookmarks: {},
update_state_all: { },
/* UI-Actions */
action_set_subscribe: { subscribe: boolean },
action_disconnect: { globally: boolean },
action_enable_microphone: {}, /* enable/unmute microphone */
action_disable_microphone: {},
action_enable_speaker: {},
action_disable_speaker: {},
action_disable_away: {
globally: boolean
},
action_set_away: {
globally: boolean;
prompt_reason: boolean;
},
action_toggle_query: {
shown: boolean
},
action_open_window: {
window: "bookmark-manage" | "query-manage"
},
action_add_current_server_to_bookmarks: {},
/* manly used for the action handler */
set_connection_handler: {
handler?: ConnectionHandler
}
}
function initialize(event_registry: Registry<InternalControlBarEvents>) {
let current_connection_handler: ConnectionHandler;
event_registry.on("set_connection_handler", event => current_connection_handler = event.handler);
event_registry.on("action_disconnect", event => {
(event.globally ? server_connections.all_connections() : [server_connections.active_connection()]).filter(e => !!e).forEach(connection => {
connection.disconnectFromServer();
});
});
event_registry.on("action_set_away", event => {
const set_away = message => {
const value = typeof message === "string" ? message : true;
(event.globally ? server_connections.all_connections() : [server_connections.active_connection()]).filter(e => !!e).forEach(connection => {
connection.setAway(value);
});
settings.changeGlobal(Settings.KEY_CLIENT_STATE_AWAY, true);
settings.changeGlobal(Settings.KEY_CLIENT_AWAY_MESSAGE, typeof value === "boolean" ? "" : value);
};
if(event.prompt_reason) {
createInputModal(tr("Set away message"), tr("Please enter your away message"), () => true, message => {
if(typeof(message) === "string")
set_away(message);
}).open();
} else {
set_away(undefined);
}
});
event_registry.on("action_disable_away", event => {
for(const connection of event.globally ? server_connections.all_connections() : [server_connections.active_connection()]) {
if(!connection) continue;
connection.setAway(false);
}
settings.changeGlobal(Settings.KEY_CLIENT_STATE_AWAY, false);
});
event_registry.on(["action_enable_microphone", "action_disable_microphone"], event => {
const state = event.type === "action_enable_microphone";
/* change the default global setting */
settings.changeGlobal(Settings.KEY_CLIENT_STATE_MICROPHONE_MUTED, !state);
if(current_connection_handler) {
current_connection_handler.setMicrophoneMuted(!state);
if(!current_connection_handler.getVoiceRecorder())
current_connection_handler.acquire_recorder(default_recorder, true); /* acquire_recorder already updates the voice status */
}
});
event_registry.on(["action_enable_speaker", "action_disable_speaker"], event => {
const state = event.type === "action_enable_speaker";
/* change the default global setting */
settings.changeGlobal(Settings.KEY_CLIENT_STATE_SPEAKER_MUTED, !state);
current_connection_handler?.setSpeakerMuted(!state);
});
event_registry.on("action_set_subscribe", event => {
/* change the default global setting */
settings.changeGlobal(Settings.KEY_CLIENT_STATE_SUBSCRIBE_ALL_CHANNELS, event.subscribe);
current_connection_handler?.setSubscribeToAllChannels(event.subscribe);
});
event_registry.on("action_toggle_query", event => {
/* change the default global setting */
settings.changeGlobal(Settings.KEY_CLIENT_STATE_QUERY_SHOWN, event.shown);
current_connection_handler?.setQueriesShown(event.shown);
});
event_registry.on("action_add_current_server_to_bookmarks", () => add_server_to_bookmarks(current_connection_handler));
event_registry.on("action_open_window", event => {
switch (event.window) {
case "bookmark-manage":
global_client_actions.fire("action_open_window", { window: "bookmark-manage", connection: current_connection_handler });
return;
case "query-manage":
global_client_actions.fire("action_open_window", { window: "query-manage", connection: current_connection_handler });
return;
}
})
}