import {InternalModal} from "tc-shared/ui/react-elements/internal-modal/Controller"; import * as React from "react"; import {Translatable, VariadicTranslatable} from "tc-shared/ui/react-elements/i18n"; import {Registry} from "tc-shared/events"; import { ChannelEditablePermissions, ChannelEditablePermissionValue, ChannelEditableProperty, ChannelEditEvents, ChannelEditPermissionsState, ChannelPropertyPermission } from "tc-shared/ui/modal/channel-edit/Definitions"; import {useContext, useEffect, useRef, useState} from "react"; import {BoxedInputField, Select} from "tc-shared/ui/react-elements/InputField"; import {Switch} from "tc-shared/ui/react-elements/Switch"; import {Button} from "tc-shared/ui/react-elements/Button"; import {Tab, TabEntry} from "tc-shared/ui/react-elements/Tab"; import {Settings, settings} from "tc-shared/settings"; import {useTr} from "tc-shared/ui/react-elements/Helper"; import {IconTooltip} from "tc-shared/ui/react-elements/Tooltip"; import {RadioButton} from "tc-shared/ui/react-elements/RadioButton"; import {Slider} from "tc-shared/ui/react-elements/Slider"; import {LoadingDots} from "tc-shared/ui/react-elements/LoadingDots"; import {RemoteIconRenderer} from "tc-shared/ui/react-elements/Icon"; import {getIconManager} from "tc-shared/file/Icons"; const cssStyle = require("./Renderer.scss"); const ModalTypeContext = React.createContext<"channel-edit" | "channel-create">("channel-edit"); const EventContext = React.createContext>(undefined); type ChannelPropertyState = { setPropertyValue: (value: ChannelEditableProperty[T], dontUpdateController?: boolean) => void } & ({ propertyState: "loading", propertyValue: undefined, } | { propertyState: "normal" | "applying", propertyValue: ChannelEditableProperty[T], }) const kPropertyLoading = "____loading_____"; function useProperty(property: T) : ChannelPropertyState { const events = useContext(EventContext); const [ value, setValue ] = useState(() => { events.fire("query_property", { property: property }); return kPropertyLoading; }); events.reactUse("notify_property", event => { if(event.property !== property) { return; } setValue(event.value as any); }, undefined, []); if(value === kPropertyLoading) { return { propertyState: "loading", propertyValue: undefined, setPropertyValue: _value => {} }; } else { return { propertyState: "normal", propertyValue: value, setPropertyValue: (value, dontUpdateController?: boolean) => { setValue(value); if(!dontUpdateController) { events.fire("action_change_property", { property: property, value: value }); } } }; } } function usePropertyPermission(permission: T, defaultValue: ChannelPropertyPermission[T]) : ChannelPropertyPermission[T] { const events = useContext(EventContext); const [ value, setValue ] = useState(() => { events.fire("query_property_permission", { permission: permission }); return defaultValue; }); events.reactUse("notify_property_permission", event => event.permission === permission && setValue(event.value as any)); return value; } function usePermission(permission: ChannelEditablePermissions) : { permissionValue: ChannelEditablePermissionValue, setPermissionValue: (newValue: number, dontUpdateController?: boolean) => void } { const events = useContext(EventContext); const [ value, setValue ] = useState(() => { events.fire("query_permission", { permission: permission }); return { state: "loading" }; }); events.reactUse("notify_permission", event => event.permission === permission && setValue(event.value)); return { permissionValue: value, setPermissionValue: (newValue, dontUpdateController) => { setValue({ value: newValue, state: "editable" }); if(!dontUpdateController) { events.fire("action_change_permission", { permission: permission, value: newValue }); } } }; } function useValidationState(property: T) : boolean { const events = useContext(EventContext); const [ valid, setValid ] = useState(() => { events.fire("query_property_valid_state", { property: property }); return true; }); events.reactUse("notify_property_validate_state", event => event.property === property && setValid(event.valid)); return valid; } const ChannelName = React.memo(() => { const modalType = useContext(ModalTypeContext); const { propertyValue, propertyState, setPropertyValue } = useProperty("name"); const editable = usePropertyPermission("name", modalType === "channel-create"); const valid = useValidationState("name"); return ( setPropertyValue(value, true)} onChange={value => setPropertyValue(value)} isInvalid={!valid} /> ); }); const ChannelIcon = () => { const events = useContext(EventContext); const { propertyValue, propertyState, setPropertyValue } = useProperty("icon"); const permissionGranted = usePropertyPermission("icon", false); const icon = getIconManager().resolveIcon(propertyValue ? propertyValue.iconId : 0, propertyValue?.remoteIcon.serverUniqueId, propertyValue?.remoteIcon.handlerId); const enabled = permissionGranted && propertyState === "normal"; return (
enabled && events.fire("action_icon_select")}>
enabled && events.fire("action_icon_select")}>Edit icon
{ if(!enabled) { return; } setPropertyValue({ iconId: 0, remoteIcon: { iconId: 0, handlerId: propertyValue.remoteIcon.handlerId, serverUniqueId: propertyValue.remoteIcon.serverUniqueId } }); }}>Remove icon
) } const ChannelPassword = React.memo(() => { const { propertyValue, propertyState, setPropertyValue } = useProperty("password"); const { editable } = usePropertyPermission("password", { enforced: false, editable: false }); const valid = useValidationState("password"); return ( { if(value.length > 0) { setPropertyValue({ state: "set", password: value }, true); } else { setPropertyValue({ state: "clear" }, true); } }} onChange={value => { if(value.length > 0) { setPropertyValue({ state: "set", password: value }); } else { setPropertyValue({ state: "clear" }); } }} isInvalid={!valid} type={"password"} /> ); }); const ChannelTopic = React.memo(() => { const { propertyValue, propertyState, setPropertyValue } = useProperty("topic"); const editable = usePropertyPermission("topic", false); return ( setPropertyValue(value, true)} onChange={value => setPropertyValue(value)} /> ); }); const BBCodeEditor = React.memo((props: { text: string, placeholder: string, disabled: boolean, callbackEdit: (value: string) => void }) => { const refText = useRef(); const insertTag = (open: string, close: string) => { const element = refText.current; if(!element) { return; } if (element.selectionStart || element.selectionStart == 0) { const startPos = element.selectionStart; const endPos = element.selectionEnd; element.value = element.value.substring(0, startPos) + open + element.value.substring(startPos, endPos) + close + element.value.substring(endPos); element.selectionEnd = endPos + open.length; element.selectionStart = element.selectionEnd; } else { element.value += open + close; element.selectionEnd = element.value.length - close.length; element.selectionStart = element.selectionEnd; } element.focus(); }; return (
insertTag("[b]", "[/b]")}>B
insertTag("[i]", "[/i]")}>I
insertTag("[u]", "[/u]")}>U