From 3fdf4b157359c8205e7543ee0a953f447a322bed Mon Sep 17 00:00:00 2001 From: Jake Date: Fri, 20 Feb 2026 15:49:47 +0800 Subject: [PATCH] save/load workspace now works --- src/main.js | 148 ++++++++++++++++++++++------------------------------ 1 file changed, 61 insertions(+), 87 deletions(-) diff --git a/src/main.js b/src/main.js index f15403b..7904909 100644 --- a/src/main.js +++ b/src/main.js @@ -131,82 +131,58 @@ function setConnectedUI(connected) { let workspaceCaptureState = null; onData((text) => { - // Check if we're capturing workspace XML - if (workspaceCaptureState) { - const { startMarker, endMarker } = workspaceCaptureState; - const startIdx = text.indexOf(startMarker); - const endIdx = text.indexOf(endMarker); - - // PRIORITY 1: If already capturing, check for end marker first - if (workspaceCaptureState.capturing) { - if (endIdx !== -1) { - // Found end marker - extract content - workspaceCaptureState.buffer += text.substring(0, endIdx); - const xmlContent = workspaceCaptureState.buffer.trim(); - - // Parse and load XML - try { - const xmlDom = Blockly.Xml.textToDom(xmlContent); - Blockly.Xml.domToWorkspace(xmlDom, workspace); - appendToTerminal('Workspace loaded successfully!\n'); - } catch (parseErr) { - appendToTerminal(`\nParse error: ${parseErr.message}\n`); - } - - workspaceCaptureState = null; - - // Don't display the end marker, but show text after it - const afterEnd = text.substring(endIdx + endMarker.length); - if (afterEnd.trim()) { - appendToTerminal(afterEnd); - } - return; - } else { - // Still capturing, accumulate buffer - workspaceCaptureState.buffer += text; - // Don't display captured content - return; - } - } - - // PRIORITY 2: Both markers in the same chunk (not yet capturing) - if (startIdx !== -1 && endIdx !== -1 && endIdx > startIdx) { - const xmlContent = text.substring(startIdx + startMarker.length, endIdx); - - // Parse and load XML - try { - const xmlDom = Blockly.Xml.textToDom(xmlContent.trim()); - Blockly.Xml.domToWorkspace(xmlDom, workspace); - appendToTerminal('Workspace loaded successfully!\n'); - } catch (parseErr) { - appendToTerminal(`\nParse error: ${parseErr.message}\n`); - } - - workspaceCaptureState = null; - - // Don't display the markers, but show text before/after - const beforeStart = text.substring(0, startIdx); - const afterEnd = text.substring(endIdx + endMarker.length); - if (beforeStart.trim() || afterEnd.trim()) { - appendToTerminal(beforeStart + afterEnd); - } - return; - } - - // PRIORITY 3: Start marker found, start capturing - if (startIdx !== -1) { - workspaceCaptureState.capturing = true; - workspaceCaptureState.buffer = text.substring(startIdx + startMarker.length); - // Don't display the start marker or content after it - const beforeStart = text.substring(0, startIdx); - if (beforeStart.trim()) { - appendToTerminal(beforeStart); - } - return; - } + if (!workspaceCaptureState) { + appendToTerminal(text); + return; } - - appendToTerminal(text); + + const { startMarker, endMarker } = workspaceCaptureState; + workspaceCaptureState.raw += text; + const raw = workspaceCaptureState.raw; + + const startIdx = raw.indexOf(startMarker); + + if (startIdx === -1) { + // No start marker yet — flush text that can't be part of the marker + const keep = startMarker.length - 1; + if (raw.length > keep) { + appendToTerminal(raw.substring(0, raw.length - keep)); + workspaceCaptureState.raw = raw.substring(raw.length - keep); + } + return; + } + + const contentStart = startIdx + startMarker.length; + const endIdx = raw.indexOf(endMarker, contentStart); + + if (endIdx === -1) { + // Have start but no end yet — show text before start marker once + if (!workspaceCaptureState.flushedPre && startIdx > 0) { + appendToTerminal(raw.substring(0, startIdx)); + workspaceCaptureState.flushedPre = true; + } + return; + } + + // Both markers found — extract content and load + const jsonContent = raw.substring(contentStart, endIdx).trim(); + const beforeStart = startIdx > 0 && !workspaceCaptureState.flushedPre + ? raw.substring(0, startIdx) : ''; + const afterEnd = raw.substring(endIdx + endMarker.length); + + workspaceCaptureState = null; + + if (beforeStart) appendToTerminal(beforeStart); + + try { + const state = JSON.parse(jsonContent); + Blockly.serialization.workspaces.load(state, workspace); + appendToTerminal('Workspace loaded successfully!\n'); + } catch (parseErr) { + appendToTerminal(`\nParse error: ${parseErr.message}\n`); + } + + if (afterEnd.trim()) appendToTerminal(afterEnd); }); // ─── Toolbar Buttons ───────────────────────────────────── @@ -331,13 +307,12 @@ btnSave.addEventListener('click', async () => { async function saveWorkspaceToDevice() { try { - // Convert workspace to XML - const xml = Blockly.Xml.workspaceToDom(workspace); - const xmlText = Blockly.Xml.domToText(xml); - + const state = Blockly.serialization.workspaces.save(workspace); + const json = JSON.stringify(state); + appendToTerminal('\nSaving workspace to device...\n'); - await writeFileToDevice(xmlText, 'workspace.xml'); - appendToTerminal('Workspace saved to workspace.xml\n'); + await writeFileToDevice(json, 'workspace.json'); + appendToTerminal('Workspace saved to workspace.json\n'); } catch (err) { appendToTerminal(`\nSave workspace error: ${err.message}\n`); } @@ -352,24 +327,23 @@ async function loadWorkspaceFromDevice() { const startMarker = `__WS_START_${timestamp}__`; const endMarker = `__WS_END_${timestamp}__`; - // Set up capture state workspaceCaptureState = { startMarker, endMarker, - buffer: '', - capturing: false, + raw: '', + flushedPre: false, }; const script = [ `try:`, - ` f = open('workspace.xml', 'r')`, + ` f = open('workspace.json', 'r')`, ` data = f.read()`, ` f.close()`, ` print('${startMarker}')`, ` print(data, end='')`, ` print('${endMarker}')`, `except Exception as e:`, - ` print('Error reading workspace.xml: ' + str(e))`, + ` print('Error reading workspace.json: ' + str(e))`, ].join('\n'); await executeCode(script); @@ -380,7 +354,7 @@ async function loadWorkspaceFromDevice() { appendToTerminal('\nTimeout waiting for workspace data\n'); workspaceCaptureState = null; } - }, 5000); + }, 10000); } catch (err) { appendToTerminal(`\nLoad workspace error: ${err.message}\n`);