import {AbstractModal} from "tc-shared/ui/react-elements/modal/Definitions"; import React, {useContext, useState} from "react"; import {Translatable} from "tc-shared/ui/react-elements/i18n"; import {IpcRegistryDescription, Registry} from "tc-events"; import {ModalInputProcessorEvents, ModalInputProcessorVariables} from "tc-shared/ui/modal/input-processor/Definitios"; import {createIpcUiVariableConsumer, IpcVariableDescriptor} from "tc-shared/ui/utils/IpcVariable"; import {UiVariableConsumer} from "tc-shared/ui/utils/Variable"; import {InputProcessorStatistics} from "tc-shared/voice/RecorderBase"; import {joinClassList, useTr} from "tc-shared/ui/react-elements/Helper"; import {Checkbox} from "tc-shared/ui/react-elements/Checkbox"; import {ControlledBoxedInputField, ControlledSelect} from "tc-shared/ui/react-elements/InputField"; import {createErrorModal} from "tc-shared/ui/elements/Modal"; import {traj} from "tc-shared/i18n/localize"; const cssStyle = require("./Renderer.scss"); const EventContext = React.createContext>(undefined); const VariableContext = React.createContext>(undefined); const StatisticsContext = React.createContext(undefined); const TablePropertiesHead = React.memo(() => (
Property
Value
)); type PropertyType = { type: "integer" | "float" | "boolean" } | { type: "select", values: string[] }; const PropertyValueBooleanRenderer = React.memo((props: { property: keyof ModalInputProcessorVariables }) => { const variables = useContext(VariableContext); const value = variables.useVariable(props.property); if(value.status === "loading") { return null; } else { return ( value.setValue(newValue)} /> ); } }); const PropertyValueNumberRenderer = React.memo((props: { property: keyof ModalInputProcessorVariables }) => { const variables = useContext(VariableContext); const value = variables.useVariable(props.property); if(value.status === "loading") { return null; } else { return ( value.setValue(newValue as any, true)} onBlur={() => { const targetValue = parseFloat(value.localValue as any); if(isNaN(targetValue)) { value.setValue(value.remoteValue, true); } else { value.setValue(targetValue, false); } }} finishOnEnter={true} /> ); } }); const PropertyValueSelectRenderer = React.memo((props: { property: keyof ModalInputProcessorVariables, options: string[] }) => { const variables = useContext(VariableContext); const value = variables.useVariable(props.property); if(value.status === "loading") { return null; } else { const index = props.options.indexOf(value.localValue as any); return ( { const targetIndex = parseInt(event.target.value); if(isNaN(targetIndex)) { return; } value.setValue(props.options[targetIndex]); }} > {props.options.map((option, index) => ( )) as any} ); } }); const TablePropertyValue = React.memo((props: { property: keyof ModalInputProcessorVariables, type: PropertyType }) => { const variables = useContext(VariableContext); const filter = variables.useReadOnly("propertyFilter", undefined, undefined); if(typeof filter === "string" && filter.length > 0) { const key = props.property as string; if(key.toLowerCase().indexOf(filter) === -1) { return null; } } let value; switch (props.type.type) { case "integer": case "float": value = ; break; case "boolean": value = ; break; case "select": value = ; break; } return (
{props.property}
{value}
); }); const PropertyFilter = React.memo(() => { const variables = useContext(VariableContext); const filter = variables.useVariable("propertyFilter"); return (
filter.setValue(newValue)} value={filter.localValue} placeholder={useTr("Filter")} />
) }); const Properties = React.memo(() => { return (
Properties
Note: All changes are temporary and will be reset on the next restart.
) }) const StatisticValue = React.memo((props: { statisticKey: keyof InputProcessorStatistics }) => { const statistics = useContext(StatisticsContext); let value; switch(statistics ? typeof statistics[props.statisticKey] : "undefined") { case "number": value = statistics[props.statisticKey].toPrecision(4); break; case "boolean": value = statistics[props.statisticKey] ? ( true ) : ( false ); break; case "string": value = statistics[props.statisticKey]; break; default: value = (
unset
); break; } return value; }); const Statistic = React.memo((props: { statisticKey: keyof InputProcessorStatistics, children }) => (
{props.children}:
)); const StatisticsProvider = React.memo((props: { children }) => { const events = useContext(EventContext); const [ statistics, setStatistics ] = useState(() => { events.fire("query_statistics"); return undefined; }); events.reactUse("notify_statistics", event => setStatistics(event.statistics), undefined, []); return ( {props.children} ); }); const Statistics = React.memo(() => (
Statistics
Output RMS (dbfs) Voice detected Echo return loss Echo return loss enchancement Delay median (ms) Delay (ms) Delay standard deviation (ms) Divergent filter fraction Residual echo likelihood Residual echo likelihood (max) RNNoise volume
)); class Modal extends AbstractModal { private readonly events: Registry; private readonly variables: UiVariableConsumer; constructor(events: IpcRegistryDescription, variables: IpcVariableDescriptor) { super(); this.events = Registry.fromIpcDescription(events); this.variables = createIpcUiVariableConsumer(variables); this.events.on("notify_apply_error", event => { createErrorModal(tr("Failed to apply changes"), traj("Failed to apply changes:{:br:}{}", event.message)).open(); }) } protected onDestroy() { super.onDestroy(); this.events.destroy(); this.variables.destroy(); } renderBody(): React.ReactElement { return (
); } renderTitle(): string | React.ReactElement { return Input processor properties; } } export default Modal;