From e8acbd87bb243c9bb58932eca6a970924af2ceb5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Vogel?= Date: Mon, 26 Oct 2026 00:50:19 +0100 Subject: [PATCH] Cleanup: the files drawer closes on a click outside; unused strings go MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A click anywhere but the drawer and 📁 closes the drawer, as the ⋮ menu does. The 19 shell strings no component uses anymore (old sidebar, footer, teacher note, sign-in labels, output messages) are dropped. CLAUDE.md: the editor's old shell CSS is gone (glpython-edu/glpython-editor#32). Co-Authored-By: Claude Opus 5.5 --- CLAUDE.md | 2 +- src/App.tsx | 10 ++++++++-- src/i18n.ts | 57 ----------------------------------------------------- 3 files changed, 9 insertions(+), 60 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 23d100e..a32c400 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -21,7 +21,7 @@ There are no tests. `.github/workflows/ci.yml` runs `npm ci`, the build (tsc cat ## Layout - `src/App.tsx` — the shell. It renders `GlPythonWorkspace` (stacked layout; its buttons go into the bar through `actionsContainer`, every file is a tab with `closeFileTabs: false`) and uses glpython-editor's project helpers (`addProjectFile`, `renameProjectFile`, …). -- `src/index.css` — the shell's styles (`ide-*` classes), from glpython-editor's `--glp-*` tokens. glpython-editor's `style.css` still has the old shell's rules (`.app-shell`, `.topbar`, `.sidebar`, …), now unused. +- `src/index.css` — the shell's styles (`ide-*` classes), from glpython-editor's `--glp-*` tokens. glpython-editor's `style.css` styles only the workspace (plus `icon-button`, `hidden-input` and `auth-notice`, which the shell uses too). - `src/i18n.ts` — only the shell's own strings (`ShellStrings`, de/en). The workspace's strings come from glpython-editor's `coreStrings`, so don't copy them here. A new workspace string goes into glpython-editor's `src/i18n.ts`. - `src/projectStorage.ts` (local storage, folder/ZIP) and `src/projectShare.ts` (`?project=` share links, lz-string, versioned payload). - `src/auth.ts` — MSAL. Only active with `VITE_ENTRA_CLIENT_ID` in `.env.local` (README «Microsoft sign-in»). diff --git a/src/App.tsx b/src/App.tsx index 792df5d..30cd706 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -73,9 +73,15 @@ function App() { }, []) // The drawer and the menu take keyboard focus when they open; a click - // elsewhere closes the menu. + // elsewhere closes them (the drawer: anywhere but itself and 📁). useEffect(() => { - if (isDrawerOpen) drawerRef.current?.querySelector('button')?.focus() + if (!isDrawerOpen) return + drawerRef.current?.querySelector('button')?.focus() + const closeOnOutsideClick = (event: PointerEvent) => { + if (!drawerRef.current?.contains(event.target as Node) && !filesButtonRef.current?.contains(event.target as Node)) setIsDrawerOpen(false) + } + document.addEventListener('pointerdown', closeOnOutsideClick) + return () => document.removeEventListener('pointerdown', closeOnOutsideClick) }, [isDrawerOpen]) useEffect(() => { if (!isMenuOpen) return diff --git a/src/i18n.ts b/src/i18n.ts index 29a1622..d6b2a21 100644 --- a/src/i18n.ts +++ b/src/i18n.ts @@ -10,11 +10,9 @@ export const localeNames: Record = { // The IDE's own shell strings; everything the workspace shows comes from // glpython-editor's coreStrings (see translations below). type ShellStrings = { - workspaceName: string openProject: string openFolder: string downloadProject: string - shareLinkCopiedOutput: string shareLinkPromptLabel: string share: string shareCopied: string @@ -25,32 +23,15 @@ type ShellStrings = { ideTools: string restartPython: string projectMenu: string - microsoftConnected: string - signInWithMicrosoft: string - settings: string - notSignedIn: string - courseMenu: string renameProject: string promptRenameProject: string - lessonProgress: string addFile: string renameFile: (path: string) => string deleteFile: (path: string) => string - teacherNoteTitle: string - teacherNoteBody: string pythonReference: string - unsaved: string - save: string - autosaveOff: string devTools: string clearLocalProject: string language: string - savedOutput: (path: string) => string - downloadedOutput: (name: string) => string - openedFolderOutput: (name: string) => string - folderNotOpened: string - openedZipOutput: (name: string) => string - zipNotOpened: string authInitError: string authConfigError: string authCancelledError: string @@ -66,11 +47,9 @@ export type Translation = CoreStrings & ShellStrings export const translations: Record = { en: { ...coreStrings.en, - workspaceName: 'Classroom workspace', openProject: 'Open project', openFolder: 'Open folder', downloadProject: 'Download project', - shareLinkCopiedOutput: 'Share link copied to the clipboard. Anyone who opens it gets a copy of this project.', shareLinkPromptLabel: 'Copy this share link:', share: 'Share', shareCopied: 'Link copied ✓', @@ -81,32 +60,15 @@ export const translations: Record = { ideTools: 'Tools', restartPython: 'Restart Python', projectMenu: 'Project', - microsoftConnected: 'Microsoft connected', - signInWithMicrosoft: 'Sign in with Microsoft', - settings: 'Settings', - notSignedIn: 'Not signed in', - courseMenu: 'Course menu', renameProject: 'Rename project', promptRenameProject: 'Project name', - lessonProgress: 'Lesson 01 of 08', addFile: 'Add file', renameFile: (path) => `Rename ${path}`, deleteFile: (path) => `Delete ${path}`, - teacherNoteTitle: "Teacher's note", - teacherNoteBody: 'Start by changing the name.', pythonReference: 'Python reference', - unsaved: 'Unsaved', - save: 'Save', - autosaveOff: 'Autosave is off', devTools: 'Development tools', clearLocalProject: 'Clear local project', language: 'Language', - savedOutput: (path) => `Saved ${path} to your workspace. OneDrive sync is ready to connect.`, - downloadedOutput: (name) => `Downloaded ${name} as a ZIP project folder.`, - openedFolderOutput: (name) => `Opened ${name} from a local folder.`, - folderNotOpened: 'The folder was not opened.', - openedZipOutput: (name) => `Opened ${name} from a ZIP project folder.`, - zipNotOpened: 'That ZIP file could not be opened as a project.', authInitError: 'Microsoft sign-in could not be initialized.', authConfigError: 'Add VITE_ENTRA_CLIENT_ID to .env.local to enable Microsoft sign-in.', authCancelledError: 'Microsoft sign-in was cancelled or failed.', @@ -118,11 +80,9 @@ export const translations: Record = { }, de: { ...coreStrings.de, - workspaceName: 'Klassenarbeitsbereich', openProject: 'Projekt öffnen', openFolder: 'Ordner öffnen', downloadProject: 'Projekt herunterladen', - shareLinkCopiedOutput: 'Freigabelink in die Zwischenablage kopiert. Wer ihn öffnet, erhält eine Kopie dieses Projekts.', shareLinkPromptLabel: 'Diesen Freigabelink kopieren:', share: 'Teilen', shareCopied: 'Link kopiert ✓', @@ -133,32 +93,15 @@ export const translations: Record = { ideTools: 'Werkzeuge', restartPython: 'Python neu starten', projectMenu: 'Projekt', - microsoftConnected: 'Mit Microsoft verbunden', - signInWithMicrosoft: 'Mit Microsoft anmelden', - settings: 'Einstellungen', - notSignedIn: 'Nicht angemeldet', - courseMenu: 'Kursmenü', renameProject: 'Projekt umbenennen', promptRenameProject: 'Projektname', - lessonProgress: 'Lektion 01 von 08', addFile: 'Datei hinzufügen', renameFile: (path) => `${path} umbenennen`, deleteFile: (path) => `${path} löschen`, - teacherNoteTitle: 'Hinweis der Lehrkraft', - teacherNoteBody: 'Zuerst den Namen ändern.', pythonReference: 'Python-Referenz', - unsaved: 'Nicht gespeichert', - save: 'Speichern', - autosaveOff: 'Automatisches Speichern ist deaktiviert', devTools: 'Entwicklerwerkzeuge', clearLocalProject: 'Lokales Projekt löschen', language: 'Sprache', - savedOutput: (path) => `${path} im Arbeitsbereich gespeichert. OneDrive-Synchronisierung ist bereit zur Verbindung.`, - downloadedOutput: (name) => `${name} als ZIP-Projektordner heruntergeladen.`, - openedFolderOutput: (name) => `${name} aus einem lokalen Ordner geöffnet.`, - folderNotOpened: 'Der Ordner wurde nicht geöffnet.', - openedZipOutput: (name) => `${name} aus einem ZIP-Projektordner geöffnet.`, - zipNotOpened: 'Diese ZIP-Datei konnte nicht als Projekt geöffnet werden.', authInitError: 'Die Microsoft-Anmeldung konnte nicht initialisiert werden.', authConfigError: 'Für die Microsoft-Anmeldung VITE_ENTRA_CLIENT_ID in .env.local eintragen.', authCancelledError: 'Die Microsoft-Anmeldung wurde abgebrochen oder ist fehlgeschlagen.',