From d41051edf935fd1e0d1aded1bc717fbe08687ece Mon Sep 17 00:00:00 2001 From: min Date: Mon, 8 Jun 2026 10:28:04 +0300 Subject: [PATCH] =?UTF-8?q?fix(lua):=20StudioCollab=20=D0=B3=D0=BB=D0=BE?= =?UTF-8?q?=D1=82=D0=B0=D0=BB=205-=D1=8B=D0=B9=20=D0=BF=D0=B0=D1=80=D0=B0?= =?UTF-8?q?=D0=BC=D0=B5=D1=82=D1=80=20language=20=D0=B2=20upsertScript?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Корень бага переключателя Lua: StudioCollab.js переопределял scene.upsertScript с 4-мя аргументами (id,code,target,name) и не передавал переданный 5-ый language в оригинал. Поэтому при смене языка в UI language пропадал и переключатель оставался на JS. Исправлено: - Обёртка scene.upsertScript = function (id, code, target, name, language) - Наследие collab-операции с language в sendOp и в _applyRemoteOp Диагностические console.log убраны. Co-Authored-By: Claude Opus 4.7 --- src/editor/ScriptEditor.jsx | 14 ++++++++++---- src/editor/engine/StudioCollab.js | 7 ++++--- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/src/editor/ScriptEditor.jsx b/src/editor/ScriptEditor.jsx index 57cb0de..ce52d5d 100644 --- a/src/editor/ScriptEditor.jsx +++ b/src/editor/ScriptEditor.jsx @@ -348,13 +348,19 @@ function ScriptEditor({ value, onSave, onRunSolo, isSoloRunning, scriptId, targe onLanguageChange(lang, nextCode); return; } - // Код не пустой — показываем кастомную модалку + // Код не пустой — показываем кастомную модалку. + // ВАЖНО: lang захвачен через map'a, но localCode и onLanguageChange + // надо взять из ref'ов на момент confirm, иначе stale closure. + const targetLang = lang; setConfirmState({ - title: `Сменить язык на ${lang === 'lua' ? 'Lua' : 'JavaScript'}?`, + title: `Сменить язык на ${targetLang === 'lua' ? 'Lua' : 'JavaScript'}?`, message: `Код останется как есть — синтаксис прежнего языка перестанет подсвечиваться, но текст не исчезнет. Можно переключиться обратно в любой момент.`, - confirmLabel: `Сменить на ${lang === 'lua' ? 'Lua' : 'JS'}`, + confirmLabel: `Сменить на ${targetLang === 'lua' ? 'Lua' : 'JS'}`, cancelLabel: 'Отмена', - onConfirm: () => onLanguageChange(lang, localCode), + onConfirm: () => { + // Берём актуальное значение из ref (не stale closure) + onLanguageChange(targetLang, localCodeRef.current); + }, }); }} style={{ diff --git a/src/editor/engine/StudioCollab.js b/src/editor/engine/StudioCollab.js index ccb4c74..f9f6166 100644 --- a/src/editor/engine/StudioCollab.js +++ b/src/editor/engine/StudioCollab.js @@ -170,8 +170,8 @@ export class StudioCollab { sc.__collabScriptsPatched = true; if (typeof sc.upsertScript === 'function') { const origUpsert = sc.upsertScript.bind(sc); - sc.upsertScript = function (id, code, target, name) { - const r = origUpsert(id, code, target, name); + sc.upsertScript = function (id, code, target, name, language) { + const r = origUpsert(id, code, target, name, language); if (!self._applyingRemote) { // id может быть сгенерён внутри upsertScript, если был null — // достаём фактический из _scripts (последний с этим code). @@ -188,6 +188,7 @@ export class StudioCollab { code: rec.code, target: rec.target ?? null, name: rec.name ?? null, + language: rec.language ?? 'js', }); } } @@ -433,7 +434,7 @@ export function applyRemoteOp(scene, op) { // Создание/редактирование скрипта у соавтора. _applyingRemote уже // выставлен (см. _applyRemoteOp) → обёртка upsertScript не зашлёт // эхо обратно. _onSceneChange внутри обновит React-панели. - scene.upsertScript?.(op.id, op.code, op.target ?? null, op.name ?? null); + scene.upsertScript?.(op.id, op.code, op.target ?? null, op.name ?? null, op.language ?? undefined); scene._onCollabScriptsChange?.(); return; case 'scriptRemove':