/* Copyright 2022 Michael Telatynski <7t3chguy@gmail.com> Copyright 2018-2023 The Matrix.org Foundation C.I.C. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ import React, { ChangeEvent, useContext, useMemo, useState } from "react"; import { logger } from "matrix-js-sdk/src/logger"; import { _t } from "../../../../languageHandler"; import BaseTool, { DevtoolsContext, IDevtoolsProps } from "./BaseTool"; import AccessibleButton from "../../elements/AccessibleButton"; import SettingsStore, { LEVEL_ORDER } from "../../../../settings/SettingsStore"; import { SettingLevel } from "../../../../settings/SettingLevel"; import { SETTINGS } from "../../../../settings/Settings"; import Field from "../../elements/Field"; const SettingExplorer: React.FC = ({ onBack }) => { const [setting, setSetting] = useState(null); const [editing, setEditing] = useState(false); if (setting && editing) { const onBack = (): void => { setEditing(false); }; return ; } else if (setting) { const onBack = (): void => { setSetting(null); }; const onEdit = async (): Promise => { setEditing(true); }; return ; } else { const onView = (setting: string): void => { setSetting(setting); }; const onEdit = (setting: string): void => { setSetting(setting); setEditing(true); }; return ; } }; export default SettingExplorer; interface ICanEditLevelFieldProps { setting: string; level: SettingLevel; roomId?: string; } const CanEditLevelField: React.FC = ({ setting, roomId, level }) => { const canEdit = SettingsStore.canSetValue(setting, roomId ?? null, level); const className = canEdit ? "mx_DevTools_SettingsExplorer_mutable" : "mx_DevTools_SettingsExplorer_immutable"; return ( {canEdit.toString()} ); }; function renderExplicitSettingValues(setting: string, roomId?: string): string { const vals: Record = {}; for (const level of LEVEL_ORDER) { try { vals[level] = SettingsStore.getValueAt(level, setting, roomId, true, true); if (vals[level] === undefined) { vals[level] = null; } } catch (e) { logger.warn(e); } } return JSON.stringify(vals, null, 4); } interface IEditSettingProps extends Pick { setting: string; } const EditSetting: React.FC = ({ setting, onBack }) => { const context = useContext(DevtoolsContext); const [explicitValue, setExplicitValue] = useState(renderExplicitSettingValues(setting)); const [explicitRoomValue, setExplicitRoomValue] = useState( renderExplicitSettingValues(setting, context.room.roomId), ); const onSave = async (): Promise => { try { const parsedExplicit = JSON.parse(explicitValue); const parsedExplicitRoom = JSON.parse(explicitRoomValue); for (const level of Object.keys(parsedExplicit)) { logger.log(`[Devtools] Setting value of ${setting} at ${level} from user input`); try { const val = parsedExplicit[level]; await SettingsStore.setValue(setting, null, level as SettingLevel, val); } catch (e) { logger.warn(e); } } const roomId = context.room.roomId; for (const level of Object.keys(parsedExplicit)) { logger.log(`[Devtools] Setting value of ${setting} at ${level} in ${roomId} from user input`); try { const val = parsedExplicitRoom[level]; await SettingsStore.setValue(setting, roomId, level as SettingLevel, val); } catch (e) { logger.warn(e); } } onBack(); } catch (e) { return _t("devtools|failed_to_save") + (e instanceof Error ? ` (${e.message})` : ""); } }; return (

{_t("devtools|setting_colon")} {setting}

{_t("devtools|caution_colon")} {_t("devtools|use_at_own_risk")}
{_t("devtools|setting_definition")}
                    {JSON.stringify(SETTINGS[setting], null, 4)}
                
{LEVEL_ORDER.map((lvl) => ( ))}
{_t("devtools|level")} {_t("devtools|settable_global")} {_t("devtools|settable_room")}
{lvl}
setExplicitValue(e.target.value)} />
setExplicitRoomValue(e.target.value)} />
); }; interface IViewSettingProps extends Pick { setting: string; onEdit(): Promise; } const ViewSetting: React.FC = ({ setting, onEdit, onBack }) => { const context = useContext(DevtoolsContext); return (

{_t("devtools|setting_colon")} {setting}

{_t("devtools|setting_definition")}
                    {JSON.stringify(SETTINGS[setting], null, 4)}
                
{_t("devtools|value_colon")}  {renderSettingValue(SettingsStore.getValue(setting))}
{_t("devtools|value_this_room_colon")}  {renderSettingValue(SettingsStore.getValue(setting, context.room.roomId))}
{_t("devtools|values_explicit_colon")}
                    {renderExplicitSettingValues(setting)}
                
{_t("devtools|values_explicit_this_room_colon")}
                    {renderExplicitSettingValues(setting, context.room.roomId)}
                
); }; function renderSettingValue(val: any): string { // Note: we don't .toString() a string because we want JSON.stringify to inject quotes for us const toStringTypes = ["boolean", "number"]; if (toStringTypes.includes(typeof val)) { return val.toString(); } else { return JSON.stringify(val); } } interface ISettingsListProps extends Pick { onView(setting: string): void; onEdit(setting: string): void; } const SettingsList: React.FC = ({ onBack, onView, onEdit }) => { const context = useContext(DevtoolsContext); const [query, setQuery] = useState(""); const allSettings = useMemo(() => { let allSettings = Object.keys(SETTINGS); if (query) { const lcQuery = query.toLowerCase(); allSettings = allSettings.filter((setting) => setting.toLowerCase().includes(lcQuery)); } return allSettings; }, [query]); return ( ) => setQuery(ev.target.value)} className="mx_TextInputDialog_input mx_DevTools_RoomStateExplorer_query" /> {allSettings.map((i) => ( ))}
{_t("devtools|setting_id")} {_t("devtools|value")} {_t("devtools|value_in_this_room")}
onView(i)} > {i} onEdit(i)} className="mx_DevTools_SettingsExplorer_edit" > ✏ {renderSettingValue(SettingsStore.getValue(i))} {renderSettingValue(SettingsStore.getValue(i, context.room.roomId))}
); };