From d229efecaa5b892364553c9b239f18cc78cdc5ee Mon Sep 17 00:00:00 2001 From: Jacob Dahl Date: Wed, 15 Jul 2026 12:34:03 -0600 Subject: [PATCH] fix(ark-ui): keep numeric TOML fields typed when saving from the editor TomlEditor chose the input widget from the live value's type. Vue's .number modifier passes non-numeric input through unchanged, so clearing a number field leaves "" behind, which flips the v-if chain to the text input and turns every later keystroke into a string. Saving then quotes the value (framerate = "30"), and the toml++ readers in the C++ services silently fall back to their defaults on a type mismatch. Render from the types captured when the config loaded, so a number field stays a number field. The convertTypes safety net meant to catch this never ran: getFullPath compared nodes of the JSON deep clone against this.config by identity, which never matches, so it always returned null. Thread the path through instead and drop getFullPath. Reject a blank number field rather than silently saving Number('') as 0. --- frontend/src/pages/components/TomlEditor.vue | 74 ++++++++------------ 1 file changed, 28 insertions(+), 46 deletions(-) diff --git a/frontend/src/pages/components/TomlEditor.vue b/frontend/src/pages/components/TomlEditor.vue index 80a4660..8444a0d 100644 --- a/frontend/src/pages/components/TomlEditor.vue +++ b/frontend/src/pages/components/TomlEditor.vue @@ -11,7 +11,7 @@ -
+
-
+
{ + const convertTypes = (obj, path = '') => { for (const key in obj) { + const fullPath = path ? `${path}.${key}` : key; const value = obj[key]; - if (value && typeof value === 'object' && !Array.isArray(value)) { - convertTypes(value); - } else if (typeof value === 'string') { - // Check if this was originally a number - const fullPath = this.getFullPath(obj, key); - if (fullPath && this.originalTypes[fullPath] === 'number') { - const numValue = Number(value); - if (!isNaN(numValue)) { - obj[key] = numValue; - } + if (this.isObject(value)) { + convertTypes(value, fullPath); + } else if (typeof value === 'string' && this.originalTypes[fullPath] === 'number') { + const numValue = this.toNumber(value); + if (!isNaN(numValue)) { + obj[key] = numValue; } } } @@ -343,33 +352,6 @@ export default { } }, - // Helper to get the full path of a nested property - getFullPath(obj, key) { - for (const path in this.originalTypes) { - const parts = path.split('.'); - const lastPart = parts[parts.length - 1]; - - if (lastPart === key) { - // Check if this is actually the right object - let currentObj = this.config; - let found = true; - - for (let i = 0; i < parts.length - 1; i++) { - if (currentObj[parts[i]] === undefined) { - found = false; - break; - } - currentObj = currentObj[parts[i]]; - } - - if (found && currentObj === obj) { - return path; - } - } - } - return null; - }, - cancelEdit() { this.$emit('close-editor'); },