feat(rbxl): XML-������ ������ .rbxl + Day/Night + Tool/Mouse/Backpack flow #38

Closed
min wants to merge 39 commits from feat/rbxl-xml-parser-import into main
2 changed files with 14 additions and 7 deletions
Showing only changes of commit d41051edf9 - Show all commits

View File

@ -348,13 +348,19 @@ function ScriptEditor({ value, onSave, onRunSolo, isSoloRunning, scriptId, targe
onLanguageChange(lang, nextCode); onLanguageChange(lang, nextCode);
return; return;
} }
// Код не пустой показываем кастомную модалку // Код не пустой показываем кастомную модалку.
// ВАЖНО: lang захвачен через map'a, но localCode и onLanguageChange
// надо взять из ref'ов на момент confirm, иначе stale closure.
const targetLang = lang;
setConfirmState({ setConfirmState({
title: `Сменить язык на ${lang === 'lua' ? 'Lua' : 'JavaScript'}?`, title: `Сменить язык на ${targetLang === 'lua' ? 'Lua' : 'JavaScript'}?`,
message: `Код останется как есть — синтаксис прежнего языка перестанет подсвечиваться, но текст не исчезнет. Можно переключиться обратно в любой момент.`, message: `Код останется как есть — синтаксис прежнего языка перестанет подсвечиваться, но текст не исчезнет. Можно переключиться обратно в любой момент.`,
confirmLabel: `Сменить на ${lang === 'lua' ? 'Lua' : 'JS'}`, confirmLabel: `Сменить на ${targetLang === 'lua' ? 'Lua' : 'JS'}`,
cancelLabel: 'Отмена', cancelLabel: 'Отмена',
onConfirm: () => onLanguageChange(lang, localCode), onConfirm: () => {
// Берём актуальное значение из ref (не stale closure)
onLanguageChange(targetLang, localCodeRef.current);
},
}); });
}} }}
style={{ style={{

View File

@ -170,8 +170,8 @@ export class StudioCollab {
sc.__collabScriptsPatched = true; sc.__collabScriptsPatched = true;
if (typeof sc.upsertScript === 'function') { if (typeof sc.upsertScript === 'function') {
const origUpsert = sc.upsertScript.bind(sc); const origUpsert = sc.upsertScript.bind(sc);
sc.upsertScript = function (id, code, target, name) { sc.upsertScript = function (id, code, target, name, language) {
const r = origUpsert(id, code, target, name); const r = origUpsert(id, code, target, name, language);
if (!self._applyingRemote) { if (!self._applyingRemote) {
// id может быть сгенерён внутри upsertScript, если был null — // id может быть сгенерён внутри upsertScript, если был null —
// достаём фактический из _scripts (последний с этим code). // достаём фактический из _scripts (последний с этим code).
@ -188,6 +188,7 @@ export class StudioCollab {
code: rec.code, code: rec.code,
target: rec.target ?? null, target: rec.target ?? null,
name: rec.name ?? null, name: rec.name ?? null,
language: rec.language ?? 'js',
}); });
} }
} }
@ -433,7 +434,7 @@ export function applyRemoteOp(scene, op) {
// Создание/редактирование скрипта у соавтора. _applyingRemote уже // Создание/редактирование скрипта у соавтора. _applyingRemote уже
// выставлен (см. _applyRemoteOp) → обёртка upsertScript не зашлёт // выставлен (см. _applyRemoteOp) → обёртка upsertScript не зашлёт
// эхо обратно. _onSceneChange внутри обновит React-панели. // эхо обратно. _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?.(); scene._onCollabScriptsChange?.();
return; return;
case 'scriptRemove': case 'scriptRemove':