From be5aff576bb93cf9f631d40b055ba1f08fe24522 Mon Sep 17 00:00:00 2001 From: Kashargul <144968721+Kashargul@users.noreply.github.com> Date: Sat, 16 Aug 2025 01:10:47 +0200 Subject: [PATCH] tgui cleanup again (#18266) * tgui cleanup again * allow spellcheck and dependency up * spellcheck pref --- biome.json | 3 +- .../client/preferences/types/game/ui.dm | 6 ++++ code/modules/tgui_input/say_modal/modal.dm | 3 +- code/modules/tgui_input/text.dm | 1 + tgui/bun.lock | 8 ++--- tgui/packages/tgui-panel/chat/renderer.tsx | 4 +-- .../tgui-panel/chat/replaceInTextNode.ts | 32 ++++++++++--------- tgui/packages/tgui-panel/package.json | 2 +- tgui/packages/tgui-say/TguiSay.tsx | 6 ++-- tgui/packages/tgui-say/package.json | 2 +- .../ControllerOverview/OverviewSection.tsx | 5 ++- .../ControllerOverview/SubsystemDialog.tsx | 2 +- .../ControllerOverview/SubsystemRow.tsx | 6 ++-- .../ControllerOverview/SubsystemViews.tsx | 7 ++-- .../interfaces/ControllerOverview/filters.ts | 2 +- .../interfaces/ControllerOverview/index.tsx | 2 +- .../interfaces/ControllerOverview/types.ts | 2 +- .../features/game_preferences/ui.tsx | 7 ++++ .../tgui/interfaces/TextInputModal.tsx | 8 +++-- tgui/packages/tgui/package.json | 2 +- 20 files changed, 64 insertions(+), 46 deletions(-) diff --git a/biome.json b/biome.json index 9b05fad5eea..8f792f2b57b 100644 --- a/biome.json +++ b/biome.json @@ -56,8 +56,7 @@ "suspicious": { "noArrayIndexKey": "off", "noExplicitAny": "off", - "noImplicitAnyLet": "off", - "noAssignInExpressions": "warn" + "noImplicitAnyLet": "off" } } }, diff --git a/code/modules/client/preferences/types/game/ui.dm b/code/modules/client/preferences/types/game/ui.dm index 27c140b537e..c9712d9f124 100644 --- a/code/modules/client/preferences/types/game/ui.dm +++ b/code/modules/client/preferences/types/game/ui.dm @@ -66,6 +66,12 @@ /datum/preference/toggle/tgui_say_light/apply_to_client(client/client, value) client.tgui_say?.load() +/datum/preference/toggle/tgui_use_spellcheck + category = PREFERENCE_CATEGORY_GAME_PREFERENCES + savefile_key = "TGUI_ENABLE_SPELLCHECK" + default_value = TRUE + savefile_identifier = PREFERENCE_PLAYER + /datum/preference/toggle/tgui_say_emotes category = PREFERENCE_CATEGORY_GAME_PREFERENCES savefile_key = "tgui_say_emotes" diff --git a/code/modules/tgui_input/say_modal/modal.dm b/code/modules/tgui_input/say_modal/modal.dm index cd8d389e5f3..64eb4565f3e 100644 --- a/code/modules/tgui_input/say_modal/modal.dm +++ b/code/modules/tgui_input/say_modal/modal.dm @@ -72,10 +72,11 @@ window.send_message("props", list( "lightMode" = client?.prefs?.read_preference(/datum/preference/toggle/tgui_say_light), - "scale" = client.prefs?.read_preference(/datum/preference/toggle/ui_scale), + "scale" = client?.prefs?.read_preference(/datum/preference/toggle/ui_scale), "minimumWidth" = minimum_width, "minimumHeight" = minimum_height, "maxLength" = max_length, + "spellcheck" = client?.prefs?.read_preference(/datum/preference/toggle/tgui_use_spellcheck) )) stop_thinking() diff --git a/code/modules/tgui_input/text.dm b/code/modules/tgui_input/text.dm index a93f52cd1d0..7f01e931c06 100644 --- a/code/modules/tgui_input/text.dm +++ b/code/modules/tgui_input/text.dm @@ -126,6 +126,7 @@ data["placeholder"] = default // Default is a reserved keyword data["swapped_buttons"] = !user.read_preference(/datum/preference/toggle/tgui_swapped_buttons) data["title"] = title + data["spellcheck"] = user.read_preference(/datum/preference/toggle/tgui_use_spellcheck) return data /datum/tgui_input_text/tgui_data(mob/user) diff --git a/tgui/bun.lock b/tgui/bun.lock index 170b916ed2b..2689b1696dc 100644 --- a/tgui/bun.lock +++ b/tgui/bun.lock @@ -48,7 +48,7 @@ "marked-smartypants": "^1.1.9", "react": "^19.1.0", "react-dom": "^19.1.0", - "tgui-core": "^5.0.0", + "tgui-core": "^5.1.0", "tgui-dev-server": "workspace:*", }, }, @@ -71,7 +71,7 @@ "react": "^19.1.0", "react-dom": "^19.1.0", "tgui": "workspace:*", - "tgui-core": "^5.0.0", + "tgui-core": "^5.1.0", "tgui-dev-server": "workspace:*", }, }, @@ -83,7 +83,7 @@ "react": "^19.1.0", "react-dom": "^19.1.0", "tgui": "workspace:*", - "tgui-core": "^5.0.0", + "tgui-core": "^5.1.0", }, }, "packages/tgui-setup": { @@ -1108,7 +1108,7 @@ "tgui": ["tgui@workspace:packages/tgui"], - "tgui-core": ["tgui-core@5.0.0", "", { "dependencies": { "@floating-ui/react": "^0.27.13", "@nozbe/microfuzz": "^1.0.0" }, "peerDependencies": { "react": "^19.1.0", "react-dom": "^19.1.0" } }, "sha512-v03Sds9QjKSLv1WTK3NB1HwZ3Mp+P7FJ0MPdB2QTYnf2UgZG8cinf+SBqo78hOXuLj9iXRMSg5GO5LzaWHBTYQ=="], + "tgui-core": ["tgui-core@5.1.0", "", { "dependencies": { "@floating-ui/react": "^0.27.13", "@nozbe/microfuzz": "^1.0.0" }, "peerDependencies": { "react": "^19.1.0", "react-dom": "^19.1.0" } }, "sha512-I6uokZ4hC2UaufOZ9sub2t7ls5F8HtTl2HV/slA4ZqL5hzi2N+lrARoHtPMhi6ZoRZ0ZPJQscqTMdE+Iptcz1A=="], "tgui-dev-server": ["tgui-dev-server@workspace:packages/tgui-dev-server"], diff --git a/tgui/packages/tgui-panel/chat/renderer.tsx b/tgui/packages/tgui-panel/chat/renderer.tsx index 453fb150aab..f8ff15d749e 100644 --- a/tgui/packages/tgui-panel/chat/renderer.tsx +++ b/tgui/packages/tgui-panel/chat/renderer.tsx @@ -191,11 +191,11 @@ class ChatRenderer { ensureScrollTracking: () => void; highlightParsers: | { - highlightWords: string; + highlightWords: string[]; highlightRegex: RegExp; highlightColor: string; highlightWholeMessage: boolean; - highlightBlacklist: string; + highlightBlacklist: boolean; blacklistregex: RegExp; }[] | null; diff --git a/tgui/packages/tgui-panel/chat/replaceInTextNode.ts b/tgui/packages/tgui-panel/chat/replaceInTextNode.ts index a5aa7838b89..91355a761bb 100644 --- a/tgui/packages/tgui-panel/chat/replaceInTextNode.ts +++ b/tgui/packages/tgui-panel/chat/replaceInTextNode.ts @@ -12,33 +12,36 @@ const regexParseNode = (params: { regex: RegExp; createNode: (text: string) => Node; captureAdjust?: (str: string) => string; -}): { nodes?: HTMLElement; n?: number } => { +}): { nodes?: Node[]; n?: number } => { const { node, regex, createNode, captureAdjust } = params; - const text = node.textContent || ''; + const text = node.textContent; + + if (!text || !regex) { + return { nodes: [], n: 0 }; + } + const textLength = text.length; - let nodes; - let new_node; - let match = regex.exec(text); + const nodes: Node[] = []; + let fragment: Node | undefined; + let new_node: Node; + let match: RegExpExecArray | null; let lastIndex = 0; - let fragment; let n = 0; let count = 0; // eslint-disable-next-line no-cond-assign - while (match !== null) { + while (true) { + match = regex.exec(text); + if (!match) break; n += 1; // Safety check to prevent permanent // client crashing if (++count > 9999) { - return {}; + return { nodes: [], n: 0 }; } // Lazy init fragment if (!fragment) { fragment = document.createDocumentFragment(); } - // Lazy init nodes - if (!nodes) { - nodes = []; - } const matchText = captureAdjust ? captureAdjust(match[0]) : match[0]; const matchLength = matchText.length; // If matchText is set to be a substring nested within the original @@ -55,7 +58,6 @@ const regexParseNode = (params: { new_node = createNode(matchText); nodes.push(new_node); fragment.appendChild(new_node); - match = regex.exec(text); } if (fragment) { // Insert the remaining unmatched chunk @@ -83,7 +85,7 @@ const regexParseNode = (params: { export const replaceInTextNode = ( regex: RegExp, - words: string | null, + words: string[] | null, createNode: (text: string) => Node, ): ((node: Node) => number) => (node: Node) => { @@ -162,7 +164,7 @@ const createHighlightNode = (text: string): HTMLSpanElement => { export const highlightNode = ( node: Node, regex: RegExp, - words: string, + words: string[], createNode: (text: string) => Node = createHighlightNode, ) => { if (!createNode) { diff --git a/tgui/packages/tgui-panel/package.json b/tgui/packages/tgui-panel/package.json index 3f14b064d20..9727382c592 100644 --- a/tgui/packages/tgui-panel/package.json +++ b/tgui/packages/tgui-panel/package.json @@ -8,7 +8,7 @@ "react": "^19.1.0", "react-dom": "^19.1.0", "tgui": "workspace:*", - "tgui-core": "^5.0.0", + "tgui-core": "^5.1.0", "tgui-dev-server": "workspace:*" }, "private": true diff --git a/tgui/packages/tgui-say/TguiSay.tsx b/tgui/packages/tgui-say/TguiSay.tsx index 40b2e49b2e4..c743e65b391 100644 --- a/tgui/packages/tgui-say/TguiSay.tsx +++ b/tgui/packages/tgui-say/TguiSay.tsx @@ -28,6 +28,7 @@ type ByondProps = { minimumWidth: number; lightMode: BooleanLike; scale: BooleanLike; + spellcheck: BooleanLike; }; export function TguiSay() { @@ -38,6 +39,7 @@ export function TguiSay() { const scale = useRef(true); const minimumHeight = useRef(WindowSize.Small); const minimumWidth = useRef(WindowSize.Width); + const spellcheck = useRef(true); // I initially wanted to make these an object or a reducer, but it's not really worth it. // You lose the granulatity and add a lot of boilerplate. @@ -320,7 +322,7 @@ export function TguiSay() { ); minimumHeight.current = data.minimumHeight; minimumWidth.current = minWidth; - setLightMode(!!data.lightMode); + spellcheck.current = !!data.spellcheck; scale.current = !!data.scale; } @@ -388,7 +390,7 @@ export function TguiSay() { {buttonContent}