Finalizing the 1.5.3 client
This commit is contained in:
parent
145f1ff0b1
commit
4a19f3a827
2
github
2
github
|
@ -1 +1 @@
|
||||||
Subproject commit 35052680fe58de01102dfd4b65835df08c2a7f20
|
Subproject commit 90d3a6c84c003ab42a3ecfb5197b9368897862b1
|
|
@ -45,9 +45,9 @@ export declare class BookmarkManager {
|
||||||
private readonly registeredBookmarks;
|
private readonly registeredBookmarks;
|
||||||
private defaultBookmarkCreated;
|
private defaultBookmarkCreated;
|
||||||
constructor();
|
constructor();
|
||||||
private loadBookmarks;
|
loadBookmarks(): Promise<void>;
|
||||||
private importOldBookmarks;
|
private importOldBookmarks;
|
||||||
private saveBookmarks;
|
saveBookmarks(): Promise<void>;
|
||||||
getRegisteredBookmarks(): BookmarkEntry[];
|
getRegisteredBookmarks(): BookmarkEntry[];
|
||||||
getOrderedRegisteredBookmarks(): OrderedBookmarkEntry[];
|
getOrderedRegisteredBookmarks(): OrderedBookmarkEntry[];
|
||||||
findBookmark(uniqueId: string): BookmarkEntry | undefined;
|
findBookmark(uniqueId: string): BookmarkEntry | undefined;
|
||||||
|
|
|
@ -104,6 +104,7 @@ export declare class ConnectionHandler {
|
||||||
settings: ServerSettings;
|
settings: ServerSettings;
|
||||||
sound: SoundManager;
|
sound: SoundManager;
|
||||||
serverFeatures: ServerFeatures;
|
serverFeatures: ServerFeatures;
|
||||||
|
log: ServerEventLog;
|
||||||
private sideBar;
|
private sideBar;
|
||||||
private playlistManager;
|
private playlistManager;
|
||||||
private channelConversations;
|
private channelConversations;
|
||||||
|
@ -116,13 +117,12 @@ export declare class ConnectionHandler {
|
||||||
private connectAttemptId;
|
private connectAttemptId;
|
||||||
private echoTestRunning;
|
private echoTestRunning;
|
||||||
private pluginCmdRegistry;
|
private pluginCmdRegistry;
|
||||||
private client_status;
|
private handlerState;
|
||||||
private clientStatusSync;
|
private clientStatusSync;
|
||||||
private inputHardwareState;
|
private inputHardwareState;
|
||||||
private listenerRecorderInputDeviceChanged;
|
private listenerRecorderInputDeviceChanged;
|
||||||
log: ServerEventLog;
|
|
||||||
constructor();
|
constructor();
|
||||||
initialize_client_state(source?: ConnectionHandler): void;
|
initializeHandlerState(source?: ConnectionHandler): void;
|
||||||
events(): Registry<ConnectionEvents>;
|
events(): Registry<ConnectionEvents>;
|
||||||
startConnectionNew(parameters: ConnectParameters, autoReconnectAttempt: boolean): Promise<void>;
|
startConnectionNew(parameters: ConnectParameters, autoReconnectAttempt: boolean): Promise<void>;
|
||||||
startConnection(addr: string, profile: ConnectionProfile, user_action: boolean, parameters: ConnectParametersOld): Promise<void>;
|
startConnection(addr: string, profile: ConnectionProfile, user_action: boolean, parameters: ConnectParametersOld): Promise<void>;
|
||||||
|
@ -142,7 +142,6 @@ export declare class ConnectionHandler {
|
||||||
private _certificate_modal;
|
private _certificate_modal;
|
||||||
handleDisconnect(type: DisconnectReason, data?: any): void;
|
handleDisconnect(type: DisconnectReason, data?: any): void;
|
||||||
cancelAutoReconnect(log_event: boolean): void;
|
cancelAutoReconnect(log_event: boolean): void;
|
||||||
private on_connection_state_changed;
|
|
||||||
private updateVoiceStatus;
|
private updateVoiceStatus;
|
||||||
private lastRecordErrorPopup;
|
private lastRecordErrorPopup;
|
||||||
update_voice_status(): void;
|
update_voice_status(): void;
|
||||||
|
@ -156,7 +155,6 @@ export declare class ConnectionHandler {
|
||||||
}>;
|
}>;
|
||||||
getVoiceRecorder(): RecorderProfile | undefined;
|
getVoiceRecorder(): RecorderProfile | undefined;
|
||||||
reconnect_properties(profile?: ConnectionProfile): ConnectParametersOld;
|
reconnect_properties(profile?: ConnectionProfile): ConnectParametersOld;
|
||||||
update_avatar(): void;
|
|
||||||
private initializeWhisperSession;
|
private initializeWhisperSession;
|
||||||
destroy(): void;
|
destroy(): void;
|
||||||
setMicrophoneMuted(muted: boolean, dontPlaySound?: boolean): void;
|
setMicrophoneMuted(muted: boolean, dontPlaySound?: boolean): void;
|
||||||
|
@ -192,8 +190,5 @@ export interface ConnectionEvents {
|
||||||
oldState: ConnectionState;
|
oldState: ConnectionState;
|
||||||
newState: ConnectionState;
|
newState: ConnectionState;
|
||||||
};
|
};
|
||||||
notify_visibility_changed: {
|
|
||||||
visible: boolean;
|
|
||||||
};
|
|
||||||
notify_handler_initialized: {};
|
notify_handler_initialized: {};
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
export declare class Mutex<T> {
|
||||||
|
private value;
|
||||||
|
private taskExecuting;
|
||||||
|
private taskQueue;
|
||||||
|
private freeListener;
|
||||||
|
constructor(value: T);
|
||||||
|
isFree(): boolean;
|
||||||
|
awaitFree(): Promise<void>;
|
||||||
|
execute<R>(callback: (value: T, setValue: (newValue: T) => void) => R | Promise<R>): Promise<R>;
|
||||||
|
tryExecute<R>(callback: (value: T, setValue: (newValue: T) => void) => R | Promise<R>): Promise<{
|
||||||
|
status: "success";
|
||||||
|
result: R;
|
||||||
|
} | {
|
||||||
|
status: "would-block";
|
||||||
|
}>;
|
||||||
|
private executeNextTask;
|
||||||
|
private triggerFinished;
|
||||||
|
}
|
|
@ -1,122 +1,3 @@
|
||||||
export declare enum KeyCode {
|
|
||||||
KEY_CANCEL = 3,
|
|
||||||
KEY_HELP = 6,
|
|
||||||
KEY_BACK_SPACE = 8,
|
|
||||||
KEY_TAB = 9,
|
|
||||||
KEY_CLEAR = 12,
|
|
||||||
KEY_RETURN = 13,
|
|
||||||
KEY_ENTER = 14,
|
|
||||||
KEY_SHIFT = 16,
|
|
||||||
KEY_CONTROL = 17,
|
|
||||||
KEY_ALT = 18,
|
|
||||||
KEY_PAUSE = 19,
|
|
||||||
KEY_CAPS_LOCK = 20,
|
|
||||||
KEY_ESCAPE = 27,
|
|
||||||
KEY_SPACE = 32,
|
|
||||||
KEY_PAGE_UP = 33,
|
|
||||||
KEY_PAGE_DOWN = 34,
|
|
||||||
KEY_END = 35,
|
|
||||||
KEY_HOME = 36,
|
|
||||||
KEY_LEFT = 37,
|
|
||||||
KEY_UP = 38,
|
|
||||||
KEY_RIGHT = 39,
|
|
||||||
KEY_DOWN = 40,
|
|
||||||
KEY_PRINTSCREEN = 44,
|
|
||||||
KEY_INSERT = 45,
|
|
||||||
KEY_DELETE = 46,
|
|
||||||
KEY_0 = 48,
|
|
||||||
KEY_1 = 49,
|
|
||||||
KEY_2 = 50,
|
|
||||||
KEY_3 = 51,
|
|
||||||
KEY_4 = 52,
|
|
||||||
KEY_5 = 53,
|
|
||||||
KEY_6 = 54,
|
|
||||||
KEY_7 = 55,
|
|
||||||
KEY_8 = 56,
|
|
||||||
KEY_9 = 57,
|
|
||||||
KEY_SEMICOLON = 59,
|
|
||||||
KEY_EQUALS = 61,
|
|
||||||
KEY_A = 65,
|
|
||||||
KEY_B = 66,
|
|
||||||
KEY_C = 67,
|
|
||||||
KEY_D = 68,
|
|
||||||
KEY_E = 69,
|
|
||||||
KEY_F = 70,
|
|
||||||
KEY_G = 71,
|
|
||||||
KEY_H = 72,
|
|
||||||
KEY_I = 73,
|
|
||||||
KEY_J = 74,
|
|
||||||
KEY_K = 75,
|
|
||||||
KEY_L = 76,
|
|
||||||
KEY_M = 77,
|
|
||||||
KEY_N = 78,
|
|
||||||
KEY_O = 79,
|
|
||||||
KEY_P = 80,
|
|
||||||
KEY_Q = 81,
|
|
||||||
KEY_R = 82,
|
|
||||||
KEY_S = 83,
|
|
||||||
KEY_T = 84,
|
|
||||||
KEY_U = 85,
|
|
||||||
KEY_V = 86,
|
|
||||||
KEY_W = 87,
|
|
||||||
KEY_X = 88,
|
|
||||||
KEY_Y = 89,
|
|
||||||
KEY_Z = 90,
|
|
||||||
KEY_LEFT_CMD = 91,
|
|
||||||
KEY_RIGHT_CMD = 93,
|
|
||||||
KEY_CONTEXT_MENU = 93,
|
|
||||||
KEY_NUMPAD0 = 96,
|
|
||||||
KEY_NUMPAD1 = 97,
|
|
||||||
KEY_NUMPAD2 = 98,
|
|
||||||
KEY_NUMPAD3 = 99,
|
|
||||||
KEY_NUMPAD4 = 100,
|
|
||||||
KEY_NUMPAD5 = 101,
|
|
||||||
KEY_NUMPAD6 = 102,
|
|
||||||
KEY_NUMPAD7 = 103,
|
|
||||||
KEY_NUMPAD8 = 104,
|
|
||||||
KEY_NUMPAD9 = 105,
|
|
||||||
KEY_MULTIPLY = 106,
|
|
||||||
KEY_ADD = 107,
|
|
||||||
KEY_SEPARATOR = 108,
|
|
||||||
KEY_SUBTRACT = 109,
|
|
||||||
KEY_DECIMAL = 110,
|
|
||||||
KEY_DIVIDE = 111,
|
|
||||||
KEY_F1 = 112,
|
|
||||||
KEY_F2 = 113,
|
|
||||||
KEY_F3 = 114,
|
|
||||||
KEY_F4 = 115,
|
|
||||||
KEY_F5 = 116,
|
|
||||||
KEY_F6 = 117,
|
|
||||||
KEY_F7 = 118,
|
|
||||||
KEY_F8 = 119,
|
|
||||||
KEY_F9 = 120,
|
|
||||||
KEY_F10 = 121,
|
|
||||||
KEY_F11 = 122,
|
|
||||||
KEY_F12 = 123,
|
|
||||||
KEY_F13 = 124,
|
|
||||||
KEY_F14 = 125,
|
|
||||||
KEY_F15 = 126,
|
|
||||||
KEY_F16 = 127,
|
|
||||||
KEY_F17 = 128,
|
|
||||||
KEY_F18 = 129,
|
|
||||||
KEY_F19 = 130,
|
|
||||||
KEY_F20 = 131,
|
|
||||||
KEY_F21 = 132,
|
|
||||||
KEY_F22 = 133,
|
|
||||||
KEY_F23 = 134,
|
|
||||||
KEY_F24 = 135,
|
|
||||||
KEY_NUM_LOCK = 144,
|
|
||||||
KEY_SCROLL_LOCK = 145,
|
|
||||||
KEY_COMMA = 188,
|
|
||||||
KEY_PERIOD = 190,
|
|
||||||
KEY_SLASH = 191,
|
|
||||||
KEY_BACK_QUOTE = 192,
|
|
||||||
KEY_OPEN_BRACKET = 219,
|
|
||||||
KEY_BACK_SLASH = 220,
|
|
||||||
KEY_CLOSE_BRACKET = 221,
|
|
||||||
KEY_QUOTE = 222,
|
|
||||||
KEY_META = 224
|
|
||||||
}
|
|
||||||
export declare enum EventType {
|
export declare enum EventType {
|
||||||
KEY_PRESS = 0,
|
KEY_PRESS = 0,
|
||||||
KEY_RELEASE = 1,
|
KEY_RELEASE = 1,
|
||||||
|
@ -139,14 +20,17 @@ export interface KeyEvent extends KeyDescriptor {
|
||||||
readonly type: EventType;
|
readonly type: EventType;
|
||||||
readonly key: string;
|
readonly key: string;
|
||||||
}
|
}
|
||||||
export interface KeyHook extends KeyDescriptor {
|
export interface KeyHook extends Partial<KeyDescriptor> {
|
||||||
callbackPress: () => any;
|
callbackPress: () => any;
|
||||||
callbackRelease: () => any;
|
callbackRelease: () => any;
|
||||||
}
|
}
|
||||||
|
interface RegisteredKeyHook extends KeyHook {
|
||||||
|
triggered: boolean;
|
||||||
|
}
|
||||||
export interface KeyBoardBackend {
|
export interface KeyBoardBackend {
|
||||||
registerListener(listener: (event: KeyEvent) => void): any;
|
registerListener(listener: (event: KeyEvent) => void): any;
|
||||||
unregisterListener(listener: (event: KeyEvent) => void): any;
|
unregisterListener(listener: (event: KeyEvent) => void): any;
|
||||||
registerHook(hook: KeyHook): any;
|
registerHook(hook: KeyHook): () => void;
|
||||||
unregisterHook(hook: KeyHook): any;
|
unregisterHook(hook: KeyHook): any;
|
||||||
isKeyPressed(key: string | SpecialKey): boolean;
|
isKeyPressed(key: string | SpecialKey): boolean;
|
||||||
}
|
}
|
||||||
|
@ -156,18 +40,19 @@ export declare class AbstractKeyBoard implements KeyBoardBackend {
|
||||||
[key: number]: boolean;
|
[key: number]: boolean;
|
||||||
};
|
};
|
||||||
protected readonly activeKeys: any;
|
protected readonly activeKeys: any;
|
||||||
protected registeredKeyHooks: KeyHook[];
|
protected registeredKeyHooks: RegisteredKeyHook[];
|
||||||
protected activeKeyHooks: KeyHook[];
|
|
||||||
constructor();
|
constructor();
|
||||||
protected destroy(): void;
|
protected destroy(): void;
|
||||||
isKeyPressed(key: string | SpecialKey): boolean;
|
isKeyPressed(key: string | SpecialKey): boolean;
|
||||||
registerHook(hook: KeyHook): void;
|
registerHook(hook: KeyHook): () => void;
|
||||||
unregisterHook(hook: KeyHook): void;
|
unregisterHook(hook: KeyHook): void;
|
||||||
registerListener(listener: (event: KeyEvent) => void): void;
|
registerListener(listener: (event: KeyEvent) => void): void;
|
||||||
unregisterListener(listener: (event: KeyEvent) => void): void;
|
unregisterListener(listener: (event: KeyEvent) => void): void;
|
||||||
|
private shouldHookBeActive;
|
||||||
protected fireKeyEvent(event: KeyEvent): void;
|
protected fireKeyEvent(event: KeyEvent): void;
|
||||||
protected resetKeyboardState(): void;
|
protected resetKeyboardState(): void;
|
||||||
}
|
}
|
||||||
export declare function getKeyBoard(): KeyBoardBackend;
|
export declare function getKeyBoard(): KeyBoardBackend;
|
||||||
export declare function setKeyBoardBackend(newBackend: KeyBoardBackend): void;
|
export declare function setKeyBoardBackend(newBackend: KeyBoardBackend): void;
|
||||||
export declare function getKeyDescription(key: KeyDescriptor): string;
|
export declare function getKeyDescription(key: KeyDescriptor): string;
|
||||||
|
export {};
|
||||||
|
|
|
@ -23,6 +23,7 @@ export declare type CachedClientInfo = {
|
||||||
status: ClientStatusInfo;
|
status: ClientStatusInfo;
|
||||||
forumAccount: ClientForumInfo | undefined;
|
forumAccount: ClientForumInfo | undefined;
|
||||||
channelGroup: number;
|
channelGroup: number;
|
||||||
|
channelGroupInheritedChannel: number;
|
||||||
serverGroups: number[];
|
serverGroups: number[];
|
||||||
version: ClientVersionInfo;
|
version: ClientVersionInfo;
|
||||||
};
|
};
|
||||||
|
@ -52,5 +53,6 @@ export declare class SelectedClientInfo {
|
||||||
private updateCachedCountry;
|
private updateCachedCountry;
|
||||||
private updateCachedVolume;
|
private updateCachedVolume;
|
||||||
private updateForumAccount;
|
private updateForumAccount;
|
||||||
|
private updateChannelGroup;
|
||||||
private initializeClientInfo;
|
private initializeClientInfo;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
import { RegistryKey, RegistryValueType, ValuedRegistryKey } from "tc-shared/settings";
|
||||||
|
export declare class ServerSettings {
|
||||||
|
private cacheServer;
|
||||||
|
private settingsDestroyed;
|
||||||
|
private serverUniqueId;
|
||||||
|
private serverSaveWorker;
|
||||||
|
private serverSettingsUpdated;
|
||||||
|
constructor();
|
||||||
|
destroy(): void;
|
||||||
|
getValue<V extends RegistryValueType, DV>(key: RegistryKey<V>, defaultValue: DV): V | DV;
|
||||||
|
getValue<V extends RegistryValueType>(key: ValuedRegistryKey<V>, defaultValue?: V): V;
|
||||||
|
setValue<T extends RegistryValueType>(key: RegistryKey<T>, value?: T): void;
|
||||||
|
setServerUniqueId(serverUniqueId: string): void;
|
||||||
|
save(): void;
|
||||||
|
}
|
||||||
|
export interface ServerSettingsStorage {
|
||||||
|
get(serverUniqueId: string): string;
|
||||||
|
set(serverUniqueId: string, value: string): any;
|
||||||
|
}
|
||||||
|
export declare function setServerSettingsStorage(storage: ServerSettingsStorage): void;
|
|
@ -0,0 +1,16 @@
|
||||||
|
/**
|
||||||
|
* Application storage meant for small and medium large internal app states.
|
||||||
|
* Possible data would be non user editable cached values like auth tokens.
|
||||||
|
* Note:
|
||||||
|
* 1. Please consider using a Settings key first before using the storage adapter!
|
||||||
|
* 2. The values may not be synced across multiple window instances.
|
||||||
|
* Don't use this for IPC.
|
||||||
|
*/
|
||||||
|
export interface StorageAdapter {
|
||||||
|
has(key: string): Promise<boolean>;
|
||||||
|
get(key: string): Promise<string | null>;
|
||||||
|
set(key: string, value: string): Promise<void>;
|
||||||
|
delete(key: string): Promise<void>;
|
||||||
|
}
|
||||||
|
export declare function getStorageAdapter(): StorageAdapter;
|
||||||
|
export declare function setStorageAdapter(adapter: StorageAdapter): void;
|
|
@ -3,6 +3,10 @@ export interface OutputDevice {
|
||||||
driver: string;
|
driver: string;
|
||||||
name: string;
|
name: string;
|
||||||
}
|
}
|
||||||
|
export declare namespace OutputDevice {
|
||||||
|
const NoDeviceId = "none";
|
||||||
|
const DefaultDeviceId = "default";
|
||||||
|
}
|
||||||
export interface AudioBackendEvents {
|
export interface AudioBackendEvents {
|
||||||
notify_initialized: {};
|
notify_initialized: {};
|
||||||
notify_volume_changed: {
|
notify_volume_changed: {
|
||||||
|
|
|
@ -4,8 +4,6 @@ export interface AudioRecorderBacked {
|
||||||
createInput(): AbstractInput;
|
createInput(): AbstractInput;
|
||||||
createLevelMeter(device: InputDevice): Promise<LevelMeter>;
|
createLevelMeter(device: InputDevice): Promise<LevelMeter>;
|
||||||
getDeviceList(): DeviceList;
|
getDeviceList(): DeviceList;
|
||||||
isRnNoiseSupported(): boolean;
|
|
||||||
toggleRnNoise(target: boolean): any;
|
|
||||||
}
|
}
|
||||||
export interface DeviceListEvents {
|
export interface DeviceListEvents {
|
||||||
notify_list_updated: {
|
notify_list_updated: {
|
||||||
|
|
|
@ -59,13 +59,13 @@ export interface SoundFile {
|
||||||
export declare function get_sound_volume(sound: Sound, default_volume?: number): number;
|
export declare function get_sound_volume(sound: Sound, default_volume?: number): number;
|
||||||
export declare function set_sound_volume(sound: Sound, volume: number): void;
|
export declare function set_sound_volume(sound: Sound, volume: number): void;
|
||||||
export declare function get_master_volume(): number;
|
export declare function get_master_volume(): number;
|
||||||
export declare function set_master_volume(volume: number): void;
|
export declare function setSoundMasterVolume(volume: number): void;
|
||||||
export declare function overlap_activated(): boolean;
|
export declare function overlap_activated(): boolean;
|
||||||
export declare function set_overlap_activated(flag: boolean): void;
|
export declare function set_overlap_activated(flag: boolean): void;
|
||||||
export declare function ignore_output_muted(): boolean;
|
export declare function ignore_output_muted(): boolean;
|
||||||
export declare function set_ignore_output_muted(flag: boolean): void;
|
export declare function set_ignore_output_muted(flag: boolean): void;
|
||||||
export declare function save(): void;
|
export declare function save(): void;
|
||||||
export declare function initialize(): Promise<void>;
|
export declare function initializeSounds(): Promise<void>;
|
||||||
export interface PlaybackOptions {
|
export interface PlaybackOptions {
|
||||||
ignore_muted?: boolean;
|
ignore_muted?: boolean;
|
||||||
ignore_overlap?: boolean;
|
ignore_overlap?: boolean;
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
import { ConnectionHandler } from "tc-shared/ConnectionHandler";
|
||||||
|
export declare type ClientInfoResult = {
|
||||||
|
status: "success";
|
||||||
|
clientName: string;
|
||||||
|
clientUniqueId: string;
|
||||||
|
clientDatabaseId: number;
|
||||||
|
} | {
|
||||||
|
status: "not-found";
|
||||||
|
} | {
|
||||||
|
status: "error";
|
||||||
|
error: string;
|
||||||
|
};
|
||||||
|
export declare class ClientInfoResolver {
|
||||||
|
private readonly handler;
|
||||||
|
private readonly requestDatabaseIds;
|
||||||
|
private readonly requestUniqueIds;
|
||||||
|
private executed;
|
||||||
|
constructor(handler: ConnectionHandler);
|
||||||
|
private registerRequest;
|
||||||
|
private fullFullAllRequests;
|
||||||
|
private static parseClientInfo;
|
||||||
|
getInfoByDatabaseId(databaseId: number): Promise<ClientInfoResult>;
|
||||||
|
getInfoByUniqueId(uniqueId: string): Promise<ClientInfoResult>;
|
||||||
|
executeQueries(): Promise<void>;
|
||||||
|
}
|
|
@ -6,6 +6,7 @@ import { WhisperSession, WhisperTarget } from "../voice/VoiceWhisper";
|
||||||
export declare class DummyVoiceConnection extends AbstractVoiceConnection {
|
export declare class DummyVoiceConnection extends AbstractVoiceConnection {
|
||||||
private recorder;
|
private recorder;
|
||||||
private voiceClients;
|
private voiceClients;
|
||||||
|
private triggerUnmountEvent;
|
||||||
constructor(connection: AbstractServerConnection);
|
constructor(connection: AbstractServerConnection);
|
||||||
acquireVoiceRecorder(recorder: RecorderProfile | undefined): Promise<void>;
|
acquireVoiceRecorder(recorder: RecorderProfile | undefined): Promise<void>;
|
||||||
availableVoiceClients(): VoiceClient[];
|
availableVoiceClients(): VoiceClient[];
|
||||||
|
|
|
@ -14,7 +14,7 @@ export declare abstract class PluginCmdHandler {
|
||||||
handleHandlerRegistered(): void;
|
handleHandlerRegistered(): void;
|
||||||
getChannel(): string;
|
getChannel(): string;
|
||||||
abstract handlePluginCommand(data: string, invoker: PluginCommandInvoker): any;
|
abstract handlePluginCommand(data: string, invoker: PluginCommandInvoker): any;
|
||||||
protected sendPluginCommand(data: string, mode: "server" | "view" | "channel" | "private", clientId?: number): Promise<CommandResult>;
|
protected sendPluginCommand(data: string, mode: "server" | "view" | "channel" | "private", clientOrChannelId?: number): Promise<CommandResult>;
|
||||||
}
|
}
|
||||||
export declare class PluginCmdRegistry {
|
export declare class PluginCmdRegistry {
|
||||||
readonly connection: ConnectionHandler;
|
readonly connection: ConnectionHandler;
|
||||||
|
|
|
@ -97,6 +97,7 @@ export declare class RTCConnection {
|
||||||
restartConnection(): void;
|
restartConnection(): void;
|
||||||
reset(updateConnectionState: boolean): void;
|
reset(updateConnectionState: boolean): void;
|
||||||
setTrackSource(type: RTCSourceTrackType, source: MediaStreamTrack | null): Promise<MediaStreamTrack>;
|
setTrackSource(type: RTCSourceTrackType, source: MediaStreamTrack | null): Promise<MediaStreamTrack>;
|
||||||
|
clearTrackSources(types: RTCSourceTrackType[]): Promise<MediaStreamTrack[]>;
|
||||||
startVideoBroadcast(type: VideoBroadcastType, config: VideoBroadcastConfig): Promise<void>;
|
startVideoBroadcast(type: VideoBroadcastType, config: VideoBroadcastConfig): Promise<void>;
|
||||||
changeVideoBroadcastConfig(type: VideoBroadcastType, config: VideoBroadcastConfig): Promise<void>;
|
changeVideoBroadcastConfig(type: VideoBroadcastType, config: VideoBroadcastConfig): Promise<void>;
|
||||||
startAudioBroadcast(): Promise<void>;
|
startAudioBroadcast(): Promise<void>;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { ConnectionHandler } from "../ConnectionHandler";
|
import { ConnectionHandler } from "../ConnectionHandler";
|
||||||
import { Registry } from "../events";
|
import { Registry } from "../events";
|
||||||
import { VideoBroadcastType } from "tc-shared/connection/VideoConnection";
|
import { VideoBroadcastType } from "tc-shared/connection/VideoConnection";
|
||||||
export declare type PermissionEditorTab = "groups-server" | "groups-channel" | "channel" | "client" | "client-channel";
|
import { PermissionEditorTab } from "tc-shared/ui/modal/permission/ModalDefinitions";
|
||||||
export interface ClientGlobalControlEvents {
|
export interface ClientGlobalControlEvents {
|
||||||
action_open_window: {
|
action_open_window: {
|
||||||
window: "settings" | /* use action_open_window_settings! */ "about" | "settings-registry" | "css-variable-editor" | "bookmark-manage" | "query-manage" | "query-create" | "ban-list" | "permissions" | "token-list" | "token-use" | "server-echo-test";
|
window: "settings" | /* use action_open_window_settings! */ "about" | "settings-registry" | "css-variable-editor" | "bookmark-manage" | "query-manage" | "query-create" | "ban-list" | "permissions" | "token-list" | "token-use" | "server-echo-test";
|
||||||
|
|
|
@ -38,7 +38,8 @@ export declare abstract class ClientAvatar {
|
||||||
setLoading(): void;
|
setLoading(): void;
|
||||||
setLoaded(data: AvatarStateData["loaded"]): void;
|
setLoaded(data: AvatarStateData["loaded"]): void;
|
||||||
setErrored(data: AvatarStateData["errored"]): void;
|
setErrored(data: AvatarStateData["errored"]): void;
|
||||||
awaitLoaded(): Promise<void>;
|
awaitLoaded(): Promise<true>;
|
||||||
|
awaitLoaded(timeout: number): Promise<boolean>;
|
||||||
getState(): AvatarState;
|
getState(): AvatarState;
|
||||||
getStateData(): AvatarStateData[AvatarState];
|
getStateData(): AvatarStateData[AvatarState];
|
||||||
getAvatarHash(): string | "unknown";
|
getAvatarHash(): string | "unknown";
|
||||||
|
|
|
@ -6,7 +6,7 @@ export declare enum ImageType {
|
||||||
SVG = 4,
|
SVG = 4,
|
||||||
JPEG = 5
|
JPEG = 5
|
||||||
}
|
}
|
||||||
export declare function imageType2MediaType(type: ImageType, file?: boolean): "svg" | "jpeg" | "png" | "bmp" | "gif" | "svg+xml";
|
export declare function imageType2MediaType(type: ImageType, file?: boolean): "svg" | "bmp" | "gif" | "svg+xml" | "jpeg" | "png";
|
||||||
export declare function responseImageType(encoded_data: string | ArrayBuffer, base64_encoded?: boolean): ImageType;
|
export declare function responseImageType(encoded_data: string | ArrayBuffer, base64_encoded?: boolean): ImageType;
|
||||||
export declare type ImageCacheState = {
|
export declare type ImageCacheState = {
|
||||||
state: "loaded";
|
state: "loaded";
|
||||||
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
export declare type LocalAvatarInfo = {
|
||||||
|
fileName: string;
|
||||||
|
fileSize: number;
|
||||||
|
fileHashMD5: string;
|
||||||
|
fileUploaded: number;
|
||||||
|
fileModified: number;
|
||||||
|
contentType: string;
|
||||||
|
resourceUrl: string | undefined;
|
||||||
|
};
|
||||||
|
export declare type LocalAvatarUpdateResult = {
|
||||||
|
status: "success";
|
||||||
|
} | {
|
||||||
|
status: "error";
|
||||||
|
reason: string;
|
||||||
|
} | {
|
||||||
|
status: "cache-unavailable";
|
||||||
|
};
|
||||||
|
export declare type LocalAvatarLoadResult<T> = {
|
||||||
|
status: "success";
|
||||||
|
result: T;
|
||||||
|
} | {
|
||||||
|
status: "error";
|
||||||
|
reason: string;
|
||||||
|
} | {
|
||||||
|
status: "cache-unavailable" | "empty-result";
|
||||||
|
};
|
||||||
|
export declare type OwnAvatarMode = "uploading" | "server";
|
||||||
|
export declare class OwnAvatarStorage {
|
||||||
|
private openedCache;
|
||||||
|
private static generateRequestUrl;
|
||||||
|
initialize(): Promise<void>;
|
||||||
|
private loadAvatarRequest;
|
||||||
|
loadAvatarImage(serverUniqueId: string, mode: OwnAvatarMode): Promise<LocalAvatarLoadResult<ArrayBuffer>>;
|
||||||
|
loadAvatar(serverUniqueId: string, mode: OwnAvatarMode, createResourceUrl: boolean): Promise<LocalAvatarLoadResult<LocalAvatarInfo>>;
|
||||||
|
updateAvatar(serverUniqueId: string, mode: OwnAvatarMode, target: File): Promise<LocalAvatarUpdateResult>;
|
||||||
|
removeAvatar(serverUniqueId: string, mode: OwnAvatarMode): Promise<void>;
|
||||||
|
/**
|
||||||
|
* Move the avatar file which is currently in "uploading" state to server
|
||||||
|
* @param serverUniqueId
|
||||||
|
*/
|
||||||
|
avatarUploadSucceeded(serverUniqueId: string): Promise<void>;
|
||||||
|
}
|
||||||
|
export declare function getOwnAvatarStorage(): OwnAvatarStorage;
|
|
@ -1,2 +1,6 @@
|
||||||
export declare const downloadTextAsFile: (text: string, name: string) => void;
|
export declare const downloadTextAsFile: (text: string, name: string) => void;
|
||||||
|
export declare const requestFile: (options: {
|
||||||
|
accept?: string;
|
||||||
|
multiple?: boolean;
|
||||||
|
}) => Promise<File[]>;
|
||||||
export declare const requestFileAsText: () => Promise<string>;
|
export declare const requestFileAsText: () => Promise<string>;
|
||||||
|
|
|
@ -1 +1,14 @@
|
||||||
export declare function country_name(alpha_code: string, fallback?: string): string;
|
import "svg-sprites/country-flags";
|
||||||
|
import { CountryFlag } from "svg-sprites/country-flags";
|
||||||
|
interface CountryInfo {
|
||||||
|
name: string;
|
||||||
|
alpha_2: string;
|
||||||
|
alpha_3: string;
|
||||||
|
un_code: number;
|
||||||
|
icon: string;
|
||||||
|
flagMissingWarned?: boolean;
|
||||||
|
}
|
||||||
|
export declare function getKnownCountries(): CountryInfo[];
|
||||||
|
export declare function getCountryName(alphaCode: string, fallback?: string): string;
|
||||||
|
export declare function getCountryFlag(alphaCode: string): CountryFlag;
|
||||||
|
export {};
|
||||||
|
|
|
@ -4,7 +4,6 @@ import { ConnectRequestData } from "tc-shared/ipc/ConnectHandler";
|
||||||
import "svg-sprites/client-icons";
|
import "svg-sprites/client-icons";
|
||||||
import "../css/load-css";
|
import "../css/load-css";
|
||||||
import "./proto";
|
import "./proto";
|
||||||
import "./video-viewer/Controller";
|
|
||||||
import "./profiles/ConnectionProfile";
|
import "./profiles/ConnectionProfile";
|
||||||
import "./update/UpdaterWeb";
|
import "./update/UpdaterWeb";
|
||||||
import "./file/LocalIcons";
|
import "./file/LocalIcons";
|
||||||
|
@ -17,6 +16,8 @@ import "./media/Video";
|
||||||
import "./ui/AppController";
|
import "./ui/AppController";
|
||||||
import "./ui/frames/menu-bar/MainMenu";
|
import "./ui/frames/menu-bar/MainMenu";
|
||||||
import "./ui/modal/connect/Controller";
|
import "./ui/modal/connect/Controller";
|
||||||
|
import "./ui/modal/video-viewer/Controller";
|
||||||
|
import "./ui/modal/avatar-upload/Controller";
|
||||||
import "./ui/elements/ContextDivider";
|
import "./ui/elements/ContextDivider";
|
||||||
import "./ui/elements/Tab";
|
import "./ui/elements/Tab";
|
||||||
import "./clientservice";
|
import "./clientservice";
|
||||||
|
|
|
@ -72,3 +72,12 @@ export declare type ReadonlyKeys<T> = {
|
||||||
-readonly [Q in P]: T[P];
|
-readonly [Q in P]: T[P];
|
||||||
}, never, P>;
|
}, never, P>;
|
||||||
}[keyof T];
|
}[keyof T];
|
||||||
|
export declare function crashOnThrow<T>(promise: Promise<T> | (() => Promise<T>)): Promise<T>;
|
||||||
|
export declare function ignorePromise<T>(_promise: Promise<T>): void;
|
||||||
|
export declare function NoThrow(target: any, methodName: string, descriptor: PropertyDescriptor): void;
|
||||||
|
export declare function CallOnce(target: any, methodName: string, descriptor: PropertyDescriptor): void;
|
||||||
|
export declare function NonNull(target: any, methodName: string, parameterIndex: number): void;
|
||||||
|
/**
|
||||||
|
* The class or method has been constrained
|
||||||
|
*/
|
||||||
|
export declare function ParameterConstrained(target: any, methodName: string, descriptor: PropertyDescriptor): void;
|
||||||
|
|
|
@ -15,6 +15,8 @@ export interface RegistryKey<ValueType extends RegistryValueType> {
|
||||||
export interface ValuedRegistryKey<ValueType extends RegistryValueType> extends RegistryKey<ValueType> {
|
export interface ValuedRegistryKey<ValueType extends RegistryValueType> extends RegistryKey<ValueType> {
|
||||||
defaultValue: ValueType;
|
defaultValue: ValueType;
|
||||||
}
|
}
|
||||||
|
export declare function encodeSettingValueToString<T extends RegistryValueType>(input: T): string;
|
||||||
|
export declare function resolveSettingKey<ValueType extends RegistryValueType, DefaultType>(key: RegistryKey<ValueType>, resolver: (key: string) => string | undefined | null, defaultValue: DefaultType): ValueType | DefaultType;
|
||||||
export declare class UrlParameterParser {
|
export declare class UrlParameterParser {
|
||||||
private readonly url;
|
private readonly url;
|
||||||
constructor(url: URL);
|
constructor(url: URL);
|
||||||
|
@ -53,14 +55,6 @@ export declare namespace AppParameters {
|
||||||
const KEY_MODAL_IPC_CHANNEL: RegistryKey<string>;
|
const KEY_MODAL_IPC_CHANNEL: RegistryKey<string>;
|
||||||
const KEY_LOAD_DUMMY_ERROR: ValuedRegistryKey<boolean>;
|
const KEY_LOAD_DUMMY_ERROR: ValuedRegistryKey<boolean>;
|
||||||
}
|
}
|
||||||
export declare class StaticSettings {
|
|
||||||
private static _instance;
|
|
||||||
static get instance(): StaticSettings;
|
|
||||||
protected staticValues: {};
|
|
||||||
protected constructor(_reserved?: any);
|
|
||||||
static<V extends RegistryValueType, DV>(key: RegistryKey<V>, defaultValue: DV): V | DV;
|
|
||||||
static<V extends RegistryValueType>(key: ValuedRegistryKey<V>, defaultValue?: V): V;
|
|
||||||
}
|
|
||||||
export interface SettingsEvents {
|
export interface SettingsEvents {
|
||||||
notify_setting_changed: {
|
notify_setting_changed: {
|
||||||
setting: string;
|
setting: string;
|
||||||
|
@ -145,6 +139,9 @@ export declare class Settings {
|
||||||
static readonly KEY_MICROPHONE_THRESHOLD_ATTACK_SMOOTH: ValuedRegistryKey<number>;
|
static readonly KEY_MICROPHONE_THRESHOLD_ATTACK_SMOOTH: ValuedRegistryKey<number>;
|
||||||
static readonly KEY_MICROPHONE_THRESHOLD_RELEASE_SMOOTH: ValuedRegistryKey<number>;
|
static readonly KEY_MICROPHONE_THRESHOLD_RELEASE_SMOOTH: ValuedRegistryKey<number>;
|
||||||
static readonly KEY_MICROPHONE_THRESHOLD_RELEASE_DELAY: ValuedRegistryKey<number>;
|
static readonly KEY_MICROPHONE_THRESHOLD_RELEASE_DELAY: ValuedRegistryKey<number>;
|
||||||
|
static readonly KEY_SPEAKER_DEVICE_ID: RegistryKey<string>;
|
||||||
|
static readonly KEY_UPDATER_LAST_USED_UI: RegistryKey<string>;
|
||||||
|
static readonly KEY_UPDATER_LAST_USED_CLIENT: RegistryKey<string>;
|
||||||
static readonly FN_LOG_ENABLED: (category: string) => RegistryKey<boolean>;
|
static readonly FN_LOG_ENABLED: (category: string) => RegistryKey<boolean>;
|
||||||
static readonly FN_SEPARATOR_STATE: (separator: string) => RegistryKey<string>;
|
static readonly FN_SEPARATOR_STATE: (separator: string) => RegistryKey<string>;
|
||||||
static readonly FN_LOG_LEVEL_ENABLED: (category: string) => RegistryKey<boolean>;
|
static readonly FN_LOG_LEVEL_ENABLED: (category: string) => RegistryKey<boolean>;
|
||||||
|
@ -159,30 +156,18 @@ export declare class Settings {
|
||||||
static readonly FN_EVENTS_LOG_ENABLED: (event: string) => RegistryKey<boolean>;
|
static readonly FN_EVENTS_LOG_ENABLED: (event: string) => RegistryKey<boolean>;
|
||||||
static readonly FN_EVENTS_FOCUS_ENABLED: (event: string) => RegistryKey<boolean>;
|
static readonly FN_EVENTS_FOCUS_ENABLED: (event: string) => RegistryKey<boolean>;
|
||||||
static readonly KEYS: any[];
|
static readonly KEYS: any[];
|
||||||
static initialize(): void;
|
|
||||||
readonly events: Registry<SettingsEvents>;
|
readonly events: Registry<SettingsEvents>;
|
||||||
private readonly cacheGlobal;
|
private settingsCache;
|
||||||
private saveWorker;
|
private saveWorker;
|
||||||
private updated;
|
private updated;
|
||||||
|
private saveState;
|
||||||
constructor();
|
constructor();
|
||||||
|
initialize(): Promise<void>;
|
||||||
getValue<V extends RegistryValueType, DV>(key: RegistryKey<V>, defaultValue: DV): V | DV;
|
getValue<V extends RegistryValueType, DV>(key: RegistryKey<V>, defaultValue: DV): V | DV;
|
||||||
getValue<V extends RegistryValueType>(key: ValuedRegistryKey<V>, defaultValue?: V): V;
|
getValue<V extends RegistryValueType>(key: ValuedRegistryKey<V>, defaultValue?: V): V;
|
||||||
setValue<T extends RegistryValueType>(key: RegistryKey<T>, value?: T): void;
|
setValue<T extends RegistryValueType>(key: RegistryKey<T>, value?: T): void;
|
||||||
globalChangeListener<T extends RegistryValueType>(key: RegistryKey<T>, listener: (newValue: T) => void): () => void;
|
globalChangeListener<T extends RegistryValueType>(key: RegistryKey<T>, listener: (newValue: T) => void): () => void;
|
||||||
save(): void;
|
private doSave;
|
||||||
}
|
|
||||||
export declare class ServerSettings {
|
|
||||||
private cacheServer;
|
|
||||||
private serverUniqueId;
|
|
||||||
private serverSaveWorker;
|
|
||||||
private serverSettingsUpdated;
|
|
||||||
private _destroyed;
|
|
||||||
constructor();
|
|
||||||
destroy(): void;
|
|
||||||
getValue<V extends RegistryValueType, DV>(key: RegistryKey<V>, defaultValue: DV): V | DV;
|
|
||||||
getValue<V extends RegistryValueType>(key: ValuedRegistryKey<V>, defaultValue?: V): V;
|
|
||||||
setValue<T extends RegistryValueType>(key: RegistryKey<T>, value?: T): void;
|
|
||||||
setServer(server_unique_id: string): void;
|
|
||||||
save(): void;
|
save(): void;
|
||||||
}
|
}
|
||||||
export declare let settings: Settings;
|
export declare let settings: Settings;
|
||||||
|
|
|
@ -4,7 +4,7 @@ import ReactRenderer from "vendor/xbbcode/renderer/react";
|
||||||
import HTMLRenderer from "vendor/xbbcode/renderer/html";
|
import HTMLRenderer from "vendor/xbbcode/renderer/html";
|
||||||
import "./emoji";
|
import "./emoji";
|
||||||
import "./highlight";
|
import "./highlight";
|
||||||
import "./YoutubeRenderer";
|
import "./YoutubeController";
|
||||||
import "./url";
|
import "./url";
|
||||||
import "./image";
|
import "./image";
|
||||||
export declare let BBCodeHandlerContext: Context<string>;
|
export declare let BBCodeHandlerContext: Context<string>;
|
||||||
|
|
|
@ -100,9 +100,7 @@ export declare class ClientConnectionInfo {
|
||||||
}
|
}
|
||||||
export interface ClientEvents extends ChannelTreeEntryEvents {
|
export interface ClientEvents extends ChannelTreeEntryEvents {
|
||||||
notify_properties_updated: {
|
notify_properties_updated: {
|
||||||
updated_properties: {
|
updated_properties: Partial<ClientProperties>;
|
||||||
[Key in keyof ClientProperties]: ClientProperties[Key];
|
|
||||||
};
|
|
||||||
client_properties: ClientProperties;
|
client_properties: ClientProperties;
|
||||||
};
|
};
|
||||||
notify_mute_state_change: {
|
notify_mute_state_change: {
|
||||||
|
@ -166,8 +164,10 @@ export declare class ClientEntry<Events extends ClientEvents = ClientEvents> ext
|
||||||
static chatTag(id: number, name: string, uid: string, braces?: boolean): JQuery;
|
static chatTag(id: number, name: string, uid: string, braces?: boolean): JQuery;
|
||||||
create_bbcode(): string;
|
create_bbcode(): string;
|
||||||
createChatTag(braces?: boolean): JQuery;
|
createChatTag(braces?: boolean): JQuery;
|
||||||
set speaking(flag: any);
|
/** @deprecated Don't use this any more! */
|
||||||
|
set speaking(flag: boolean);
|
||||||
isSpeaking(): boolean;
|
isSpeaking(): boolean;
|
||||||
|
protected setSpeaking(flag: boolean): void;
|
||||||
updateVariables(...variables: {
|
updateVariables(...variables: {
|
||||||
key: string;
|
key: string;
|
||||||
value: string;
|
value: string;
|
||||||
|
@ -188,6 +188,7 @@ export declare class ClientEntry<Events extends ClientEvents = ClientEvents> ext
|
||||||
export declare class LocalClientEntry extends ClientEntry {
|
export declare class LocalClientEntry extends ClientEntry {
|
||||||
handle: ConnectionHandler;
|
handle: ConnectionHandler;
|
||||||
constructor(handle: ConnectionHandler);
|
constructor(handle: ConnectionHandler);
|
||||||
|
setSpeaking(flag: boolean): void;
|
||||||
showContextMenu(x: number, y: number, on_close?: () => void): void;
|
showContextMenu(x: number, y: number, on_close?: () => void): void;
|
||||||
renameSelf(new_name: string): Promise<boolean>;
|
renameSelf(new_name: string): Promise<boolean>;
|
||||||
openRenameModal(): void;
|
openRenameModal(): void;
|
||||||
|
|
|
@ -28,6 +28,7 @@ declare class InfoController {
|
||||||
sendMicrophoneState(): void;
|
sendMicrophoneState(): void;
|
||||||
sendMicrophoneList(): void;
|
sendMicrophoneList(): void;
|
||||||
sendSpeakerState(): void;
|
sendSpeakerState(): void;
|
||||||
|
sendSpeakerList(): Promise<void>;
|
||||||
sendSubscribeState(): void;
|
sendSubscribeState(): void;
|
||||||
sendQueryState(): void;
|
sendQueryState(): void;
|
||||||
sendHostButton(): void;
|
sendHostButton(): void;
|
||||||
|
|
|
@ -27,7 +27,7 @@ export declare type VideoDeviceInfo = {
|
||||||
name: string;
|
name: string;
|
||||||
id: string;
|
id: string;
|
||||||
};
|
};
|
||||||
export declare type MicrophoneDeviceInfo = {
|
export declare type AudioDeviceInfo = {
|
||||||
name: string;
|
name: string;
|
||||||
id: string;
|
id: string;
|
||||||
driver: string;
|
driver: string;
|
||||||
|
@ -57,6 +57,7 @@ export interface ControlBarEvents {
|
||||||
};
|
};
|
||||||
action_toggle_speaker: {
|
action_toggle_speaker: {
|
||||||
enabled: boolean;
|
enabled: boolean;
|
||||||
|
targetDeviceId?: string;
|
||||||
};
|
};
|
||||||
action_toggle_subscribe: {
|
action_toggle_subscribe: {
|
||||||
subscribe: boolean;
|
subscribe: boolean;
|
||||||
|
@ -75,6 +76,7 @@ export interface ControlBarEvents {
|
||||||
broadcastType: VideoBroadcastType;
|
broadcastType: VideoBroadcastType;
|
||||||
};
|
};
|
||||||
action_open_microphone_settings: {};
|
action_open_microphone_settings: {};
|
||||||
|
action_open_speaker_settings: {};
|
||||||
query_mode: {};
|
query_mode: {};
|
||||||
query_connection_state: {};
|
query_connection_state: {};
|
||||||
query_bookmarks: {};
|
query_bookmarks: {};
|
||||||
|
@ -82,6 +84,7 @@ export interface ControlBarEvents {
|
||||||
query_microphone_state: {};
|
query_microphone_state: {};
|
||||||
query_microphone_list: {};
|
query_microphone_list: {};
|
||||||
query_speaker_state: {};
|
query_speaker_state: {};
|
||||||
|
query_speaker_list: {};
|
||||||
query_subscribe_state: {};
|
query_subscribe_state: {};
|
||||||
query_query_state: {};
|
query_query_state: {};
|
||||||
query_host_button: {};
|
query_host_button: {};
|
||||||
|
@ -105,11 +108,17 @@ export interface ControlBarEvents {
|
||||||
state: MicrophoneState;
|
state: MicrophoneState;
|
||||||
};
|
};
|
||||||
notify_microphone_list: {
|
notify_microphone_list: {
|
||||||
devices: MicrophoneDeviceInfo[];
|
devices: AudioDeviceInfo[];
|
||||||
};
|
};
|
||||||
notify_speaker_state: {
|
notify_speaker_state: {
|
||||||
enabled: boolean;
|
enabled: boolean;
|
||||||
};
|
};
|
||||||
|
notify_speaker_list: {
|
||||||
|
state: "initialized";
|
||||||
|
devices: AudioDeviceInfo[];
|
||||||
|
} | {
|
||||||
|
state: "uninitialized";
|
||||||
|
};
|
||||||
notify_subscribe_state: {
|
notify_subscribe_state: {
|
||||||
subscribe: boolean;
|
subscribe: boolean;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import { ReactComponentBase } from "tc-shared/ui/react-elements/ReactComponentBase";
|
|
||||||
import { RemoteIconInfo } from "tc-shared/file/Icons";
|
import { RemoteIconInfo } from "tc-shared/file/Icons";
|
||||||
export interface DropdownEntryProperties {
|
export interface DropdownEntryProperties {
|
||||||
icon?: string | RemoteIconInfo;
|
icon?: string | RemoteIconInfo;
|
||||||
|
@ -7,10 +6,14 @@ export interface DropdownEntryProperties {
|
||||||
onClick?: (event: React.MouseEvent) => void;
|
onClick?: (event: React.MouseEvent) => void;
|
||||||
onAuxClick?: (event: React.MouseEvent) => void;
|
onAuxClick?: (event: React.MouseEvent) => void;
|
||||||
onContextMenu?: (event: React.MouseEvent) => void;
|
onContextMenu?: (event: React.MouseEvent) => void;
|
||||||
children?: React.ReactElement<DropdownEntry>[];
|
children?: React.ReactElement<DropdownEntry | DropdownTitleEntry>[];
|
||||||
}
|
}
|
||||||
export declare class DropdownEntry extends ReactComponentBase<DropdownEntryProperties, {}> {
|
export declare class DropdownEntry extends React.PureComponent<DropdownEntryProperties> {
|
||||||
protected defaultState(): {};
|
render(): JSX.Element;
|
||||||
|
}
|
||||||
|
export declare class DropdownTitleEntry extends React.PureComponent<{
|
||||||
|
children: any;
|
||||||
|
}> {
|
||||||
render(): JSX.Element;
|
render(): JSX.Element;
|
||||||
}
|
}
|
||||||
export declare const DropdownContainer: (props: {
|
export declare const DropdownContainer: (props: {
|
||||||
|
|
|
@ -15,7 +15,6 @@ export declare abstract class AbstractConversationController<Events extends Abst
|
||||||
protected registerConversationManagerEvents(manager: Manager): void;
|
protected registerConversationManagerEvents(manager: Manager): void;
|
||||||
protected registerConversationEvents(conversation: ConversationType): void;
|
protected registerConversationEvents(conversation: ConversationType): void;
|
||||||
protected setCurrentlySelected(conversation: ConversationType | undefined): void;
|
protected setCurrentlySelected(conversation: ConversationType | undefined): void;
|
||||||
handlePanelShow(): void;
|
|
||||||
protected reportStateToUI(conversation: AbstractChat<any>): void;
|
protected reportStateToUI(conversation: AbstractChat<any>): void;
|
||||||
uiQueryHistory(conversation: AbstractChat<any>, timestamp: number, enforce?: boolean): void;
|
uiQueryHistory(conversation: AbstractChat<any>, timestamp: number, enforce?: boolean): void;
|
||||||
protected getCurrentConversation(): ConversationType | undefined;
|
protected getCurrentConversation(): ConversationType | undefined;
|
||||||
|
|
|
@ -121,7 +121,6 @@ export interface AbstractConversationUiEvents {
|
||||||
notify_selected_chat: {
|
notify_selected_chat: {
|
||||||
chatId: "unselected" | string;
|
chatId: "unselected" | string;
|
||||||
};
|
};
|
||||||
notify_panel_show: {};
|
|
||||||
notify_chat_event: {
|
notify_chat_event: {
|
||||||
chatId: string;
|
chatId: string;
|
||||||
triggerUnread: boolean;
|
triggerUnread: boolean;
|
||||||
|
|
|
@ -8,7 +8,6 @@ export declare class ChannelConversationController extends AbstractConversationC
|
||||||
constructor();
|
constructor();
|
||||||
destroy(): void;
|
destroy(): void;
|
||||||
setConnectionHandler(connection: ConnectionHandler): void;
|
setConnectionHandler(connection: ConnectionHandler): void;
|
||||||
private initializeConnectionListener;
|
|
||||||
private handleMessageDelete;
|
private handleMessageDelete;
|
||||||
protected registerConversationEvents(conversation: ChannelConversation): void;
|
protected registerConversationEvents(conversation: ChannelConversation): void;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,10 +3,13 @@ export declare class ClientInfoController {
|
||||||
private readonly uiEvents;
|
private readonly uiEvents;
|
||||||
private connection;
|
private connection;
|
||||||
private listenerConnection;
|
private listenerConnection;
|
||||||
|
private listenerInheritedChannel;
|
||||||
|
private inheritedChannelInfo;
|
||||||
constructor();
|
constructor();
|
||||||
destroy(): void;
|
destroy(): void;
|
||||||
setConnectionHandler(connection: ConnectionHandler): void;
|
setConnectionHandler(connection: ConnectionHandler): void;
|
||||||
private initializeConnection;
|
private initializeConnection;
|
||||||
|
private updateInheritedInfo;
|
||||||
private generateGroupInfo;
|
private generateGroupInfo;
|
||||||
private sendClient;
|
private sendClient;
|
||||||
private sendChannelGroup;
|
private sendChannelGroup;
|
||||||
|
|
|
@ -46,6 +46,10 @@ export declare type ClientVersionInfo = {
|
||||||
platform: string;
|
platform: string;
|
||||||
version: string;
|
version: string;
|
||||||
};
|
};
|
||||||
|
export declare type InheritedChannelInfo = {
|
||||||
|
channelId: number;
|
||||||
|
channelName: string;
|
||||||
|
};
|
||||||
export interface ClientInfoEvents {
|
export interface ClientInfoEvents {
|
||||||
action_show_full_info: {};
|
action_show_full_info: {};
|
||||||
action_edit_avatar: {};
|
action_edit_avatar: {};
|
||||||
|
@ -68,6 +72,7 @@ export interface ClientInfoEvents {
|
||||||
};
|
};
|
||||||
notify_channel_group: {
|
notify_channel_group: {
|
||||||
group: ClientGroupInfo | undefined;
|
group: ClientGroupInfo | undefined;
|
||||||
|
inheritedChannel: InheritedChannelInfo | undefined;
|
||||||
};
|
};
|
||||||
notify_server_groups: {
|
notify_server_groups: {
|
||||||
groups: ClientGroupInfo[];
|
groups: ClientGroupInfo[];
|
||||||
|
|
|
@ -15,7 +15,6 @@ export declare class PrivateConversationController extends AbstractConversationC
|
||||||
constructor();
|
constructor();
|
||||||
destroy(): void;
|
destroy(): void;
|
||||||
setConnectionHandler(connection: ConnectionHandler): void;
|
setConnectionHandler(connection: ConnectionHandler): void;
|
||||||
private initializeConnectionListener;
|
|
||||||
protected registerConversationManagerEvents(manager: PrivateConversationManager): void;
|
protected registerConversationManagerEvents(manager: PrivateConversationManager): void;
|
||||||
focusInput(): void;
|
focusInput(): void;
|
||||||
private reportConversationList;
|
private reportConversationList;
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
export declare function spawnAvatarUpload(callback_data: (data: ArrayBuffer | undefined | null) => any): void;
|
|
|
@ -1,6 +0,0 @@
|
||||||
export declare const Regex: {
|
|
||||||
DOMAIN: RegExp;
|
|
||||||
IP_V4: RegExp;
|
|
||||||
IP_V6: RegExp;
|
|
||||||
IP: RegExp;
|
|
||||||
};
|
|
|
@ -1,2 +0,0 @@
|
||||||
import { ClientEntry } from "../../tree/Client";
|
|
||||||
export declare function createServerGroupAssignmentModal(client: ClientEntry, callback: (groups: number[], flag: boolean) => Promise<boolean>): void;
|
|
|
@ -0,0 +1 @@
|
||||||
|
export declare function spawnAboutModal(): void;
|
|
@ -0,0 +1,15 @@
|
||||||
|
export interface ModalAboutVariables {
|
||||||
|
readonly uiVersion: string;
|
||||||
|
readonly uiVersionTimestamp: number;
|
||||||
|
readonly nativeVersion: string;
|
||||||
|
eggShown: boolean;
|
||||||
|
}
|
||||||
|
export interface ModalAboutEvents {
|
||||||
|
action_update_high_score: {
|
||||||
|
score: number;
|
||||||
|
};
|
||||||
|
query_high_score: {};
|
||||||
|
notify_high_score: {
|
||||||
|
score: number;
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
import { AbstractModal } from "tc-shared/ui/react-elements/modal/Definitions";
|
||||||
|
import React from "react";
|
||||||
|
import { IpcRegistryDescription } from "tc-events";
|
||||||
|
import { ModalAboutEvents, ModalAboutVariables } from "tc-shared/ui/modal/about/Definitions";
|
||||||
|
import { IpcVariableDescriptor } from "tc-shared/ui/utils/IpcVariable";
|
||||||
|
declare class Modal extends AbstractModal {
|
||||||
|
private readonly events;
|
||||||
|
private readonly variables;
|
||||||
|
constructor(events: IpcRegistryDescription<ModalAboutEvents>, variables: IpcVariableDescriptor<ModalAboutVariables>);
|
||||||
|
renderBody(): React.ReactElement;
|
||||||
|
renderTitle(): string | React.ReactElement;
|
||||||
|
}
|
||||||
|
export default Modal;
|
|
@ -0,0 +1,2 @@
|
||||||
|
import { ConnectionHandler } from "tc-shared/ConnectionHandler";
|
||||||
|
export declare function spawnAvatarUpload(connection: ConnectionHandler): void;
|
|
@ -0,0 +1,33 @@
|
||||||
|
export declare type CurrentAvatarState = {
|
||||||
|
status: "unset" | "loading";
|
||||||
|
} | {
|
||||||
|
status: "available" | "exceeds-max-size";
|
||||||
|
fileName: string;
|
||||||
|
fileSize: number;
|
||||||
|
fileHashMD5: string;
|
||||||
|
resourceUrl: string | undefined;
|
||||||
|
serverHasAvatar: boolean;
|
||||||
|
} | {
|
||||||
|
status: "server";
|
||||||
|
resourceUrl: string;
|
||||||
|
};
|
||||||
|
export interface ModalAvatarUploadVariables {
|
||||||
|
readonly maxAvatarSize: number;
|
||||||
|
readonly currentAvatar: CurrentAvatarState;
|
||||||
|
}
|
||||||
|
export interface ModalAvatarUploadEvents {
|
||||||
|
action_open_select: {};
|
||||||
|
action_file_cache_loading: {};
|
||||||
|
action_file_cache_loading_finished: {
|
||||||
|
success: boolean;
|
||||||
|
};
|
||||||
|
action_avatar_upload: {
|
||||||
|
closeWindow: boolean;
|
||||||
|
};
|
||||||
|
action_avatar_delete: {
|
||||||
|
closeWindow: boolean;
|
||||||
|
};
|
||||||
|
notify_avatar_load_error: {
|
||||||
|
error: string;
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
import { AbstractModal } from "tc-shared/ui/react-elements/modal/Definitions";
|
||||||
|
import React from "react";
|
||||||
|
import { IpcRegistryDescription } from "tc-events";
|
||||||
|
import { ModalAvatarUploadEvents, ModalAvatarUploadVariables } from "tc-shared/ui/modal/avatar-upload/Definitions";
|
||||||
|
import { IpcVariableDescriptor } from "tc-shared/ui/utils/IpcVariable";
|
||||||
|
declare class ModalAvatarUpload extends AbstractModal {
|
||||||
|
private readonly serverUniqueId;
|
||||||
|
private readonly events;
|
||||||
|
private readonly variables;
|
||||||
|
constructor(events: IpcRegistryDescription<ModalAvatarUploadEvents>, variables: IpcVariableDescriptor<ModalAvatarUploadVariables>, serverUniqueId: string);
|
||||||
|
protected onDestroy(): void;
|
||||||
|
renderBody(): React.ReactElement;
|
||||||
|
renderTitle(): string | React.ReactElement;
|
||||||
|
}
|
||||||
|
export default ModalAvatarUpload;
|
|
@ -0,0 +1,2 @@
|
||||||
|
import { ConnectionHandler } from "tc-shared/ConnectionHandler";
|
||||||
|
export declare function spawnServerGroupAssignments(handler: ConnectionHandler, targetClientDatabaseId: number): void;
|
|
@ -0,0 +1,57 @@
|
||||||
|
import { RemoteIconInfo } from "tc-shared/file/Icons";
|
||||||
|
export declare type AvailableGroup = {
|
||||||
|
groupId: number;
|
||||||
|
saveDB: boolean;
|
||||||
|
name: string;
|
||||||
|
icon: RemoteIconInfo | undefined;
|
||||||
|
addAble: boolean;
|
||||||
|
removeAble: boolean;
|
||||||
|
};
|
||||||
|
export declare type ClientInfo = {
|
||||||
|
status: "success";
|
||||||
|
clientDatabaseId: number;
|
||||||
|
clientUniqueId: string;
|
||||||
|
clientName: string;
|
||||||
|
} | {
|
||||||
|
status: "error";
|
||||||
|
message: string;
|
||||||
|
};
|
||||||
|
export interface ModalClientGroupAssignmentVariables {
|
||||||
|
readonly handlerId: string;
|
||||||
|
readonly targetClient: ClientInfo;
|
||||||
|
readonly availableGroups: {
|
||||||
|
groups: AvailableGroup[];
|
||||||
|
defaultGroup: number;
|
||||||
|
};
|
||||||
|
readonly assignedGroupStatus: {
|
||||||
|
status: "loaded";
|
||||||
|
assignedGroups: number;
|
||||||
|
} | {
|
||||||
|
status: "loading";
|
||||||
|
} | {
|
||||||
|
status: "error";
|
||||||
|
message: string;
|
||||||
|
};
|
||||||
|
groupAssigned: boolean;
|
||||||
|
}
|
||||||
|
export interface ModalClientGroupAssignmentEvents {
|
||||||
|
action_close: {};
|
||||||
|
action_remove_all: {};
|
||||||
|
action_refresh: {
|
||||||
|
slowMode: boolean;
|
||||||
|
};
|
||||||
|
notify_toggle_result: {
|
||||||
|
action: "add" | "remove";
|
||||||
|
groupId: number;
|
||||||
|
groupName: string;
|
||||||
|
result: {
|
||||||
|
status: "success";
|
||||||
|
} | {
|
||||||
|
status: "error";
|
||||||
|
reason: string;
|
||||||
|
} | {
|
||||||
|
status: "no-permissions";
|
||||||
|
permission: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
import { AbstractModal } from "tc-shared/ui/react-elements/modal/Definitions";
|
||||||
|
import React from "react";
|
||||||
|
import { IpcRegistryDescription } from "tc-events";
|
||||||
|
import { ModalClientGroupAssignmentEvents, ModalClientGroupAssignmentVariables } from "tc-shared/ui/modal/group-assignment/Definitions";
|
||||||
|
import { IpcVariableDescriptor } from "tc-shared/ui/utils/IpcVariable";
|
||||||
|
export default class ModalServerGroups extends AbstractModal {
|
||||||
|
private readonly events;
|
||||||
|
private readonly variables;
|
||||||
|
constructor(events: IpcRegistryDescription<ModalClientGroupAssignmentEvents>, variables: IpcVariableDescriptor<ModalClientGroupAssignmentVariables>);
|
||||||
|
protected onDestroy(): void;
|
||||||
|
renderBody(): React.ReactElement;
|
||||||
|
renderTitle(): string | React.ReactElement;
|
||||||
|
}
|
|
@ -0,0 +1,2 @@
|
||||||
|
import { InputProcessor } from "tc-shared/voice/RecorderBase";
|
||||||
|
export declare function spawnInputProcessorModal(processor: InputProcessor): void;
|
|
@ -0,0 +1,13 @@
|
||||||
|
import { InputProcessorConfigRNNoise, InputProcessorConfigWebRTC, InputProcessorStatistics } from "tc-shared/voice/RecorderBase";
|
||||||
|
export declare type ModalInputProcessorVariables = {
|
||||||
|
propertyFilter: string;
|
||||||
|
} & InputProcessorConfigRNNoise & InputProcessorConfigWebRTC;
|
||||||
|
export interface ModalInputProcessorEvents {
|
||||||
|
query_statistics: {};
|
||||||
|
notify_statistics: {
|
||||||
|
statistics: InputProcessorStatistics;
|
||||||
|
};
|
||||||
|
notify_apply_error: {
|
||||||
|
message: string;
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
import { AbstractModal } from "tc-shared/ui/react-elements/modal/Definitions";
|
||||||
|
import React from "react";
|
||||||
|
import { IpcRegistryDescription } from "tc-events";
|
||||||
|
import { ModalInputProcessorEvents, ModalInputProcessorVariables } from "tc-shared/ui/modal/input-processor/Definitios";
|
||||||
|
import { IpcVariableDescriptor } from "tc-shared/ui/utils/IpcVariable";
|
||||||
|
declare class Modal extends AbstractModal {
|
||||||
|
private readonly events;
|
||||||
|
private readonly variables;
|
||||||
|
constructor(events: IpcRegistryDescription<ModalInputProcessorEvents>, variables: IpcVariableDescriptor<ModalInputProcessorVariables>);
|
||||||
|
protected onDestroy(): void;
|
||||||
|
renderBody(): React.ReactElement;
|
||||||
|
renderTitle(): string | React.ReactElement;
|
||||||
|
}
|
||||||
|
export default Modal;
|
|
@ -1,6 +1,3 @@
|
||||||
import * as React from "react";
|
|
||||||
import { Registry } from "tc-shared/events";
|
|
||||||
import { ConnectionHandler } from "tc-shared/ConnectionHandler";
|
|
||||||
export interface EditorGroupedPermissions {
|
export interface EditorGroupedPermissions {
|
||||||
groupId: string;
|
groupId: string;
|
||||||
groupName: string;
|
groupName: string;
|
||||||
|
@ -11,7 +8,7 @@ export interface EditorGroupedPermissions {
|
||||||
}[];
|
}[];
|
||||||
children: EditorGroupedPermissions[];
|
children: EditorGroupedPermissions[];
|
||||||
}
|
}
|
||||||
declare type PermissionEditorMode = "unset" | "no-permissions" | "normal";
|
export declare type PermissionEditorMode = "unset" | "no-permissions" | "normal";
|
||||||
export interface PermissionEditorEvents {
|
export interface PermissionEditorEvents {
|
||||||
action_set_mode: {
|
action_set_mode: {
|
||||||
mode: PermissionEditorMode;
|
mode: PermissionEditorMode;
|
||||||
|
@ -104,15 +101,3 @@ export interface PermissionEditorEvents {
|
||||||
}[];
|
}[];
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
interface PermissionEditorProperties {
|
|
||||||
connection: ConnectionHandler;
|
|
||||||
events: Registry<PermissionEditorEvents>;
|
|
||||||
}
|
|
||||||
interface PermissionEditorState {
|
|
||||||
state: "no-permissions" | "unset" | "normal";
|
|
||||||
}
|
|
||||||
export declare class PermissionEditor extends React.Component<PermissionEditorProperties, PermissionEditorState> {
|
|
||||||
render(): JSX.Element[];
|
|
||||||
componentDidMount(): void;
|
|
||||||
}
|
|
||||||
export {};
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
import * as React from "react";
|
||||||
|
import { Registry } from "tc-shared/events";
|
||||||
|
import { PermissionEditorEvents } from "tc-shared/ui/modal/permission/EditorDefinitions";
|
||||||
|
interface PermissionEditorProperties {
|
||||||
|
handlerId: string;
|
||||||
|
serverUniqueId: string;
|
||||||
|
events: Registry<PermissionEditorEvents>;
|
||||||
|
}
|
||||||
|
interface PermissionEditorState {
|
||||||
|
state: "no-permissions" | "unset" | "normal";
|
||||||
|
}
|
||||||
|
export declare class EditorRenderer extends React.Component<PermissionEditorProperties, PermissionEditorState> {
|
||||||
|
render(): JSX.Element;
|
||||||
|
componentDidMount(): void;
|
||||||
|
}
|
||||||
|
export {};
|
|
@ -0,0 +1,4 @@
|
||||||
|
import { ConnectionHandler } from "tc-shared/ConnectionHandler";
|
||||||
|
import { DefaultTabValues } from "tc-shared/ui/modal/permission/ModalRenderer";
|
||||||
|
import { PermissionEditorTab } from "tc-shared/ui/modal/permission/ModalDefinitions";
|
||||||
|
export declare function spawnPermissionEditorModal(connection: ConnectionHandler, defaultTab?: PermissionEditorTab, defaultTabValues?: DefaultTabValues): void;
|
|
@ -1,14 +1,5 @@
|
||||||
import { ConnectionHandler } from "tc-shared/ConnectionHandler";
|
export declare type PermissionEditorTab = "groups-server" | "groups-channel" | "channel" | "client" | "client-channel";
|
||||||
import * as React from "react";
|
|
||||||
import { PermissionEditorTab } from "tc-shared/events/GlobalEvents";
|
|
||||||
export declare type PermissionEditorSubject = "groups-server" | "groups-channel" | "channel" | "client" | "client-channel" | "none";
|
export declare type PermissionEditorSubject = "groups-server" | "groups-channel" | "channel" | "client" | "client-channel" | "none";
|
||||||
export declare const PermissionTabName: {
|
|
||||||
[T in PermissionEditorTab]: {
|
|
||||||
name: string;
|
|
||||||
useTranslate: () => string;
|
|
||||||
renderTranslate: () => React.ReactNode;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
export declare type GroupProperties = {
|
export declare type GroupProperties = {
|
||||||
id: number;
|
id: number;
|
||||||
type: "query" | "template" | "normal";
|
type: "query" | "template" | "normal";
|
||||||
|
@ -182,11 +173,6 @@ export interface PermissionModalEvents {
|
||||||
property: "name" | "icon";
|
property: "name" | "icon";
|
||||||
value: any;
|
value: any;
|
||||||
};
|
};
|
||||||
|
notify_initial_rendered: {};
|
||||||
notify_destroy: {};
|
notify_destroy: {};
|
||||||
}
|
}
|
||||||
export declare type DefaultTabValues = {
|
|
||||||
groupId?: number;
|
|
||||||
channelId?: number;
|
|
||||||
clientDatabaseId?: number;
|
|
||||||
};
|
|
||||||
export declare function spawnPermissionEditorModal(connection: ConnectionHandler, defaultTab?: PermissionEditorTab, values?: DefaultTabValues): void;
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
import * as React from "react";
|
||||||
|
import { IpcRegistryDescription, Registry } from "tc-shared/events";
|
||||||
|
import { Translatable } from "tc-shared/ui/react-elements/i18n";
|
||||||
|
import { PermissionEditorEvents } from "tc-shared/ui/modal/permission/EditorDefinitions";
|
||||||
|
import { PermissionEditorTab, PermissionModalEvents } from "tc-shared/ui/modal/permission/ModalDefinitions";
|
||||||
|
import { AbstractModal } from "tc-shared/ui/react-elements/modal/Definitions";
|
||||||
|
export declare type PermissionEditorServerInfo = {
|
||||||
|
handlerId: string;
|
||||||
|
serverUniqueId: string;
|
||||||
|
};
|
||||||
|
export declare const PermissionTabName: {
|
||||||
|
[T in PermissionEditorTab]: {
|
||||||
|
name: string;
|
||||||
|
useTranslate: () => string;
|
||||||
|
renderTranslate: () => React.ReactNode;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
export declare type DefaultTabValues = {
|
||||||
|
groupId?: number;
|
||||||
|
channelId?: number;
|
||||||
|
clientDatabaseId?: number;
|
||||||
|
};
|
||||||
|
export declare class PermissionEditorModal extends AbstractModal {
|
||||||
|
readonly serverInfo: PermissionEditorServerInfo;
|
||||||
|
readonly modalEvents: Registry<PermissionModalEvents>;
|
||||||
|
readonly editorEvents: Registry<PermissionEditorEvents>;
|
||||||
|
constructor(serverInfo: PermissionEditorServerInfo, modalEvents: IpcRegistryDescription<PermissionModalEvents>, editorEvents: IpcRegistryDescription<PermissionEditorEvents>);
|
||||||
|
protected onDestroy(): void;
|
||||||
|
renderBody(): JSX.Element;
|
||||||
|
renderTitle(): React.ReactElement<Translatable>;
|
||||||
|
}
|
||||||
|
export default PermissionEditorModal;
|
|
@ -1,12 +0,0 @@
|
||||||
import * as React from "react";
|
|
||||||
import { Registry } from "tc-shared/events";
|
|
||||||
import { PermissionModalEvents } from "tc-shared/ui/modal/permission/ModalPermissionEditor";
|
|
||||||
import { PermissionEditorEvents } from "tc-shared/ui/modal/permission/PermissionEditor";
|
|
||||||
import { ConnectionHandler } from "tc-shared/ConnectionHandler";
|
|
||||||
export declare class SideBar extends React.Component<{
|
|
||||||
connection: ConnectionHandler;
|
|
||||||
modalEvents: Registry<PermissionModalEvents>;
|
|
||||||
editorEvents: Registry<PermissionEditorEvents>;
|
|
||||||
}, {}> {
|
|
||||||
render(): JSX.Element[];
|
|
||||||
}
|
|
|
@ -1,76 +1,3 @@
|
||||||
import { Registry } from "tc-shared/events";
|
import { Registry } from "tc-shared/events";
|
||||||
import { DeviceListState } from "tc-shared/audio/Recorder";
|
import { MicrophoneSettingsEvents } from "tc-shared/ui/modal/settings/MicrophoneDefinitions";
|
||||||
export declare type MicrophoneSetting = "volume" | "vad-type" | "ppt-key" | "ppt-release-delay" | "ppt-release-delay-active" | "threshold-threshold" | "rnnoise";
|
|
||||||
export declare type MicrophoneDevice = {
|
|
||||||
id: string;
|
|
||||||
name: string;
|
|
||||||
driver: string;
|
|
||||||
default: boolean;
|
|
||||||
};
|
|
||||||
export declare type SelectedMicrophone = {
|
|
||||||
type: "default";
|
|
||||||
} | {
|
|
||||||
type: "none";
|
|
||||||
} | {
|
|
||||||
type: "device";
|
|
||||||
deviceId: string;
|
|
||||||
};
|
|
||||||
export declare type MicrophoneDevices = {
|
|
||||||
status: "error";
|
|
||||||
error: string;
|
|
||||||
} | {
|
|
||||||
status: "audio-not-initialized";
|
|
||||||
} | {
|
|
||||||
status: "no-permissions";
|
|
||||||
shouldAsk: boolean;
|
|
||||||
} | {
|
|
||||||
status: "success";
|
|
||||||
devices: MicrophoneDevice[];
|
|
||||||
selectedDevice: SelectedMicrophone;
|
|
||||||
};
|
|
||||||
export interface MicrophoneSettingsEvents {
|
|
||||||
"query_devices": {
|
|
||||||
refresh_list: boolean;
|
|
||||||
};
|
|
||||||
"query_help": {};
|
|
||||||
"query_setting": {
|
|
||||||
setting: MicrophoneSetting;
|
|
||||||
};
|
|
||||||
"action_help_click": {};
|
|
||||||
"action_request_permissions": {};
|
|
||||||
"action_set_selected_device": {
|
|
||||||
target: SelectedMicrophone;
|
|
||||||
};
|
|
||||||
"action_set_selected_device_result": {
|
|
||||||
status: "error";
|
|
||||||
reason: string;
|
|
||||||
};
|
|
||||||
"action_set_setting": {
|
|
||||||
setting: MicrophoneSetting;
|
|
||||||
value: any;
|
|
||||||
};
|
|
||||||
notify_setting: {
|
|
||||||
setting: MicrophoneSetting;
|
|
||||||
value: any;
|
|
||||||
};
|
|
||||||
notify_devices: MicrophoneDevices;
|
|
||||||
notify_device_selected: {
|
|
||||||
device: SelectedMicrophone;
|
|
||||||
};
|
|
||||||
notify_device_level: {
|
|
||||||
level: {
|
|
||||||
[key: string]: {
|
|
||||||
deviceId: string;
|
|
||||||
status: "success" | "error";
|
|
||||||
level?: number;
|
|
||||||
error?: string;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
status: Exclude<DeviceListState, "error">;
|
|
||||||
};
|
|
||||||
notify_highlight: {
|
|
||||||
field: "hs-0" | "hs-1" | "hs-2" | undefined;
|
|
||||||
};
|
|
||||||
notify_destroy: {};
|
|
||||||
}
|
|
||||||
export declare function initialize_audio_microphone_controller(events: Registry<MicrophoneSettingsEvents>): void;
|
export declare function initialize_audio_microphone_controller(events: Registry<MicrophoneSettingsEvents>): void;
|
||||||
|
|
|
@ -0,0 +1,88 @@
|
||||||
|
import { DeviceListState } from "tc-shared/audio/Recorder";
|
||||||
|
export declare type MicrophoneSetting = "volume" | "vad-type" | "ppt-key" | "ppt-release-delay" | "ppt-release-delay-active" | "threshold-threshold" | "rnnoise";
|
||||||
|
export declare type MicrophoneDevice = {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
driver: string;
|
||||||
|
default: boolean;
|
||||||
|
};
|
||||||
|
export declare type SelectedMicrophone = {
|
||||||
|
type: "default";
|
||||||
|
} | {
|
||||||
|
type: "none";
|
||||||
|
} | {
|
||||||
|
type: "device";
|
||||||
|
deviceId: string;
|
||||||
|
};
|
||||||
|
export declare type MicrophoneDevices = {
|
||||||
|
status: "error";
|
||||||
|
error: string;
|
||||||
|
} | {
|
||||||
|
status: "audio-not-initialized";
|
||||||
|
} | {
|
||||||
|
status: "no-permissions";
|
||||||
|
shouldAsk: boolean;
|
||||||
|
} | {
|
||||||
|
status: "success";
|
||||||
|
devices: MicrophoneDevice[];
|
||||||
|
selectedDevice: SelectedMicrophone;
|
||||||
|
};
|
||||||
|
export declare type InputDeviceLevel = {
|
||||||
|
status: "success";
|
||||||
|
level: number;
|
||||||
|
} | {
|
||||||
|
status: "uninitialized";
|
||||||
|
} | {
|
||||||
|
status: "error";
|
||||||
|
message: string;
|
||||||
|
};
|
||||||
|
export interface MicrophoneSettingsEvents {
|
||||||
|
"query_devices": {
|
||||||
|
refresh_list: boolean;
|
||||||
|
};
|
||||||
|
"query_help": {};
|
||||||
|
"query_setting": {
|
||||||
|
setting: MicrophoneSetting;
|
||||||
|
};
|
||||||
|
"query_input_level": {};
|
||||||
|
"action_help_click": {};
|
||||||
|
"action_request_permissions": {};
|
||||||
|
"action_set_selected_device": {
|
||||||
|
target: SelectedMicrophone;
|
||||||
|
};
|
||||||
|
"action_set_selected_device_result": {
|
||||||
|
status: "error";
|
||||||
|
reason: string;
|
||||||
|
};
|
||||||
|
"action_open_processor_properties": {};
|
||||||
|
"action_set_setting": {
|
||||||
|
setting: MicrophoneSetting;
|
||||||
|
value: any;
|
||||||
|
};
|
||||||
|
notify_setting: {
|
||||||
|
setting: MicrophoneSetting;
|
||||||
|
value: any;
|
||||||
|
};
|
||||||
|
notify_devices: MicrophoneDevices;
|
||||||
|
notify_device_selected: {
|
||||||
|
device: SelectedMicrophone;
|
||||||
|
};
|
||||||
|
notify_device_level: {
|
||||||
|
level: {
|
||||||
|
[key: string]: {
|
||||||
|
deviceId: string;
|
||||||
|
status: "success" | "error";
|
||||||
|
level?: number;
|
||||||
|
error?: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
status: Exclude<DeviceListState, "error">;
|
||||||
|
};
|
||||||
|
notify_input_level: {
|
||||||
|
level: InputDeviceLevel;
|
||||||
|
};
|
||||||
|
notify_highlight: {
|
||||||
|
field: "hs-0" | "hs-1" | "hs-2" | undefined;
|
||||||
|
};
|
||||||
|
notify_destroy: {};
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
/// <reference types="react" />
|
/// <reference types="react" />
|
||||||
import { Registry } from "tc-shared/events";
|
import { Registry } from "tc-shared/events";
|
||||||
import { MicrophoneSettingsEvents } from "tc-shared/ui/modal/settings/Microphone";
|
import { MicrophoneSettingsEvents } from "tc-shared/ui/modal/settings/MicrophoneDefinitions";
|
||||||
export declare const MicrophoneSettings: (props: {
|
export declare const MicrophoneSettings: (props: {
|
||||||
events: Registry<MicrophoneSettingsEvents>;
|
events: Registry<MicrophoneSettingsEvents>;
|
||||||
}) => JSX.Element;
|
}) => JSX.Element;
|
||||||
|
|
|
@ -32,6 +32,7 @@ export declare class NavigationBar extends ReactComponentBase<NavigationBarPrope
|
||||||
private ignoreBlur;
|
private ignoreBlur;
|
||||||
private lastSucceededPath;
|
private lastSucceededPath;
|
||||||
protected defaultState(): NavigationBarState;
|
protected defaultState(): NavigationBarState;
|
||||||
|
componentDidMount(): void;
|
||||||
render(): JSX.Element;
|
render(): JSX.Element;
|
||||||
componentDidUpdate(prevProps: Readonly<NavigationBarProperties>, prevState: Readonly<NavigationBarState>, snapshot?: any): void;
|
componentDidUpdate(prevProps: Readonly<NavigationBarProperties>, prevState: Readonly<NavigationBarState>, snapshot?: any): void;
|
||||||
private onPathClicked;
|
private onPathClicked;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { PluginCmdHandler, PluginCommandInvoker } from "../connection/PluginCmdHandler";
|
|
||||||
import { Registry } from "../events";
|
|
||||||
import { PlayerStatus } from "../video-viewer/Definitions";
|
import { PlayerStatus } from "../video-viewer/Definitions";
|
||||||
|
import { Registry } from "tc-events";
|
||||||
|
import { PluginCmdHandler, PluginCommandInvoker } from "tc-shared/connection/PluginCmdHandler";
|
||||||
export interface W2GEvents {
|
export interface W2GEvents {
|
||||||
notify_watcher_add: {
|
notify_watcher_add: {
|
||||||
watcher: W2GWatcher;
|
watcher: W2GWatcher;
|
|
@ -0,0 +1,6 @@
|
||||||
|
/// <reference types="react" />
|
||||||
|
export declare const Arrow: (props: {
|
||||||
|
direction: NavigationReason;
|
||||||
|
className?: string;
|
||||||
|
onClick?: () => void;
|
||||||
|
}) => JSX.Element;
|
|
@ -6,6 +6,7 @@ export interface CheckboxProperties {
|
||||||
onChange?: (value: boolean) => void;
|
onChange?: (value: boolean) => void;
|
||||||
value?: boolean;
|
value?: boolean;
|
||||||
initialValue?: boolean;
|
initialValue?: boolean;
|
||||||
|
className?: string;
|
||||||
children?: never;
|
children?: never;
|
||||||
}
|
}
|
||||||
export interface CheckboxState {
|
export interface CheckboxState {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/// <reference types="react" />
|
/// <reference types="react" />
|
||||||
export declare const CountryIcon: (props: {
|
export declare const CountryCode: (props: {
|
||||||
country: string;
|
alphaCode: string;
|
||||||
className?: string;
|
className?: string;
|
||||||
}) => JSX.Element;
|
}) => JSX.Element;
|
|
@ -1,5 +1,5 @@
|
||||||
/// <reference types="react" />
|
import * as React from "react";
|
||||||
import { RemoteIcon } from "tc-shared/file/Icons";
|
import { RemoteIcon, RemoteIconInfo } from "tc-shared/file/Icons";
|
||||||
export declare const IconRenderer: (props: {
|
export declare const IconRenderer: (props: {
|
||||||
icon: string;
|
icon: string;
|
||||||
title?: string;
|
title?: string;
|
||||||
|
@ -10,3 +10,8 @@ export declare const RemoteIconRenderer: (props: {
|
||||||
className?: string;
|
className?: string;
|
||||||
title?: string;
|
title?: string;
|
||||||
}) => JSX.Element;
|
}) => JSX.Element;
|
||||||
|
export declare const RemoteIconInfoRenderer: React.MemoExoticComponent<(props: {
|
||||||
|
icon: RemoteIconInfo;
|
||||||
|
className?: string;
|
||||||
|
title?: string;
|
||||||
|
}) => JSX.Element>;
|
||||||
|
|
|
@ -26,3 +26,4 @@ export declare const IconTooltip: (props: {
|
||||||
className?: string;
|
className?: string;
|
||||||
outerClassName?: string;
|
outerClassName?: string;
|
||||||
}) => JSX.Element;
|
}) => JSX.Element;
|
||||||
|
export declare const TooltipHook: React.MemoExoticComponent<() => JSX.Element>;
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import { IpcRegistryDescription, Registry } from "tc-shared/events";
|
import { IpcRegistryDescription, Registry } from "tc-shared/events";
|
||||||
import { VideoViewerEvents } from "tc-shared/video-viewer/Definitions";
|
|
||||||
import { ChannelEditEvents } from "tc-shared/ui/modal/channel-edit/Definitions";
|
import { ChannelEditEvents } from "tc-shared/ui/modal/channel-edit/Definitions";
|
||||||
import { EchoTestEvents } from "tc-shared/ui/modal/echo-test/Definitions";
|
import { EchoTestEvents } from "tc-shared/ui/modal/echo-test/Definitions";
|
||||||
import { ModalGlobalSettingsEditorEvents } from "tc-shared/ui/modal/global-settings-editor/Definitions";
|
import { ModalGlobalSettingsEditorEvents } from "tc-shared/ui/modal/global-settings-editor/Definitions";
|
||||||
|
@ -9,6 +8,14 @@ import { IpcVariableDescriptor } from "tc-shared/ui/utils/IpcVariable";
|
||||||
import { ModalBookmarkEvents, ModalBookmarkVariables } from "tc-shared/ui/modal/bookmarks/Definitions";
|
import { ModalBookmarkEvents, ModalBookmarkVariables } from "tc-shared/ui/modal/bookmarks/Definitions";
|
||||||
import { ModalBookmarksAddServerEvents, ModalBookmarksAddServerVariables } from "tc-shared/ui/modal/bookmarks-add-server/Definitions";
|
import { ModalBookmarksAddServerEvents, ModalBookmarksAddServerVariables } from "tc-shared/ui/modal/bookmarks-add-server/Definitions";
|
||||||
import { ModalPokeEvents, ModalPokeVariables } from "tc-shared/ui/modal/poke/Definitions";
|
import { ModalPokeEvents, ModalPokeVariables } from "tc-shared/ui/modal/poke/Definitions";
|
||||||
|
import { ModalClientGroupAssignmentEvents, ModalClientGroupAssignmentVariables } from "tc-shared/ui/modal/group-assignment/Definitions";
|
||||||
|
import { VideoViewerEvents } from "tc-shared/ui/modal/video-viewer/Definitions";
|
||||||
|
import { PermissionModalEvents } from "tc-shared/ui/modal/permission/ModalDefinitions";
|
||||||
|
import { PermissionEditorEvents } from "tc-shared/ui/modal/permission/EditorDefinitions";
|
||||||
|
import { PermissionEditorServerInfo } from "tc-shared/ui/modal/permission/ModalRenderer";
|
||||||
|
import { ModalAvatarUploadEvents, ModalAvatarUploadVariables } from "tc-shared/ui/modal/avatar-upload/Definitions";
|
||||||
|
import { ModalInputProcessorEvents, ModalInputProcessorVariables } from "tc-shared/ui/modal/input-processor/Definitios";
|
||||||
|
import { ModalAboutVariables } from "tc-shared/ui/modal/about/Definitions";
|
||||||
export declare type ModalType = "error" | "warning" | "info" | "none";
|
export declare type ModalType = "error" | "warning" | "info" | "none";
|
||||||
export declare type ModalRenderType = "page" | "dialog";
|
export declare type ModalRenderType = "page" | "dialog";
|
||||||
export interface ModalOptions {
|
export interface ModalOptions {
|
||||||
|
@ -71,6 +78,8 @@ export interface ModalInstanceController {
|
||||||
getEvents(): Registry<ModalInstanceEvents>;
|
getEvents(): Registry<ModalInstanceEvents>;
|
||||||
show(): Promise<void>;
|
show(): Promise<void>;
|
||||||
hide(): Promise<void>;
|
hide(): Promise<void>;
|
||||||
|
minimize(): Promise<void>;
|
||||||
|
maximize(): Promise<void>;
|
||||||
destroy(): any;
|
destroy(): any;
|
||||||
}
|
}
|
||||||
export interface ModalController {
|
export interface ModalController {
|
||||||
|
@ -92,6 +101,7 @@ export declare abstract class AbstractModal {
|
||||||
type(): ModalType;
|
type(): ModalType;
|
||||||
color(): "none" | "blue";
|
color(): "none" | "blue";
|
||||||
verticalAlignment(): "top" | "center" | "bottom";
|
verticalAlignment(): "top" | "center" | "bottom";
|
||||||
|
/** @deprecated */
|
||||||
protected onInitialize(): void;
|
protected onInitialize(): void;
|
||||||
protected onDestroy(): void;
|
protected onDestroy(): void;
|
||||||
protected onClose(): void;
|
protected onClose(): void;
|
||||||
|
@ -114,4 +124,9 @@ export interface ModalConstructorArguments {
|
||||||
"modal-bookmarks": [IpcRegistryDescription<ModalBookmarkEvents>, IpcVariableDescriptor<ModalBookmarkVariables>];
|
"modal-bookmarks": [IpcRegistryDescription<ModalBookmarkEvents>, IpcVariableDescriptor<ModalBookmarkVariables>];
|
||||||
"modal-bookmark-add-server": [IpcRegistryDescription<ModalBookmarksAddServerEvents>, IpcVariableDescriptor<ModalBookmarksAddServerVariables>];
|
"modal-bookmark-add-server": [IpcRegistryDescription<ModalBookmarksAddServerEvents>, IpcVariableDescriptor<ModalBookmarksAddServerVariables>];
|
||||||
"modal-poked": [IpcRegistryDescription<ModalPokeEvents>, IpcVariableDescriptor<ModalPokeVariables>];
|
"modal-poked": [IpcRegistryDescription<ModalPokeEvents>, IpcVariableDescriptor<ModalPokeVariables>];
|
||||||
|
"modal-assign-server-groups": [IpcRegistryDescription<ModalClientGroupAssignmentEvents>, IpcVariableDescriptor<ModalClientGroupAssignmentVariables>];
|
||||||
|
"modal-permission-edit": [PermissionEditorServerInfo, IpcRegistryDescription<PermissionModalEvents>, IpcRegistryDescription<PermissionEditorEvents>];
|
||||||
|
"modal-avatar-upload": [IpcRegistryDescription<ModalAvatarUploadEvents>, IpcVariableDescriptor<ModalAvatarUploadVariables>, string];
|
||||||
|
"modal-input-processor": [IpcRegistryDescription<ModalInputProcessorEvents>, IpcVariableDescriptor<ModalInputProcessorVariables>];
|
||||||
|
"modal-about": [IpcRegistryDescription, IpcVariableDescriptor<ModalAboutVariables>];
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,7 +33,6 @@ export declare class PageModalRenderer extends React.PureComponent<{
|
||||||
modalInstance: AbstractModal;
|
modalInstance: AbstractModal;
|
||||||
onBackdropClicked: () => void;
|
onBackdropClicked: () => void;
|
||||||
children: React.ReactElement<ModalFrameRenderer>;
|
children: React.ReactElement<ModalFrameRenderer>;
|
||||||
}, {
|
|
||||||
shown: boolean;
|
shown: boolean;
|
||||||
}> {
|
}> {
|
||||||
constructor(props: any);
|
constructor(props: any);
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import { Registry } from "tc-events";
|
import { Registry } from "tc-events";
|
||||||
import { ModalOptions } from "tc-shared/ui/react-elements/modal/Definitions";
|
import { ModalInstanceController, ModalInstanceEvents, ModalOptions, ModalState } from "tc-shared/ui/react-elements/modal/Definitions";
|
||||||
import { ModalInstanceController, ModalInstanceEvents, ModalState } from "tc-shared/ui/react-elements/modal/Definitions";
|
|
||||||
export declare class ExternalModalController implements ModalInstanceController {
|
export declare class ExternalModalController implements ModalInstanceController {
|
||||||
private readonly modalType;
|
private readonly modalType;
|
||||||
private readonly modalOptions;
|
private readonly modalOptions;
|
||||||
|
@ -10,6 +9,7 @@ export declare class ExternalModalController implements ModalInstanceController
|
||||||
private ipcRemotePeerId;
|
private ipcRemotePeerId;
|
||||||
private ipcChannel;
|
private ipcChannel;
|
||||||
private readonly modalEvents;
|
private readonly modalEvents;
|
||||||
|
private modalInitialized;
|
||||||
private modalInitializeCallback;
|
private modalInitializeCallback;
|
||||||
private windowId;
|
private windowId;
|
||||||
private windowListener;
|
private windowListener;
|
||||||
|
@ -20,6 +20,8 @@ export declare class ExternalModalController implements ModalInstanceController
|
||||||
getState(): ModalState;
|
getState(): ModalState;
|
||||||
show(): Promise<void>;
|
show(): Promise<void>;
|
||||||
hide(): Promise<void>;
|
hide(): Promise<void>;
|
||||||
|
minimize(): Promise<void>;
|
||||||
|
maximize(): Promise<void>;
|
||||||
private mutateWindow;
|
private mutateWindow;
|
||||||
private handleWindowDestroyed;
|
private handleWindowDestroyed;
|
||||||
private registerIpcMessageHandler;
|
private registerIpcMessageHandler;
|
||||||
|
|
|
@ -1,25 +1,40 @@
|
||||||
import { ModalInstanceController, ModalInstanceEvents, ModalOptions, ModalState } from "tc-shared/ui/react-elements/modal/Definitions";
|
import { AbstractModal, ModalInstanceController, ModalInstanceEvents, ModalOptions, ModalState } from "tc-shared/ui/react-elements/modal/Definitions";
|
||||||
|
import * as React from "react";
|
||||||
import { RegisteredModal } from "tc-shared/ui/react-elements/modal/Registry";
|
import { RegisteredModal } from "tc-shared/ui/react-elements/modal/Registry";
|
||||||
import { Registry } from "tc-events";
|
import { Registry } from "tc-events";
|
||||||
|
declare class InternalRendererInstance extends React.PureComponent<{
|
||||||
|
instance: InternalModalInstance;
|
||||||
|
}, {
|
||||||
|
shown: boolean;
|
||||||
|
}> {
|
||||||
|
constructor(props: any);
|
||||||
|
render(): JSX.Element;
|
||||||
|
componentWillUnmount(): void;
|
||||||
|
}
|
||||||
export declare class InternalModalInstance implements ModalInstanceController {
|
export declare class InternalModalInstance implements ModalInstanceController {
|
||||||
|
readonly instanceUniqueId: string;
|
||||||
readonly events: Registry<ModalInstanceEvents>;
|
readonly events: Registry<ModalInstanceEvents>;
|
||||||
|
readonly refRendererInstance: React.RefObject<InternalRendererInstance>;
|
||||||
private readonly modalKlass;
|
private readonly modalKlass;
|
||||||
private readonly constructorArguments;
|
private readonly constructorArguments;
|
||||||
private readonly rendererInstance;
|
|
||||||
private readonly modalOptions;
|
private readonly modalOptions;
|
||||||
private state;
|
private state;
|
||||||
private modalInstance;
|
modalInstance: AbstractModal;
|
||||||
private htmlContainer;
|
|
||||||
private modalInitializePromise;
|
private modalInitializePromise;
|
||||||
constructor(modalType: RegisteredModal<any>, constructorArguments: any[], modalOptions: ModalOptions);
|
constructor(modalType: RegisteredModal<any>, constructorArguments: any[], modalOptions: ModalOptions);
|
||||||
private constructModal;
|
private constructModal;
|
||||||
private destructModal;
|
private destructModal;
|
||||||
|
private destructModalInstance;
|
||||||
getState(): ModalState;
|
getState(): ModalState;
|
||||||
getEvents(): Registry<ModalInstanceEvents>;
|
getEvents(): Registry<ModalInstanceEvents>;
|
||||||
show(): Promise<void>;
|
show(): Promise<void>;
|
||||||
hide(): Promise<void>;
|
hide(): Promise<void>;
|
||||||
|
minimize(): Promise<void>;
|
||||||
|
maximize(): Promise<void>;
|
||||||
destroy(): void;
|
destroy(): void;
|
||||||
private getCloseCallback;
|
getCloseCallback(): () => void;
|
||||||
private getPopoutCallback;
|
getPopoutCallback(): () => void;
|
||||||
private getMinimizeCallback;
|
getMinimizeCallback(): any;
|
||||||
}
|
}
|
||||||
|
export declare const InternalModalHook: React.MemoExoticComponent<() => JSX.Element>;
|
||||||
|
export {};
|
||||||
|
|
|
@ -209,9 +209,6 @@ export interface ChannelTreeUIEvents {
|
||||||
treeEntryId: number;
|
treeEntryId: number;
|
||||||
unread: boolean;
|
unread: boolean;
|
||||||
};
|
};
|
||||||
notify_visibility_changed: {
|
|
||||||
visible: boolean;
|
|
||||||
};
|
|
||||||
notify_destroy: {};
|
notify_destroy: {};
|
||||||
}
|
}
|
||||||
export declare type ChannelTreeDragEntry = {
|
export declare type ChannelTreeDragEntry = {
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
|
declare type EntryTagStyle = "text-only" | "normal";
|
||||||
export declare const ServerTag: React.MemoExoticComponent<(props: {
|
export declare const ServerTag: React.MemoExoticComponent<(props: {
|
||||||
serverName: string;
|
serverName: string;
|
||||||
handlerId: string;
|
handlerId: string;
|
||||||
serverUniqueId?: string;
|
serverUniqueId?: string;
|
||||||
className?: string;
|
className?: string;
|
||||||
|
style?: EntryTagStyle;
|
||||||
}) => JSX.Element>;
|
}) => JSX.Element>;
|
||||||
export declare const ClientTag: React.MemoExoticComponent<(props: {
|
export declare const ClientTag: React.MemoExoticComponent<(props: {
|
||||||
clientName: string;
|
clientName: string;
|
||||||
|
@ -12,6 +14,7 @@ export declare const ClientTag: React.MemoExoticComponent<(props: {
|
||||||
clientId?: number;
|
clientId?: number;
|
||||||
clientDatabaseId?: number;
|
clientDatabaseId?: number;
|
||||||
className?: string;
|
className?: string;
|
||||||
|
style?: EntryTagStyle;
|
||||||
}) => JSX.Element>;
|
}) => JSX.Element>;
|
||||||
export declare const ChannelTag: React.MemoExoticComponent<(props: {
|
export declare const ChannelTag: React.MemoExoticComponent<(props: {
|
||||||
channelName: string;
|
channelName: string;
|
||||||
|
@ -19,3 +22,4 @@ export declare const ChannelTag: React.MemoExoticComponent<(props: {
|
||||||
handlerId: string;
|
handlerId: string;
|
||||||
className?: string;
|
className?: string;
|
||||||
}) => JSX.Element>;
|
}) => JSX.Element>;
|
||||||
|
export {};
|
||||||
|
|
|
@ -32,7 +32,6 @@ export declare class ChannelTreeView extends ReactComponentBase<ChannelTreeViewP
|
||||||
constructor(props: any);
|
constructor(props: any);
|
||||||
componentDidMount(): void;
|
componentDidMount(): void;
|
||||||
componentWillUnmount(): void;
|
componentWillUnmount(): void;
|
||||||
private handleVisibilityChanged;
|
|
||||||
private visibleEntries;
|
private visibleEntries;
|
||||||
render(): JSX.Element;
|
render(): JSX.Element;
|
||||||
private onScroll;
|
private onScroll;
|
||||||
|
|
|
@ -20,6 +20,7 @@ export declare abstract class UiVariableProvider<Variables extends UiVariableMap
|
||||||
getArtificialDelay(): number;
|
getArtificialDelay(): number;
|
||||||
setArtificialDelay(value: number): void;
|
setArtificialDelay(value: number): void;
|
||||||
setVariableProvider<T extends keyof Variables>(variable: T, provider: (customData: any) => Variables[T] | Promise<Variables[T]>): void;
|
setVariableProvider<T extends keyof Variables>(variable: T, provider: (customData: any) => Variables[T] | Promise<Variables[T]>): void;
|
||||||
|
setVariableProviderAsync<T extends keyof Variables>(variable: T, provider: (customData: any) => Promise<Variables[T]>): void;
|
||||||
/**
|
/**
|
||||||
* @param variable
|
* @param variable
|
||||||
* @param editor If the editor returns `false` or a new variable, such variable will be used
|
* @param editor If the editor returns `false` or a new variable, such variable will be used
|
||||||
|
|
|
@ -2,7 +2,10 @@ import { ChangeLog } from "../update/ChangeLog";
|
||||||
export interface Updater {
|
export interface Updater {
|
||||||
getChangeLog(): ChangeLog;
|
getChangeLog(): ChangeLog;
|
||||||
getChangeList(oldVersion: string): ChangeLog;
|
getChangeList(oldVersion: string): ChangeLog;
|
||||||
getLastUsedVersion(): string;
|
/**
|
||||||
|
* @returns `undefined` if `updateUsedVersion()` never has been called.
|
||||||
|
*/
|
||||||
|
getLastUsedVersion(): string | undefined;
|
||||||
getCurrentVersion(): string;
|
getCurrentVersion(): string;
|
||||||
updateUsedVersion(): any;
|
updateUsedVersion(): any;
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,6 +64,112 @@ export declare enum FilterMode {
|
||||||
*/
|
*/
|
||||||
Block = 2
|
Block = 2
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* All available options for input processing.
|
||||||
|
* Since input processing is only available on the native client these are the options
|
||||||
|
* the native client (especially WebRTC audio processing) have.
|
||||||
|
*/
|
||||||
|
export interface InputProcessorConfigWebRTC {
|
||||||
|
"pipeline.maximum_internal_processing_rate": number;
|
||||||
|
"pipeline.multi_channel_render": boolean;
|
||||||
|
"pipeline.multi_channel_capture": boolean;
|
||||||
|
"pre_amplifier.enabled": boolean;
|
||||||
|
"pre_amplifier.fixed_gain_factor": number;
|
||||||
|
"high_pass_filter.enabled": boolean;
|
||||||
|
"high_pass_filter.apply_in_full_band": boolean;
|
||||||
|
"echo_canceller.enabled": boolean;
|
||||||
|
"echo_canceller.mobile_mode": boolean;
|
||||||
|
"echo_canceller.export_linear_aec_output": boolean;
|
||||||
|
"echo_canceller.enforce_high_pass_filtering": boolean;
|
||||||
|
"noise_suppression.enabled": boolean;
|
||||||
|
"noise_suppression.level": "low" | "moderate" | "high" | "very-high";
|
||||||
|
"noise_suppression.analyze_linear_aec_output_when_available": boolean;
|
||||||
|
"transient_suppression.enabled": boolean;
|
||||||
|
"voice_detection.enabled": boolean;
|
||||||
|
"gain_controller1.enabled": boolean;
|
||||||
|
"gain_controller1.mode": "adaptive-analog" | "adaptive-digital" | "fixed-digital";
|
||||||
|
"gain_controller1.target_level_dbfs": number;
|
||||||
|
"gain_controller1.compression_gain_db": number;
|
||||||
|
"gain_controller1.enable_limiter": boolean;
|
||||||
|
"gain_controller1.analog_level_minimum": number;
|
||||||
|
"gain_controller1.analog_level_maximum": number;
|
||||||
|
"gain_controller1.analog_gain_controller.enabled": boolean;
|
||||||
|
"gain_controller1.analog_gain_controller.startup_min_volume": number;
|
||||||
|
"gain_controller1.analog_gain_controller.clipped_level_min": number;
|
||||||
|
"gain_controller1.analog_gain_controller.enable_agc2_level_estimator": boolean;
|
||||||
|
"gain_controller1.analog_gain_controller.enable_digital_adaptive": boolean;
|
||||||
|
"gain_controller2.enabled": boolean;
|
||||||
|
"gain_controller2.fixed_digital.gain_db": number;
|
||||||
|
"gain_controller2.adaptive_digital.enabled": boolean;
|
||||||
|
"gain_controller2.adaptive_digital.vad_probability_attack": number;
|
||||||
|
"gain_controller2.adaptive_digital.level_estimator": "rms" | "peak";
|
||||||
|
"gain_controller2.adaptive_digital.level_estimator_adjacent_speech_frames_threshold": number;
|
||||||
|
"gain_controller2.adaptive_digital.use_saturation_protector": boolean;
|
||||||
|
"gain_controller2.adaptive_digital.initial_saturation_margin_db": number;
|
||||||
|
"gain_controller2.adaptive_digital.extra_saturation_margin_db": number;
|
||||||
|
"gain_controller2.adaptive_digital.gain_applier_adjacent_speech_frames_threshold": number;
|
||||||
|
"gain_controller2.adaptive_digital.max_gain_change_db_per_second": number;
|
||||||
|
"gain_controller2.adaptive_digital.max_output_noise_level_dbfs": number;
|
||||||
|
"residual_echo_detector.enabled": boolean;
|
||||||
|
"level_estimation.enabled": boolean;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Attention:
|
||||||
|
* These keys **MUST** be equal to all keys of `InputProcessorConfigWebRTC`.
|
||||||
|
* All keys not registered in here will not be consideration.
|
||||||
|
*/
|
||||||
|
export declare const kInputProcessorConfigWebRTCKeys: (keyof InputProcessorConfigWebRTC)[];
|
||||||
|
export interface InputProcessorConfigRNNoise {
|
||||||
|
"rnnoise.enabled": boolean;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Attention:
|
||||||
|
* These keys **MUST** be equal to all keys of `InputProcessorConfigWebRTC`.
|
||||||
|
* All keys not registered in here will not be consideration.
|
||||||
|
*/
|
||||||
|
export declare const kInputProcessorConfigRNNoiseKeys: (keyof InputProcessorConfigRNNoise)[];
|
||||||
|
export interface InputProcessorConfigMapping {
|
||||||
|
"webrtc-processing": InputProcessorConfigWebRTC;
|
||||||
|
"rnnoise": InputProcessorConfigRNNoise;
|
||||||
|
}
|
||||||
|
export declare type InputProcessorType = keyof InputProcessorConfigMapping;
|
||||||
|
export interface InputProcessorStatistics {
|
||||||
|
output_rms_dbfs: number | undefined;
|
||||||
|
voice_detected: number | undefined;
|
||||||
|
echo_return_loss: number | undefined;
|
||||||
|
echo_return_loss_enhancement: number | undefined;
|
||||||
|
divergent_filter_fraction: number | undefined;
|
||||||
|
delay_median_ms: number | undefined;
|
||||||
|
delay_standard_deviation_ms: number | undefined;
|
||||||
|
residual_echo_likelihood: number | undefined;
|
||||||
|
residual_echo_likelihood_recent_max: number | undefined;
|
||||||
|
delay_ms: number | undefined;
|
||||||
|
rnnoise_volume: number | undefined;
|
||||||
|
}
|
||||||
|
export interface InputProcessor {
|
||||||
|
/**
|
||||||
|
* @param processor Target processor type
|
||||||
|
* @returns `true` if the target processor type is supported and available
|
||||||
|
*/
|
||||||
|
hasProcessor(processor: InputProcessorType): boolean;
|
||||||
|
/**
|
||||||
|
* Get the processor config of the target type.
|
||||||
|
* This method will throw when the target processor isn't supported.
|
||||||
|
* @param processor Target processor type.
|
||||||
|
* @returns The processor config.
|
||||||
|
*/
|
||||||
|
getProcessorConfig<T extends InputProcessorType>(processor: T): InputProcessorConfigMapping[T];
|
||||||
|
/**
|
||||||
|
* Apply the target config.
|
||||||
|
* @param processor
|
||||||
|
* @param config
|
||||||
|
*/
|
||||||
|
applyProcessorConfig<T extends InputProcessorType>(processor: T, config: InputProcessorConfigMapping[T]): any;
|
||||||
|
/**
|
||||||
|
* Get the current processor statistics.
|
||||||
|
*/
|
||||||
|
getStatistics(): InputProcessorStatistics;
|
||||||
|
}
|
||||||
export interface AbstractInput {
|
export interface AbstractInput {
|
||||||
readonly events: Registry<InputEvents>;
|
readonly events: Registry<InputEvents>;
|
||||||
currentState(): InputState;
|
currentState(): InputState;
|
||||||
|
@ -89,6 +195,13 @@ export interface AbstractInput {
|
||||||
removeFilter(filter: Filter): any;
|
removeFilter(filter: Filter): any;
|
||||||
getVolume(): number;
|
getVolume(): number;
|
||||||
setVolume(volume: number): any;
|
setVolume(volume: number): any;
|
||||||
|
getInputProcessor(): InputProcessor;
|
||||||
|
/**
|
||||||
|
* Create a new level meter for this audio input.
|
||||||
|
* This level meter will be indicate the audio level after all processing.
|
||||||
|
* Note: Changing the input device or stopping the input will result in no activity.
|
||||||
|
*/
|
||||||
|
createLevelMeter(): LevelMeter;
|
||||||
}
|
}
|
||||||
export interface LevelMeter {
|
export interface LevelMeter {
|
||||||
getDevice(): InputDevice;
|
getDevice(): InputDevice;
|
||||||
|
|
|
@ -29,6 +29,27 @@ export declare const defaultRecorderEvents: Registry<DefaultRecorderEvents>;
|
||||||
export declare function setDefaultRecorder(recorder: RecorderProfile): void;
|
export declare function setDefaultRecorder(recorder: RecorderProfile): void;
|
||||||
export interface RecorderProfileEvents {
|
export interface RecorderProfileEvents {
|
||||||
notify_device_changed: {};
|
notify_device_changed: {};
|
||||||
|
notify_voice_start: {};
|
||||||
|
notify_voice_end: {};
|
||||||
|
notify_input_initialized: {};
|
||||||
|
}
|
||||||
|
export declare abstract class RecorderProfileOwner {
|
||||||
|
/**
|
||||||
|
* This method will be called from the recorder profile.
|
||||||
|
*/
|
||||||
|
protected abstract handleUnmount(): any;
|
||||||
|
/**
|
||||||
|
* This callback will be called when the recorder audio input has
|
||||||
|
* been initialized.
|
||||||
|
* Note: This method might be called within ownRecorder().
|
||||||
|
* If this method has been called, handleUnmount will be called.
|
||||||
|
*
|
||||||
|
* @param input The target input.
|
||||||
|
*/
|
||||||
|
protected abstract handleRecorderInput(input: AbstractInput): any;
|
||||||
|
}
|
||||||
|
export declare abstract class ConnectionRecorderProfileOwner extends RecorderProfileOwner {
|
||||||
|
abstract getConnection(): ConnectionHandler;
|
||||||
}
|
}
|
||||||
export declare class RecorderProfile {
|
export declare class RecorderProfile {
|
||||||
readonly events: Registry<RecorderProfileEvents>;
|
readonly events: Registry<RecorderProfileEvents>;
|
||||||
|
@ -36,11 +57,9 @@ export declare class RecorderProfile {
|
||||||
readonly volatile: any;
|
readonly volatile: any;
|
||||||
config: RecorderProfileConfig;
|
config: RecorderProfileConfig;
|
||||||
input: AbstractInput;
|
input: AbstractInput;
|
||||||
|
private currentOwner;
|
||||||
|
private currentOwnerMutex;
|
||||||
current_handler: ConnectionHandler;
|
current_handler: ConnectionHandler;
|
||||||
callback_input_initialized: (input: AbstractInput) => void;
|
|
||||||
callback_start: () => any;
|
|
||||||
callback_stop: () => any;
|
|
||||||
callback_unmount: () => any;
|
|
||||||
private readonly pptHook;
|
private readonly pptHook;
|
||||||
private pptTimeout;
|
private pptTimeout;
|
||||||
private pptHookRegistered;
|
private pptHookRegistered;
|
||||||
|
@ -52,6 +71,13 @@ export declare class RecorderProfile {
|
||||||
private save;
|
private save;
|
||||||
private reinitializePPTHook;
|
private reinitializePPTHook;
|
||||||
private reinitializeFilter;
|
private reinitializeFilter;
|
||||||
|
/**
|
||||||
|
* Own the recorder.
|
||||||
|
*/
|
||||||
|
ownRecorder(target: RecorderProfileOwner | undefined): Promise<void>;
|
||||||
|
getOwner(): RecorderProfileOwner | undefined;
|
||||||
|
isInputActive(): boolean;
|
||||||
|
/** @deprecated use `ownRecorder(undefined)` */
|
||||||
unmount(): Promise<void>;
|
unmount(): Promise<void>;
|
||||||
getVadType(): VadType;
|
getVadType(): VadType;
|
||||||
setVadType(type: VadType): boolean;
|
setVadType(type: VadType): boolean;
|
||||||
|
|
|
@ -123,5 +123,5 @@ function deploy_client() {
|
||||||
#install_npm
|
#install_npm
|
||||||
#compile_scripts
|
#compile_scripts
|
||||||
#compile_native
|
#compile_native
|
||||||
package_client
|
#package_client
|
||||||
deploy_client
|
deploy_client
|
||||||
|
|
|
@ -39,24 +39,11 @@ export function initialize() {
|
||||||
window.displayCriticalError = _impl;
|
window.displayCriticalError = _impl;
|
||||||
}
|
}
|
||||||
|
|
||||||
loader.register_task(loader.Stage.JAVASCRIPT, {
|
loader.register_task(Stage.JAVASCRIPT, {
|
||||||
name: "teaclient jquery",
|
name: "handler initialize #2",
|
||||||
|
priority: -1,
|
||||||
function: async () => {
|
function: async () => {
|
||||||
window.$ = require("jquery");
|
await import("../renderer/hooks/StorageAdapter");
|
||||||
|
|
||||||
window.jQuery = window.$;
|
|
||||||
Object.assign(window.$, window.jsrender = require('jsrender'));
|
|
||||||
},
|
|
||||||
priority: 80
|
|
||||||
});
|
|
||||||
|
|
||||||
loader.register_task(Stage.JAVASCRIPT_INITIALIZING, {
|
|
||||||
name: "handler initialize",
|
|
||||||
priority: 80,
|
|
||||||
function: async () => {
|
|
||||||
await import("../renderer/Logger");
|
|
||||||
await import("../renderer/PersistentLocalStorage");
|
|
||||||
await import("../renderer/ContextMenu");
|
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
}
|
}
|
|
@ -0,0 +1,65 @@
|
||||||
|
import * as electron from "electron";
|
||||||
|
import * as path from "path";
|
||||||
|
import * as fs from "fs-extra";
|
||||||
|
import {StorageAdapter} from "tc-shared/StorageAdapter";
|
||||||
|
import {ServerSettingsStorage} from "tc-shared/ServerSettings";
|
||||||
|
import {LogCategory, logError} from "tc-shared/log";
|
||||||
|
|
||||||
|
const kStoragePath = path.join(electron.remote.app.getPath("userData"), "settings");
|
||||||
|
|
||||||
|
function storageKeyPath(key: string) {
|
||||||
|
return path.join(kStoragePath, encodeURIComponent(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
export class ClientStorageAdapter implements StorageAdapter {
|
||||||
|
delete(key: string): Promise<void> {
|
||||||
|
return fs.remove(storageKeyPath(key)).catch(error => {});
|
||||||
|
}
|
||||||
|
|
||||||
|
async get(key: string): Promise<string | null> {
|
||||||
|
try {
|
||||||
|
const result = await fs.readFile(storageKeyPath(key));
|
||||||
|
return JSON.parse(result.toString());
|
||||||
|
} catch (error) {
|
||||||
|
logError(LogCategory.GENERAL, tr("Failed to load client storage key %s: %o"), key, error);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
has(key: string): Promise<boolean> {
|
||||||
|
return fs.pathExists(storageKeyPath(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
set(key: string, value: string): Promise<void> {
|
||||||
|
return fs.writeFile(storageKeyPath(key), JSON.stringify(value)).catch(error => {
|
||||||
|
logError(LogCategory.GENERAL, tr("Failed to set client storage key %s: %o"), key, error);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export let clientStorage;
|
||||||
|
|
||||||
|
export class ClientServerSettingsStorage implements ServerSettingsStorage {
|
||||||
|
get(serverUniqueId: string): string {
|
||||||
|
try {
|
||||||
|
const result = fs.readFileSync(storageKeyPath("settings.server_" + serverUniqueId));
|
||||||
|
return JSON.parse(result.toString());
|
||||||
|
} catch (error) {
|
||||||
|
logError(LogCategory.GENERAL, tr("Failed to load individual server settings for %s: %o"), serverUniqueId, error);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
set(serverUniqueId: string, value: string) {
|
||||||
|
try {
|
||||||
|
fs.writeFileSync(storageKeyPath("settings.server_" + serverUniqueId), JSON.stringify(value));
|
||||||
|
} catch (error) {
|
||||||
|
logError(LogCategory.GENERAL, tr("Failed to write individual server settings for %s: %o"), serverUniqueId, error);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function initializeClientStorage() {
|
||||||
|
await fs.mkdirp(kStoragePath);
|
||||||
|
clientStorage = new ClientStorageAdapter();
|
||||||
|
}
|
|
@ -3,13 +3,15 @@ import * as path from "path";
|
||||||
import * as fs from "fs-extra";
|
import * as fs from "fs-extra";
|
||||||
import {Updater} from "tc-shared/update/Updater";
|
import {Updater} from "tc-shared/update/Updater";
|
||||||
import {ChangeLog, ChangeSetEntry} from "tc-shared/update/ChangeLog";
|
import {ChangeLog, ChangeSetEntry} from "tc-shared/update/ChangeLog";
|
||||||
|
import {settings, Settings} from "tc-shared/settings";
|
||||||
|
|
||||||
function getChangeLogFile() {
|
function getChangeLogFile() {
|
||||||
const app_path = electron.remote.app.getAppPath();
|
const app_path = electron.remote.app.getAppPath();
|
||||||
if(app_path.endsWith(".asar"))
|
if(app_path.endsWith(".asar")) {
|
||||||
return path.join(path.dirname(app_path), "..", "ChangeLog.txt");
|
return path.join(path.dirname(app_path), "..", "ChangeLog.txt");
|
||||||
else
|
} else {
|
||||||
return path.join(app_path, "github", "ChangeLog.txt"); /* We've the source master :D */
|
return path.join(app_path, "github", "ChangeLog.txt"); /* We've the source :D */
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const EntryRegex = /^([0-9]+)\.([0-9]+)\.([0-9]+)(-b[0-9]+)?:$/m;
|
const EntryRegex = /^([0-9]+)\.([0-9]+)\.([0-9]+)(-b[0-9]+)?:$/m;
|
||||||
|
@ -31,8 +33,9 @@ function parseChangeLogEntry(lines: string[], index: number) : { entries: Change
|
||||||
if(trimmed[0] === '-') {
|
if(trimmed[0] === '-') {
|
||||||
const depth = lines[index].indexOf('-');
|
const depth = lines[index].indexOf('-');
|
||||||
if(depth > entryDepth) {
|
if(depth > entryDepth) {
|
||||||
if(typeof currentEntry === "undefined")
|
if(typeof currentEntry === "undefined") {
|
||||||
throw "missing change child entries parent at line " + index;
|
throw "missing change child entries parent at line " + index;
|
||||||
|
}
|
||||||
|
|
||||||
const result = parseChangeLogEntry(lines, index);
|
const result = parseChangeLogEntry(lines, index);
|
||||||
entries.push({
|
entries.push({
|
||||||
|
@ -45,8 +48,9 @@ function parseChangeLogEntry(lines: string[], index: number) : { entries: Change
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
/* new entry */
|
/* new entry */
|
||||||
if(typeof currentEntry === "string")
|
if(typeof currentEntry === "string") {
|
||||||
entries.push(currentEntry);
|
entries.push(currentEntry);
|
||||||
|
}
|
||||||
|
|
||||||
currentEntry = trimmed.substr(1).trim();
|
currentEntry = trimmed.substr(1).trim();
|
||||||
}
|
}
|
||||||
|
@ -57,8 +61,9 @@ function parseChangeLogEntry(lines: string[], index: number) : { entries: Change
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(typeof currentEntry === "string")
|
if(typeof currentEntry === "string") {
|
||||||
entries.push(currentEntry);
|
entries.push(currentEntry);
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
index: index,
|
index: index,
|
||||||
|
@ -75,8 +80,9 @@ async function parseClientChangeLog() : Promise<ChangeLog> {
|
||||||
const lines = (await fs.readFile(getChangeLogFile())).toString("UTF-8").split("\n");
|
const lines = (await fs.readFile(getChangeLogFile())).toString("UTF-8").split("\n");
|
||||||
let index = 0;
|
let index = 0;
|
||||||
|
|
||||||
while(index < lines.length && !lines[index].match(EntryRegex))
|
while(index < lines.length && !lines[index].match(EntryRegex)) {
|
||||||
index++;
|
index++;
|
||||||
|
}
|
||||||
|
|
||||||
while(index < lines.length) {
|
while(index < lines.length) {
|
||||||
const [ _, major, minor, patch, build ] = lines[index].match(EntryRegex);
|
const [ _, major, minor, patch, build ] = lines[index].match(EntryRegex);
|
||||||
|
@ -93,7 +99,6 @@ async function parseClientChangeLog() : Promise<ChangeLog> {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
const kLastUsedVersionKey = "updater-used-version-native";
|
|
||||||
export class ClientUpdater implements Updater {
|
export class ClientUpdater implements Updater {
|
||||||
private changeLog: ChangeLog;
|
private changeLog: ChangeLog;
|
||||||
private currentVersion: string;
|
private currentVersion: string;
|
||||||
|
@ -131,10 +136,10 @@ export class ClientUpdater implements Updater {
|
||||||
}
|
}
|
||||||
|
|
||||||
getLastUsedVersion(): string {
|
getLastUsedVersion(): string {
|
||||||
return localStorage.getItem(kLastUsedVersionKey) || "1.4.9";
|
return settings.getValue(Settings.KEY_UPDATER_LAST_USED_CLIENT, undefined);
|
||||||
}
|
}
|
||||||
|
|
||||||
updateUsedVersion() {
|
updateUsedVersion() {
|
||||||
localStorage.setItem(kLastUsedVersionKey, this.getCurrentVersion());
|
settings.setValue(Settings.KEY_UPDATER_LAST_USED_CLIENT, this.getCurrentVersion());
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
import {ContextMenuEntry, ContextMenuFactory, setGlobalContextMenuFactory} from "tc-shared/ui/ContextMenu";
|
import {ContextMenuEntry, ContextMenuFactory} from "tc-shared/ui/ContextMenu";
|
||||||
import * as electron from "electron";
|
import * as electron from "electron";
|
||||||
import {MenuItemConstructorOptions} from "electron";
|
import {MenuItemConstructorOptions} from "electron";
|
||||||
import {clientIconClassToImage, remoteIconDatafier, RemoteIconWrapper} from "./IconHelper";
|
import {clientIconClassToImage, remoteIconDatafier, RemoteIconWrapper} from "./IconHelper";
|
||||||
|
@ -109,7 +109,7 @@ class ContextMenuInstance {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setGlobalContextMenuFactory(new class implements ContextMenuFactory {
|
export class ClientContextMenuFactory implements ContextMenuFactory {
|
||||||
closeContextMenu() {
|
closeContextMenu() {
|
||||||
currentMenu?.destroy();
|
currentMenu?.destroy();
|
||||||
currentMenu = undefined;
|
currentMenu = undefined;
|
||||||
|
@ -120,4 +120,4 @@ setGlobalContextMenuFactory(new class implements ContextMenuFactory {
|
||||||
currentMenu = new ContextMenuInstance(entries, callbackClose);
|
currentMenu = new ContextMenuInstance(entries, callbackClose);
|
||||||
currentMenu.spawn(position.pageX, position.pageY);
|
currentMenu.spawn(position.pageX, position.pageY);
|
||||||
}
|
}
|
||||||
});
|
};
|
|
@ -37,7 +37,7 @@ function create_logger(name: string) : Logger {
|
||||||
const log = (type, message: string, ...args) => {
|
const log = (type, message: string, ...args) => {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case LogType.TRACE:
|
case LogType.TRACE:
|
||||||
original_console.trace(message, ...args);
|
original_console.debug(message, ...args);
|
||||||
break;
|
break;
|
||||||
case LogType.DEBUG:
|
case LogType.DEBUG:
|
||||||
original_console.debug(message, ...args);
|
original_console.debug(message, ...args);
|
||||||
|
|
|
@ -1,99 +0,0 @@
|
||||||
import * as electron from "electron";
|
|
||||||
import * as path from "path";
|
|
||||||
import * as fs from "fs-extra";
|
|
||||||
|
|
||||||
const APP_DATA = electron.remote.app.getPath("userData");
|
|
||||||
const SETTINGS_DIR = path.join(APP_DATA, "settings");
|
|
||||||
|
|
||||||
let _local_storage: {[key: string]: any} = {};
|
|
||||||
let _local_storage_save: {[key: string]: boolean} = {};
|
|
||||||
let _save_timer: number;
|
|
||||||
|
|
||||||
export async function initialize() {
|
|
||||||
await fs.mkdirp(SETTINGS_DIR);
|
|
||||||
|
|
||||||
console.error("Load local storage from: %o", SETTINGS_DIR);
|
|
||||||
const files = await fs.readdir(SETTINGS_DIR);
|
|
||||||
for(const file of files) {
|
|
||||||
const key = decodeURIComponent(file);
|
|
||||||
console.log("Load settings: %s", key);
|
|
||||||
|
|
||||||
try {
|
|
||||||
const data = await fs.readFile(path.join(SETTINGS_DIR, file));
|
|
||||||
_local_storage[key] = JSON.parse(data.toString() || "{}");
|
|
||||||
} catch(error) {
|
|
||||||
const target_file = path.join(SETTINGS_DIR, file + "." + Date.now() + ".broken");
|
|
||||||
console.error("Failed to load settings for %s: %o. Moving settings so the file does not get overridden. Target file: %s", key, error, target_file);
|
|
||||||
try {
|
|
||||||
await fs.move(path.join(SETTINGS_DIR, file), target_file);
|
|
||||||
} catch (error) {
|
|
||||||
console.warn("Failed to move broken settings file!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let _new_storage: Storage = {} as any;
|
|
||||||
|
|
||||||
_new_storage.getItem = key => _local_storage[key] || null;
|
|
||||||
_new_storage.setItem = (key, value) => {
|
|
||||||
_local_storage[key] = value;
|
|
||||||
_local_storage_save[key] = true;
|
|
||||||
(_new_storage as any)["length"] = Object.keys(_local_storage).length;
|
|
||||||
};
|
|
||||||
|
|
||||||
_new_storage.clear = () => {
|
|
||||||
_local_storage = {};
|
|
||||||
_local_storage_save = {};
|
|
||||||
|
|
||||||
try {
|
|
||||||
fs.emptyDirSync(SETTINGS_DIR);
|
|
||||||
} catch(error) {
|
|
||||||
console.warn("Failed to empty settings dir");
|
|
||||||
}
|
|
||||||
(_new_storage as any)["length"] = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
_new_storage.key = index => Object.keys(_local_storage)[index];
|
|
||||||
_new_storage.removeItem = key => {
|
|
||||||
delete _local_storage[key];
|
|
||||||
delete_key(key).catch(error => {
|
|
||||||
console.warn("Failed to delete key on fs: %s => %o", key, error);
|
|
||||||
});
|
|
||||||
(_new_storage as any)["length"] = Object.keys(_local_storage).length;
|
|
||||||
};
|
|
||||||
Object.assign(window.localStorage, _new_storage);
|
|
||||||
|
|
||||||
/* try to save everything all 60 seconds */
|
|
||||||
_save_timer = setInterval(() => {
|
|
||||||
save_all_sync();
|
|
||||||
}, 60 * 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function save_all_sync() {
|
|
||||||
for(const key of Object.keys(_local_storage_save))
|
|
||||||
save_key_sync(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
function key_path(key: string) {
|
|
||||||
return path.join(SETTINGS_DIR, encodeURIComponent(key));
|
|
||||||
}
|
|
||||||
|
|
||||||
export function save_key_sync(key: string) {
|
|
||||||
if(!_local_storage_save[key])
|
|
||||||
return;
|
|
||||||
|
|
||||||
delete _local_storage_save[key];
|
|
||||||
const setting_path = key_path(key);
|
|
||||||
fs.writeJsonSync(setting_path, _local_storage[key], {spaces: 0});
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function delete_key(key: string) {
|
|
||||||
delete _local_storage_save[key];
|
|
||||||
const setting_path = key_path(key);
|
|
||||||
await fs.remove(setting_path); /* could be async because we're not carrying about data */
|
|
||||||
}
|
|
||||||
|
|
||||||
window.addEventListener("beforeunload", () => {
|
|
||||||
console.log("Save local storage");
|
|
||||||
save_all_sync();
|
|
||||||
});
|
|
|
@ -25,6 +25,10 @@ export class NativeWindowManager implements WindowManager {
|
||||||
constructor() {
|
constructor() {
|
||||||
this.windowInstances = {};
|
this.windowInstances = {};
|
||||||
this.events = new Registry<WindowManagerEvents>();
|
this.events = new Registry<WindowManagerEvents>();
|
||||||
|
|
||||||
|
window.onunload = () => {
|
||||||
|
Object.values(this.windowInstances).forEach(window => window.destroy());
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
getEvents(): Registry<WindowManagerEvents> {
|
getEvents(): Registry<WindowManagerEvents> {
|
||||||
|
|
|
@ -4,8 +4,14 @@ import {
|
||||||
InputConsumer,
|
InputConsumer,
|
||||||
InputConsumerType,
|
InputConsumerType,
|
||||||
InputEvents,
|
InputEvents,
|
||||||
|
InputProcessor,
|
||||||
|
InputProcessorConfigMapping,
|
||||||
|
InputProcessorStatistics,
|
||||||
|
InputProcessorType,
|
||||||
InputStartError,
|
InputStartError,
|
||||||
InputState,
|
InputState,
|
||||||
|
kInputProcessorConfigRNNoiseKeys,
|
||||||
|
kInputProcessorConfigWebRTCKeys,
|
||||||
LevelMeter,
|
LevelMeter,
|
||||||
} from "tc-shared/voice/RecorderBase";
|
} from "tc-shared/voice/RecorderBase";
|
||||||
import {audio} from "tc-native/connection";
|
import {audio} from "tc-native/connection";
|
||||||
|
@ -17,15 +23,16 @@ import {getRecorderBackend, InputDevice} from "tc-shared/audio/Recorder";
|
||||||
import {LogCategory, logError, logTrace, logWarn} from "tc-shared/log";
|
import {LogCategory, logError, logTrace, logWarn} from "tc-shared/log";
|
||||||
import {Settings, settings} from "tc-shared/settings";
|
import {Settings, settings} from "tc-shared/settings";
|
||||||
import NativeFilterMode = audio.record.FilterMode;
|
import NativeFilterMode = audio.record.FilterMode;
|
||||||
|
import AudioProcessor = audio.record.AudioProcessor;
|
||||||
|
|
||||||
export class NativeInput implements AbstractInput {
|
export class NativeInput implements AbstractInput {
|
||||||
static readonly instances = [] as NativeInput[];
|
|
||||||
|
|
||||||
readonly events: Registry<InputEvents>;
|
readonly events: Registry<InputEvents>;
|
||||||
|
|
||||||
readonly nativeHandle: audio.record.AudioRecorder;
|
private readonly inputProcessor: NativeInputProcessor;
|
||||||
readonly nativeConsumer: audio.record.AudioConsumer;
|
private readonly nativeHandle: audio.record.AudioRecorder;
|
||||||
|
private readonly nativeConsumer: audio.record.AudioConsumer;
|
||||||
|
|
||||||
|
private listenerRNNoise: () => void;
|
||||||
private state: InputState;
|
private state: InputState;
|
||||||
private deviceId: string | undefined;
|
private deviceId: string | undefined;
|
||||||
|
|
||||||
|
@ -36,9 +43,11 @@ export class NativeInput implements AbstractInput {
|
||||||
this.events = new Registry<InputEvents>();
|
this.events = new Registry<InputEvents>();
|
||||||
|
|
||||||
this.nativeHandle = audio.record.create_recorder();
|
this.nativeHandle = audio.record.create_recorder();
|
||||||
|
this.inputProcessor = new NativeInputProcessor(this.nativeHandle.get_audio_processor());
|
||||||
|
this.inputProcessor.applyProcessorConfig("rnnoise", { "rnnoise.enabled": settings.getValue(Settings.KEY_RNNOISE_FILTER) });
|
||||||
|
this.listenerRNNoise = settings.globalChangeListener(Settings.KEY_RNNOISE_FILTER, newValue => this.inputProcessor.applyProcessorConfig("rnnoise", { "rnnoise.enabled": newValue }));
|
||||||
|
|
||||||
this.nativeConsumer = this.nativeHandle.create_consumer();
|
this.nativeConsumer = this.nativeHandle.create_consumer();
|
||||||
this.nativeConsumer.toggle_rnnoise(settings.getValue(Settings.KEY_RNNOISE_FILTER));
|
|
||||||
|
|
||||||
this.nativeConsumer.callback_ended = () => {
|
this.nativeConsumer.callback_ended = () => {
|
||||||
this.filtered = true;
|
this.filtered = true;
|
||||||
|
@ -50,13 +59,12 @@ export class NativeInput implements AbstractInput {
|
||||||
};
|
};
|
||||||
|
|
||||||
this.state = InputState.PAUSED;
|
this.state = InputState.PAUSED;
|
||||||
NativeInput.instances.push(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
destroy() {
|
destroy() {
|
||||||
const index = NativeInput.instances.indexOf(this);
|
if(this.listenerRNNoise) {
|
||||||
if(index !== -1) {
|
this.listenerRNNoise();
|
||||||
NativeInput.instances.splice(index, 1);
|
this.listenerRNNoise = undefined;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -267,43 +275,145 @@ export class NativeInput implements AbstractInput {
|
||||||
this.nativeConsumer.set_filter_mode(nativeMode);
|
this.nativeConsumer.set_filter_mode(nativeMode);
|
||||||
this.events.fire("notify_filter_mode_changed", { oldMode, newMode: mode });
|
this.events.fire("notify_filter_mode_changed", { oldMode, newMode: mode });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getInputProcessor(): InputProcessor {
|
||||||
|
return this.inputProcessor;
|
||||||
|
}
|
||||||
|
|
||||||
|
createLevelMeter(): LevelMeter {
|
||||||
|
return new NativeInputLevelMeter(this.nativeHandle.create_level_meter("post-process"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class NativeInputProcessor implements InputProcessor {
|
||||||
|
private readonly processor: AudioProcessor;
|
||||||
|
|
||||||
|
constructor(processor: AudioProcessor) {
|
||||||
|
this.processor = processor;
|
||||||
|
}
|
||||||
|
|
||||||
|
applyProcessorConfig<T extends InputProcessorType>(processor: T, config: Partial<InputProcessorConfigMapping[T]>) {
|
||||||
|
let keys: string[];
|
||||||
|
switch (processor) {
|
||||||
|
case "webrtc-processing":
|
||||||
|
keys = kInputProcessorConfigWebRTCKeys;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "rnnoise":
|
||||||
|
keys = kInputProcessorConfigRNNoiseKeys;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw "invalid processor";
|
||||||
|
}
|
||||||
|
|
||||||
|
const filteredConfig = {};
|
||||||
|
keys.forEach(key => {
|
||||||
|
if(typeof config[key] === "undefined") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
filteredConfig[key] = config[key];
|
||||||
|
});
|
||||||
|
this.processor.apply_config(filteredConfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
getProcessorConfig<T extends InputProcessorType>(processor: T): InputProcessorConfigMapping[T] {
|
||||||
|
let keys: string[];
|
||||||
|
const config = this.processor.get_config();
|
||||||
|
|
||||||
|
switch (processor) {
|
||||||
|
case "webrtc-processing":
|
||||||
|
keys = kInputProcessorConfigWebRTCKeys;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "rnnoise":
|
||||||
|
keys = kInputProcessorConfigRNNoiseKeys;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw "invalid processor";
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = {};
|
||||||
|
keys.forEach(key => result[key] = config[key]);
|
||||||
|
return result as any;
|
||||||
|
}
|
||||||
|
|
||||||
|
getStatistics(): InputProcessorStatistics {
|
||||||
|
return this.processor.get_statistics();
|
||||||
|
}
|
||||||
|
|
||||||
|
hasProcessor(processor: InputProcessorType): boolean {
|
||||||
|
switch (processor) {
|
||||||
|
case "rnnoise":
|
||||||
|
case "webrtc-processing":
|
||||||
|
return true;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class NativeInputLevelMeter implements LevelMeter {
|
||||||
|
private nativeHandle: audio.record.AudioLevelMeter;
|
||||||
|
|
||||||
|
constructor(nativeHandle: audio.record.AudioLevelMeter) {
|
||||||
|
this.nativeHandle = nativeHandle;
|
||||||
|
this.nativeHandle.start(error => {
|
||||||
|
if(typeof error !== "undefined") {
|
||||||
|
logError(LogCategory.AUDIO, tr("Native input audio level meter failed to start. This should not happen. Reason: %o"), error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
destroy(): any {
|
||||||
|
this.nativeHandle?.set_callback(undefined);
|
||||||
|
this.nativeHandle?.stop();
|
||||||
|
this.nativeHandle = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
getDevice(): InputDevice {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
setObserver(callback: (value: number) => any) {
|
||||||
|
this.nativeHandle.set_callback(level => {
|
||||||
|
try {
|
||||||
|
callback(level);
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class NativeLevelMeter implements LevelMeter {
|
export class NativeLevelMeter implements LevelMeter {
|
||||||
static readonly instances: NativeLevelMeter[] = [];
|
|
||||||
readonly targetDevice: InputDevice;
|
readonly targetDevice: InputDevice;
|
||||||
|
|
||||||
public nativeRecorder: audio.record.AudioRecorder;
|
private nativeHandle: audio.record.AudioLevelMeter;
|
||||||
public nativeConsumer: audio.record.AudioConsumer;
|
|
||||||
|
|
||||||
private callback: (num: number) => any;
|
|
||||||
private nativeFilter: audio.record.ThresholdConsumeFilter;
|
|
||||||
|
|
||||||
constructor(device: InputDevice) {
|
constructor(device: InputDevice) {
|
||||||
this.targetDevice = device;
|
this.targetDevice = device;
|
||||||
this.callback = () => {};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async initialize() {
|
async initialize() {
|
||||||
try {
|
try {
|
||||||
this.nativeRecorder = audio.record.create_recorder();
|
this.nativeHandle = audio.record.create_device_level_meter(this.targetDevice.deviceId);
|
||||||
this.nativeConsumer = this.nativeRecorder.create_consumer();
|
|
||||||
|
|
||||||
this.nativeConsumer.toggle_rnnoise(settings.getValue(Settings.KEY_RNNOISE_FILTER));
|
|
||||||
|
|
||||||
this.nativeFilter = this.nativeConsumer.create_filter_threshold(.5);
|
|
||||||
this.nativeFilter.set_attack_smooth(.75);
|
|
||||||
this.nativeFilter.set_release_smooth(.75);
|
|
||||||
|
|
||||||
await new Promise(resolve => this.nativeRecorder.set_device(this.targetDevice.deviceId, resolve));
|
|
||||||
await new Promise((resolve, reject) => {
|
await new Promise((resolve, reject) => {
|
||||||
this.nativeRecorder.start(flag => {
|
this.nativeHandle.start(error => {
|
||||||
if (typeof flag === "boolean" && flag)
|
if(typeof error !== "undefined") {
|
||||||
resolve();
|
reject(error);
|
||||||
else
|
} else {
|
||||||
reject(typeof flag === "string" ? flag : "failed to start");
|
resolve(error);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/* TODO: May implement smoothing to the native level meter as well? */
|
||||||
|
//this.nativeFilter.set_attack_smooth(.75);
|
||||||
|
//this.nativeFilter.set_release_smooth(.75);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (typeof (error) === "string") {
|
if (typeof (error) === "string") {
|
||||||
throw error;
|
throw error;
|
||||||
|
@ -312,40 +422,25 @@ export class NativeLevelMeter implements LevelMeter {
|
||||||
logWarn(LogCategory.AUDIO, tr("Failed to initialize level meter for device %o: %o"), this.targetDevice, error);
|
logWarn(LogCategory.AUDIO, tr("Failed to initialize level meter for device %o: %o"), this.targetDevice, error);
|
||||||
throw "initialize failed (lookup console)";
|
throw "initialize failed (lookup console)";
|
||||||
}
|
}
|
||||||
|
|
||||||
/* references this variable, needs a destroy() call, else memory leak */
|
|
||||||
this.nativeFilter.set_analyze_filter(value => this.callback(value));
|
|
||||||
NativeLevelMeter.instances.push(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
destroy() {
|
destroy() {
|
||||||
const index = NativeLevelMeter.instances.indexOf(this);
|
this.nativeHandle?.set_callback(undefined);
|
||||||
if(index !== -1) {
|
this.nativeHandle?.stop();
|
||||||
NativeLevelMeter.instances.splice(index, 1);
|
this.nativeHandle = undefined;
|
||||||
}
|
|
||||||
|
|
||||||
if (this.nativeFilter) {
|
|
||||||
this.nativeFilter.set_analyze_filter(undefined);
|
|
||||||
this.nativeConsumer.unregister_filter(this.nativeFilter);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.nativeConsumer) {
|
|
||||||
this.nativeRecorder.delete_consumer(this.nativeConsumer);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(this.nativeRecorder) {
|
|
||||||
this.nativeRecorder.stop();
|
|
||||||
}
|
|
||||||
this.nativeRecorder = undefined;
|
|
||||||
this.nativeConsumer = undefined;
|
|
||||||
this.nativeFilter = undefined;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getDevice(): InputDevice {
|
getDevice(): InputDevice {
|
||||||
return this.targetDevice;
|
return this.targetDevice;
|
||||||
}
|
}
|
||||||
|
|
||||||
setObserver(callback: (value: number) => any) {
|
setObserver(callback: (value: number) => void) {
|
||||||
this.callback = callback || (() => {});
|
this.nativeHandle.set_callback(level => {
|
||||||
|
try {
|
||||||
|
callback(level);
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -171,7 +171,7 @@ class ErrorCommandHandler extends AbstractCommandHandler {
|
||||||
connection_bandwidth_received_last_minute_speech: 0,
|
connection_bandwidth_received_last_minute_speech: 0,
|
||||||
connection_bandwidth_received_last_minute_keepalive: 0,
|
connection_bandwidth_received_last_minute_keepalive: 0,
|
||||||
connection_bandwidth_received_last_minute_control: 0
|
connection_bandwidth_received_last_minute_control: 0
|
||||||
}
|
}, { process_result: false }
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -211,9 +211,23 @@ export class ServerConnection extends AbstractServerConnection {
|
||||||
|
|
||||||
this.nativeHandle = spawn_native_server_connection();
|
this.nativeHandle = spawn_native_server_connection();
|
||||||
this.nativeHandle.callback_disconnect = reason => {
|
this.nativeHandle.callback_disconnect = reason => {
|
||||||
this.client.handleDisconnect(DisconnectReason.CONNECTION_CLOSED, {
|
switch (this.connectionState) {
|
||||||
reason: reason
|
case ConnectionState.CONNECTING:
|
||||||
});
|
case ConnectionState.AUTHENTICATING:
|
||||||
|
case ConnectionState.INITIALISING:
|
||||||
|
this.client.handleDisconnect(DisconnectReason.CONNECT_FAILURE, reason);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ConnectionState.CONNECTED:
|
||||||
|
this.client.handleDisconnect(DisconnectReason.CONNECTION_CLOSED, {
|
||||||
|
reason: reason
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ConnectionState.DISCONNECTING:
|
||||||
|
case ConnectionState.UNCONNECTED:
|
||||||
|
break;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
this.nativeHandle.callback_command = (command, args, switches) => {
|
this.nativeHandle.callback_command = (command, args, switches) => {
|
||||||
console.log("Received: %o %o %o", command, args, switches);
|
console.log("Received: %o %o %o", command, args, switches);
|
||||||
|
|
|
@ -3,18 +3,20 @@ import {
|
||||||
VoiceConnectionStatus,
|
VoiceConnectionStatus,
|
||||||
WhisperSessionInitializer
|
WhisperSessionInitializer
|
||||||
} from "tc-shared/connection/VoiceConnection";
|
} from "tc-shared/connection/VoiceConnection";
|
||||||
import {RecorderProfile} from "tc-shared/voice/RecorderProfile";
|
import {ConnectionRecorderProfileOwner, RecorderProfile} from "tc-shared/voice/RecorderProfile";
|
||||||
import {NativeServerConnection, NativeVoiceClient, NativeVoiceConnection, PlayerState} from "tc-native/connection";
|
import {NativeServerConnection, NativeVoiceClient, NativeVoiceConnection, PlayerState} from "tc-native/connection";
|
||||||
import {ServerConnection} from "./ServerConnection";
|
import {ServerConnection} from "./ServerConnection";
|
||||||
import {VoiceClient} from "tc-shared/voice/VoiceClient";
|
import {VoiceClient} from "tc-shared/voice/VoiceClient";
|
||||||
import {WhisperSession, WhisperTarget} from "tc-shared/voice/VoiceWhisper";
|
import {WhisperSession, WhisperTarget} from "tc-shared/voice/VoiceWhisper";
|
||||||
import {NativeInput} from "../audio/AudioRecorder";
|
import {NativeInput} from "../audio/AudioRecorder";
|
||||||
import {ConnectionState} from "tc-shared/ConnectionHandler";
|
import {ConnectionHandler, ConnectionState} from "tc-shared/ConnectionHandler";
|
||||||
import {VoicePlayerEvents, VoicePlayerLatencySettings, VoicePlayerState} from "tc-shared/voice/VoicePlayer";
|
import {VoicePlayerEvents, VoicePlayerLatencySettings, VoicePlayerState} from "tc-shared/voice/VoicePlayer";
|
||||||
import {Registry} from "tc-shared/events";
|
import {Registry} from "tc-shared/events";
|
||||||
import {LogCategory, logDebug, logInfo, logWarn} from "tc-shared/log";
|
import {LogCategory, logError, logInfo, logWarn} from "tc-shared/log";
|
||||||
import {tr} from "tc-shared/i18n/localize";
|
import {tr} from "tc-shared/i18n/localize";
|
||||||
import {ConnectionStatistics} from "tc-shared/connection/ConnectionBase";
|
import {ConnectionStatistics} from "tc-shared/connection/ConnectionBase";
|
||||||
|
import {AbstractInput} from "tc-shared/voice/RecorderBase";
|
||||||
|
import {crashOnThrow, ignorePromise} from "tc-shared/proto";
|
||||||
|
|
||||||
export class NativeVoiceConnectionWrapper extends AbstractVoiceConnection {
|
export class NativeVoiceConnectionWrapper extends AbstractVoiceConnection {
|
||||||
private readonly serverConnectionStateChangedListener;
|
private readonly serverConnectionStateChangedListener;
|
||||||
|
@ -24,6 +26,9 @@ export class NativeVoiceConnectionWrapper extends AbstractVoiceConnection {
|
||||||
private connectionState: VoiceConnectionStatus;
|
private connectionState: VoiceConnectionStatus;
|
||||||
private currentRecorder: RecorderProfile;
|
private currentRecorder: RecorderProfile;
|
||||||
|
|
||||||
|
private ignoreRecorderUnmount: boolean;
|
||||||
|
private listenerRecorder: (() => void)[];
|
||||||
|
|
||||||
private registeredVoiceClients: {[key: number]: NativeVoiceClientWrapper} = {};
|
private registeredVoiceClients: {[key: number]: NativeVoiceClientWrapper} = {};
|
||||||
|
|
||||||
private currentlyReplayingAudio = false;
|
private currentlyReplayingAudio = false;
|
||||||
|
@ -32,6 +37,7 @@ export class NativeVoiceConnectionWrapper extends AbstractVoiceConnection {
|
||||||
constructor(connection: ServerConnection, voice: NativeVoiceConnection) {
|
constructor(connection: ServerConnection, voice: NativeVoiceConnection) {
|
||||||
super(connection);
|
super(connection);
|
||||||
this.native = voice;
|
this.native = voice;
|
||||||
|
this.ignoreRecorderUnmount = false;
|
||||||
|
|
||||||
this.serverConnectionStateChangedListener = () => {
|
this.serverConnectionStateChangedListener = () => {
|
||||||
if(this.connection.getConnectionState() === ConnectionState.CONNECTED) {
|
if(this.connection.getConnectionState() === ConnectionState.CONNECTED) {
|
||||||
|
@ -78,46 +84,61 @@ export class NativeVoiceConnectionWrapper extends AbstractVoiceConnection {
|
||||||
return this.native.decoding_supported(codec);
|
return this.native.decoding_supported(codec);
|
||||||
}
|
}
|
||||||
|
|
||||||
async acquireVoiceRecorder(recorder: RecorderProfile | undefined): Promise<void> {
|
async acquireVoiceRecorder(recorder: RecorderProfile | undefined, enforce?: boolean): Promise<void> {
|
||||||
if(this.currentRecorder === recorder) {
|
if(this.currentRecorder === recorder && !enforce) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(this.currentRecorder) {
|
this.listenerRecorder?.forEach(callback => callback());
|
||||||
this.currentRecorder.callback_unmount = undefined;
|
this.listenerRecorder = undefined;
|
||||||
this.native.set_audio_source(undefined);
|
|
||||||
|
|
||||||
this.handleVoiceEndEvent();
|
if(this.currentRecorder) {
|
||||||
await this.currentRecorder.unmount();
|
this.ignoreRecorderUnmount = true;
|
||||||
this.currentRecorder = undefined;
|
this.ignoreRecorderUnmount = false;
|
||||||
|
|
||||||
|
this.native.set_audio_source(undefined);
|
||||||
}
|
}
|
||||||
|
|
||||||
await recorder?.unmount();
|
|
||||||
const oldRecorder = recorder;
|
const oldRecorder = recorder;
|
||||||
this.currentRecorder = recorder;
|
this.currentRecorder = recorder;
|
||||||
|
|
||||||
try {
|
if(this.currentRecorder) {
|
||||||
if(recorder) {
|
const connection = this;
|
||||||
if(!(recorder.input instanceof NativeInput)) {
|
await recorder.ownRecorder(new class extends ConnectionRecorderProfileOwner {
|
||||||
this.currentRecorder = undefined;
|
getConnection(): ConnectionHandler {
|
||||||
throw "Recorder input must be an instance of NativeInput!";
|
return connection.connection.client;
|
||||||
}
|
}
|
||||||
|
|
||||||
recorder.current_handler = this.connection.client;
|
protected handleRecorderInput(input: AbstractInput): any {
|
||||||
recorder.callback_unmount = () => {
|
if(!(input instanceof NativeInput)) {
|
||||||
logDebug(LogCategory.VOICE, tr("Lost voice recorder..."));
|
logError(LogCategory.VOICE, tr("Recorder input isn't an instance of NativeInput. Ignoring recorder input."));
|
||||||
this.acquireVoiceRecorder(undefined);
|
return;
|
||||||
};
|
}
|
||||||
|
|
||||||
recorder.callback_start = this.handleVoiceStartEvent.bind(this);
|
connection.native.set_audio_source(input.getNativeConsumer());
|
||||||
recorder.callback_stop = this.handleVoiceEndEvent.bind(this);
|
}
|
||||||
|
|
||||||
this.native.set_audio_source(recorder.input.getNativeConsumer());
|
protected handleUnmount(): any {
|
||||||
}
|
if(connection.ignoreRecorderUnmount) {
|
||||||
} catch(error) {
|
return;
|
||||||
this.currentRecorder = undefined;
|
}
|
||||||
throw error;
|
|
||||||
|
connection.currentRecorder = undefined;
|
||||||
|
ignorePromise(crashOnThrow(connection.acquireVoiceRecorder(undefined, true)));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.listenerRecorder = [];
|
||||||
|
this.listenerRecorder.push(recorder.events.on("notify_voice_start", () => this.handleVoiceStartEvent()));
|
||||||
|
this.listenerRecorder.push(recorder.events.on("notify_voice_end", () => this.handleVoiceEndEvent(tr("recorder event"))));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(this.currentRecorder?.isInputActive()) {
|
||||||
|
this.handleVoiceStartEvent();
|
||||||
|
} else {
|
||||||
|
this.handleVoiceEndEvent(tr("recorder change"));
|
||||||
|
}
|
||||||
|
|
||||||
this.events.fire("notify_recorder_changed", {
|
this.events.fire("notify_recorder_changed", {
|
||||||
oldRecorder,
|
oldRecorder,
|
||||||
newRecorder: recorder
|
newRecorder: recorder
|
||||||
|
@ -144,6 +165,7 @@ export class NativeVoiceConnectionWrapper extends AbstractVoiceConnection {
|
||||||
if(status === this.currentlyReplayingAudio) {
|
if(status === this.currentlyReplayingAudio) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.currentlyReplayingAudio = status;
|
this.currentlyReplayingAudio = status;
|
||||||
this.events.fire("notify_voice_replay_state_change", { replaying: status });
|
this.events.fire("notify_voice_replay_state_change", { replaying: status });
|
||||||
}
|
}
|
||||||
|
@ -161,26 +183,22 @@ export class NativeVoiceConnectionWrapper extends AbstractVoiceConnection {
|
||||||
|
|
||||||
this.native.enable_voice_send(true);
|
this.native.enable_voice_send(true);
|
||||||
this.localAudioStarted = true;
|
this.localAudioStarted = true;
|
||||||
logInfo(LogCategory.VOICE, tr("Local voice started"));
|
|
||||||
|
|
||||||
const ch = chandler.getClient();
|
logInfo(LogCategory.VOICE, tr("Local voice started"));
|
||||||
if(ch) ch.speaking = true;
|
chandler.getClient()?.setSpeaking(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private handleVoiceEndEvent() {
|
private handleVoiceEndEvent(reason: string) {
|
||||||
this.native.enable_voice_send(false);
|
this.native.enable_voice_send(false);
|
||||||
|
|
||||||
|
if(!this.localAudioStarted) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const chandler = this.connection.client;
|
const chandler = this.connection.client;
|
||||||
const ch = chandler.getClient();
|
chandler.getClient()?.setSpeaking(false);
|
||||||
if(ch) ch.speaking = false;
|
|
||||||
|
|
||||||
if(!chandler.connected)
|
logInfo(LogCategory.VOICE, tr("Local voice ended (%s)"), reason);
|
||||||
return false;
|
|
||||||
|
|
||||||
if(chandler.isMicrophoneMuted())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
logInfo(LogCategory.VOICE, tr("Local voice ended"));
|
|
||||||
this.localAudioStarted = false;
|
this.localAudioStarted = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -196,12 +214,15 @@ export class NativeVoiceConnectionWrapper extends AbstractVoiceConnection {
|
||||||
}
|
}
|
||||||
|
|
||||||
unregisterVoiceClient(client: VoiceClient) {
|
unregisterVoiceClient(client: VoiceClient) {
|
||||||
if(!(client instanceof NativeVoiceClientWrapper))
|
if(!(client instanceof NativeVoiceClientWrapper)) {
|
||||||
throw "invalid client type";
|
throw "invalid client type";
|
||||||
|
}
|
||||||
|
|
||||||
delete this.registeredVoiceClients[client.getClientId()];
|
delete this.registeredVoiceClients[client.getClientId()];
|
||||||
this.native.unregister_client(client.getClientId());
|
this.native.unregister_client(client.getClientId());
|
||||||
client.destroy();
|
client.destroy();
|
||||||
|
|
||||||
|
this.handleVoiceClientStateChange();
|
||||||
}
|
}
|
||||||
|
|
||||||
stopAllVoiceReplays() {
|
stopAllVoiceReplays() {
|
||||||
|
@ -221,18 +242,15 @@ export class NativeVoiceConnectionWrapper extends AbstractVoiceConnection {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
setWhisperSessionInitializer(initializer: WhisperSessionInitializer | undefined) {
|
setWhisperSessionInitializer(initializer: WhisperSessionInitializer | undefined) { }
|
||||||
}
|
|
||||||
|
|
||||||
startWhisper(target: WhisperTarget): Promise<void> {
|
startWhisper(target: WhisperTarget): Promise<void> {
|
||||||
return Promise.resolve(undefined);
|
return Promise.resolve(undefined);
|
||||||
}
|
}
|
||||||
|
|
||||||
dropWhisperSession(session: WhisperSession) {
|
dropWhisperSession(session: WhisperSession) { }
|
||||||
}
|
|
||||||
|
|
||||||
stopWhisper() {
|
stopWhisper() { }
|
||||||
}
|
|
||||||
|
|
||||||
getConnectionStats(): Promise<ConnectionStatistics> {
|
getConnectionStats(): Promise<ConnectionStatistics> {
|
||||||
/* FIXME: This is iffy! */
|
/* FIXME: This is iffy! */
|
||||||
|
@ -276,6 +294,10 @@ class NativeVoiceClientWrapper implements VoiceClient {
|
||||||
case PlayerState.STOPPING:
|
case PlayerState.STOPPING:
|
||||||
this.setState(VoicePlayerState.STOPPING);
|
this.setState(VoicePlayerState.STOPPING);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
logError(LogCategory.VOICE, tr("Native audio player has invalid state: %o"), state);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,13 +17,4 @@ setRecorderBackend(new class implements AudioRecorderBacked {
|
||||||
getDeviceList(): DeviceList {
|
getDeviceList(): DeviceList {
|
||||||
return inputDeviceList;
|
return inputDeviceList;
|
||||||
}
|
}
|
||||||
|
|
||||||
isRnNoiseSupported(): boolean {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
toggleRnNoise(target: boolean) {
|
|
||||||
NativeLevelMeter.instances.forEach(input => input.nativeConsumer.toggle_rnnoise(target));
|
|
||||||
NativeInput.instances.forEach(input => input.nativeConsumer.toggle_rnnoise(target));
|
|
||||||
}
|
|
||||||
});
|
});
|
|
@ -0,0 +1,11 @@
|
||||||
|
import * as loader from "tc-loader";
|
||||||
|
import {setGlobalContextMenuFactory} from "tc-shared/ui/ContextMenu";
|
||||||
|
import {ClientContextMenuFactory} from "../ContextMenu";
|
||||||
|
|
||||||
|
loader.register_task(loader.Stage.JAVASCRIPT_INITIALIZING, {
|
||||||
|
name: "context menu",
|
||||||
|
function: async () => {
|
||||||
|
setGlobalContextMenuFactory(new ClientContextMenuFactory());
|
||||||
|
},
|
||||||
|
priority: 60
|
||||||
|
});
|
|
@ -0,0 +1,10 @@
|
||||||
|
import * as loader from "tc-loader";
|
||||||
|
import {Stage} from "tc-loader";
|
||||||
|
import {ClientServerSettingsStorage} from "../ClientStorage";
|
||||||
|
import {setServerSettingsStorage} from "tc-shared/ServerSettings";
|
||||||
|
|
||||||
|
loader.register_task(Stage.JAVASCRIPT_INITIALIZING, {
|
||||||
|
name: "server storage init",
|
||||||
|
function: async () => setServerSettingsStorage(new ClientServerSettingsStorage()),
|
||||||
|
priority: 80
|
||||||
|
});
|
|
@ -0,0 +1,15 @@
|
||||||
|
import {setStorageAdapter} from "tc-shared/StorageAdapter";
|
||||||
|
import {clientStorage, initializeClientStorage} from "../ClientStorage";
|
||||||
|
import * as loader from "tc-loader";
|
||||||
|
import {Stage} from "tc-loader";
|
||||||
|
|
||||||
|
loader.register_task(Stage.JAVASCRIPT_INITIALIZING, {
|
||||||
|
name: "storage init",
|
||||||
|
function: async () => {
|
||||||
|
await initializeClientStorage();
|
||||||
|
setStorageAdapter(clientStorage);
|
||||||
|
},
|
||||||
|
|
||||||
|
/* Must come before everything else! */
|
||||||
|
priority: 10_000
|
||||||
|
});
|
|
@ -1,9 +1,12 @@
|
||||||
|
import "./StorageAdapter";
|
||||||
|
import "./ContextMenu";
|
||||||
import "./AudioInput";
|
import "./AudioInput";
|
||||||
import "./AudioBackend";
|
import "./AudioBackend";
|
||||||
import "./Backend";
|
import "./Backend";
|
||||||
import "./ChangeLogClient";
|
import "./ChangeLogClient";
|
||||||
import "./Dns";
|
import "./Dns";
|
||||||
import "./MenuBar";
|
import "./MenuBar";
|
||||||
|
import "./ServerSettingsAdapter";
|
||||||
import "./ServerConnection";
|
import "./ServerConnection";
|
||||||
import "./Video";
|
import "./Video";
|
||||||
import "./Sound";
|
import "./Sound";
|
||||||
|
|
|
@ -41,26 +41,6 @@ declare global {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* we use out own jquery resource */
|
|
||||||
loader.register_task(loader.Stage.JAVASCRIPT, {
|
|
||||||
name: "teaclient jquery",
|
|
||||||
function: async () => {
|
|
||||||
window.$ = require("jquery");
|
|
||||||
window.jQuery = window.$;
|
|
||||||
Object.assign(window.$, window.jsrender = require('jsrender'));
|
|
||||||
},
|
|
||||||
priority: 80
|
|
||||||
});
|
|
||||||
|
|
||||||
loader.register_task(loader.Stage.SETUP, {
|
|
||||||
name: "teaclient initialize persistent storage",
|
|
||||||
function: async () => {
|
|
||||||
const storage = require("./PersistentLocalStorage");
|
|
||||||
await storage.initialize();
|
|
||||||
},
|
|
||||||
priority: 90
|
|
||||||
});
|
|
||||||
|
|
||||||
loader.register_task(loader.Stage.INITIALIZING, {
|
loader.register_task(loader.Stage.INITIALIZING, {
|
||||||
name: "teaclient initialize logging",
|
name: "teaclient initialize logging",
|
||||||
function: async () => {
|
function: async () => {
|
||||||
|
@ -149,19 +129,16 @@ loader.register_task(loader.Stage.LOADED, {
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
loader.register_task(loader.Stage.JAVASCRIPT_INITIALIZING, {
|
loader.register_task(loader.Stage.JAVASCRIPT, {
|
||||||
name: "teaclient load adapters",
|
name: "teaclient load adapters",
|
||||||
function: async () => {
|
function: async () => {
|
||||||
/* all files which replaces a native driver */
|
/* all files which replaces a native driver */
|
||||||
try {
|
try {
|
||||||
await import("./MenuBar");
|
await import("./hooks");
|
||||||
await import("./ContextMenu");
|
|
||||||
await import("./SingleInstanceHandler");
|
await import("./SingleInstanceHandler");
|
||||||
await import("./IconHelper");
|
await import("./IconHelper");
|
||||||
await import("./connection/FileTransfer");
|
await import("./connection/FileTransfer");
|
||||||
|
|
||||||
await import("./hooks");
|
|
||||||
|
|
||||||
await import("./UnloadHandler");
|
await import("./UnloadHandler");
|
||||||
await import("./WindowsTrayHandler");
|
await import("./WindowsTrayHandler");
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
@ -171,5 +148,6 @@ loader.register_task(loader.Stage.JAVASCRIPT_INITIALIZING, {
|
||||||
}
|
}
|
||||||
remote.getCurrentWindow().on('focus', () => remote.getCurrentWindow().flashFrame(false));
|
remote.getCurrentWindow().on('focus', () => remote.getCurrentWindow().flashFrame(false));
|
||||||
},
|
},
|
||||||
priority: 60
|
/* Register all tasks after all javascript files have been loaded */
|
||||||
|
priority: -1
|
||||||
});
|
});
|
|
@ -11,7 +11,8 @@
|
||||||
"tc-loader": ["imports/loader"],
|
"tc-loader": ["imports/loader"],
|
||||||
"svg-sprites/*": ["imports/svg-sprites/*"],
|
"svg-sprites/*": ["imports/svg-sprites/*"],
|
||||||
"tc-events": ["imports/vendor/TeaEventBus/src/index.d.ts"],
|
"tc-events": ["imports/vendor/TeaEventBus/src/index.d.ts"],
|
||||||
"tc-services": ["imports/vendor/TeaClientServices/src/index.d.ts"]
|
"tc-services": ["imports/vendor/TeaClientServices/src/index.d.ts"],
|
||||||
|
"tc-native/connection": ["native/serverconnection/exports/exports.d.ts"]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"include": [
|
"include": [
|
||||||
|
|
|
@ -13,7 +13,8 @@
|
||||||
"tc-loader": ["imports/loader"],
|
"tc-loader": ["imports/loader"],
|
||||||
"svg-sprites/*": ["imports/svg-sprites/*"],
|
"svg-sprites/*": ["imports/svg-sprites/*"],
|
||||||
"tc-events": ["imports/vendor/TeaEventBus/src/index.d.ts"],
|
"tc-events": ["imports/vendor/TeaEventBus/src/index.d.ts"],
|
||||||
"tc-services": ["imports/vendor/TeaClientServices/src/index.d.ts"]
|
"tc-services": ["imports/vendor/TeaClientServices/src/index.d.ts"],
|
||||||
|
"tc-native/connection": ["native/serverconnection/exports/exports.d.ts"]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"exclude": [
|
"exclude": [
|
||||||
|
|
Loading…
Reference in New Issue