Skip to content

Commit 744bf8a

Browse files
committed
Fix Browse button (#3) and missing-canvasapi pipeline crash (#4)
#3: Browse button on Settings page → Output Directory had no effect. loadSettingsData() injects the Browse button into #conn-fields asynchronously, but attachPageHandlers tried to bind the click handler before the element existed. The optional chaining (?.) silently no-op'd. Fix: await loadSettingsData() before binding handlers on page 6. #4: Pipeline failed with "No module named 'canvasapi'" because env:check only verified tqdm/requests/openai imports, missing several core deps that downloader.py and other pipeline scripts need. Users could pass the first- start wizard with a partially-installed venv and hit the cryptic crash mid-pipeline. Fix: extend the env:check import probe to cover canvasapi, PIL, fitz, pptx; also re-run checkEnv from the renderer right before launching the pipeline so a regressed venv prompts the user to reinstall instead of failing silently. Verified: 26/26 jest tests pass; node --check on main.js and app.js clean.
1 parent 7ea3a7e commit 744bf8a

2 files changed

Lines changed: 24 additions & 5 deletions

File tree

electron/main.js

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -984,15 +984,19 @@ function registerIpc() {
984984
path: VENV_PYTHON,
985985
}));
986986

987-
// Environment readiness check for first-start wizard
987+
// Environment readiness check for first-start wizard.
988+
// Imports cover everything downloader.py and the other pipeline scripts
989+
// need at start-up. Missing any of these triggers the setup wizard so the
990+
// user installs the ML environment instead of hitting "No module named X"
991+
// mid-pipeline (e.g. issue #4: canvasapi missing).
988992
ipcMain.handle('env:check', () => {
989993
const hasPython = fs.existsSync(VENV_PYTHON);
990-
// Check if core packages are importable
991994
let coreOk = false;
992995
if (hasPython) {
993996
try {
994-
const r = spawnSync(VENV_PYTHON, ['-c', 'import tqdm, requests, openai; print("ok")'],
995-
{ timeout: 10000, windowsHide: true });
997+
const r = spawnSync(VENV_PYTHON,
998+
['-c', 'import tqdm, requests, openai, canvasapi, PIL, fitz, pptx; print("ok")'],
999+
{ timeout: 10000, windowsHide: true });
9961000
coreOk = (r.status === 0 && (r.stdout || '').toString().includes('ok'));
9971001
} catch {}
9981002
}

electron/renderer/app.js

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1460,6 +1460,18 @@ async function attachPageHandlers() {
14601460
document.getElementById('pp-run-btn')?.addEventListener('click', async () => {
14611461
const cid = document.getElementById('pp-course')?.value;
14621462
if (!cid) { snack('Select a course first.', false); return; }
1463+
1464+
// Verify the ML environment is ready before launching Python.
1465+
// Without this, missing imports (e.g. canvasapi — issue #4) surface
1466+
// as a cryptic mid-pipeline failure.
1467+
try {
1468+
const env = await window.api.checkEnv();
1469+
if (env && env.needsSetup) {
1470+
snack('ML environment not installed. Open Settings → Install ML Environment.', false);
1471+
return;
1472+
}
1473+
} catch {/* checkEnv unavailable in older builds — proceed */}
1474+
14631475
const python = await window.api.getPythonPath();
14641476
const outDir = State.outputDir || await window.api.getOutputDir();
14651477
const stealth = document.getElementById('pp-stealth')?.checked;
@@ -1749,7 +1761,10 @@ async function attachPageHandlers() {
17491761

17501762
// ── Settings ──────────────────────────────────────────────────────────────────
17511763
if (pg === 6) {
1752-
loadSettingsData();
1764+
// loadSettingsData injects the Browse button + other inputs into
1765+
// #conn-fields asynchronously. Await it before binding handlers, otherwise
1766+
// the elements don't exist yet and the bindings silently no-op.
1767+
await loadSettingsData();
17531768
fillEnvComponents();
17541769

17551770
document.getElementById('cfg-browse-btn')?.addEventListener('click', async () => {

0 commit comments

Comments
 (0)