From 292910e41fc27690fcf0d2fdb71469a971b47f3b Mon Sep 17 00:00:00 2001 From: Moros Smith Date: Tue, 4 Jun 2024 17:06:07 -0400 Subject: [PATCH 01/31] remove unused editor panel functions, add compiler info on success handler --- resources/js/app.js | 4 +--- resources/js/components/EditorPanel.js | 18 ------------------ 2 files changed, 1 insertion(+), 21 deletions(-) diff --git a/resources/js/app.js b/resources/js/app.js index 517b280..909b591 100644 --- a/resources/js/app.js +++ b/resources/js/app.js @@ -253,7 +253,6 @@ class PGEtinker this.infoPanel.clear(); this.consolePanel.clear(); - this.editorPanel.clearMarkers(); this.playerPanel.setCompiling(); this.compiling = true; @@ -307,6 +306,7 @@ class PGEtinker compileSuccessHandler(data) { + this.infoPanel.setContent(data.stderr); this.playerPanel.setHtml(data.html); this.compiling = false; } @@ -316,8 +316,6 @@ class PGEtinker this.setActiveTab("C++ Editor"); this.infoPanel.setContent(stderr); - this.editorPanel.extractAndSetMarkers(stderr); - this.playerPanel.setCompilingFailed(); this.compiling = false; } diff --git a/resources/js/components/EditorPanel.js b/resources/js/components/EditorPanel.js index abb2773..45df9ae 100644 --- a/resources/js/components/EditorPanel.js +++ b/resources/js/components/EditorPanel.js @@ -136,24 +136,6 @@ export default class EditorPanel this.monacoWrapper.getEditor().revealPositionInCenter(position); } - extractAndSetMarkers(input) - { - } - - clearMarkers() - { - } - - setMarkers(markers) - { - // // set model markers - // monaco.editor.setModelMarkers(this.monacoModel, "owner", markers); - // // move to first marker - // this.monacoEditor.setPosition({lineNumber: markers[0].startLineNumber, column: markers[0].startColumn }); - // // trigger activate nearest marker - // setTimeout(() => { this.monacoEditor.trigger("", "editor.action.marker.next"); }, 50); - } - async setTheme(theme) { if(this.monacoWrapper == null) From 0beeba84cfb1d386d36ff4cb78b981d50f383ab3 Mon Sep 17 00:00:00 2001 From: Moros Smith Date: Tue, 4 Jun 2024 17:09:11 -0400 Subject: [PATCH 02/31] remove unused monaco --- resources/js/app.js | 1 - 1 file changed, 1 deletion(-) diff --git a/resources/js/app.js b/resources/js/app.js index 909b591..2f921c7 100644 --- a/resources/js/app.js +++ b/resources/js/app.js @@ -1,6 +1,5 @@ import './lib/bootstrap'; import './lib/goldenLayout'; -// import './lib/monaco'; import './lib/lucide'; import version from "./lib/version"; import agreeDialog from './lib/agreeDialog'; From a3f1fa7f5d1b3af0f84933280f1658aec232432a Mon Sep 17 00:00:00 2001 From: Moros Smith Date: Wed, 5 Jun 2024 01:05:57 -0400 Subject: [PATCH 03/31] add restart after disconnect --- resources/js/lib/monacoConfig.js | 2 +- resources/js/lib/monacoWrapper.js | 31 ++++++++++++++++++++++++++++++- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/resources/js/lib/monacoConfig.js b/resources/js/lib/monacoConfig.js index a15ffe3..ce8cb9c 100644 --- a/resources/js/lib/monacoConfig.js +++ b/resources/js/lib/monacoConfig.js @@ -30,7 +30,7 @@ export const createUserConfig = (workspaceRoot, code, codeUri) => return { languageClientConfig: { languageId: 'cpp', - name: 'Clangd Language Server Example', + name: 'Clangd Language Server', options: { $type: 'WebSocket', host: window.location.host, diff --git a/resources/js/lib/monacoWrapper.js b/resources/js/lib/monacoWrapper.js index 8b7f5b5..989030f 100644 --- a/resources/js/lib/monacoWrapper.js +++ b/resources/js/lib/monacoWrapper.js @@ -48,11 +48,40 @@ export const runCppWrapper = async (htmlElement) => { // reset editor font zoom window.addEventListener("keydown", (event) => { if (event.ctrlKey && event.key == "0") { - // event.preventDefault(); vscode.commands.executeCommand("editor.action.fontZoomReset"); } }); + + window.addEventListener("pgetinker-start-language-server", async() => + { + if(!wrapper.getLanguageClientWrapper().isStarted()) + await wrapper.getLanguageClientWrapper().start(); + }); + window.addEventListener("pgetinker-stop-language-server", async() => + { + if(wrapper.getLanguageClientWrapper().isStarted()) + await wrapper.getLanguageClientWrapper().disposeLanguageClient(); + }); + + window.addEventListener("pgetinker-restart-language-server", async(event) => + { + if(wrapper.getLanguageClientWrapper().isStarted() || event.detail.force) + await wrapper.getLanguageClientWrapper().restartLanguageClient(); + }); + + let keepAliveInterval; + + keepAliveInterval = setInterval(() => + { + // has the language client shutdown/disconnected? + if(!wrapper.getLanguageClientWrapper().isStarted()) + { + // force restart the language server, hopefully it'll reconnect + window.dispatchEvent(new CustomEvent("pgetinker-restart-language-server", { detail: { force: true } })); + } + }, 10000); + // @ts-ignore window.addEventListener("unload", async(event) => { await wrapper.dispose(); From ea5fd0bbfc3c2cc37f48b6137daf3f483ac14025 Mon Sep 17 00:00:00 2001 From: Moros Smith Date: Wed, 5 Jun 2024 16:10:23 -0400 Subject: [PATCH 04/31] remove preformatted style --- resources/css/info-panel.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/css/info-panel.scss b/resources/css/info-panel.scss index 139631d..3c273c7 100644 --- a/resources/css/info-panel.scss +++ b/resources/css/info-panel.scss @@ -9,6 +9,6 @@ } #info-panel div { - white-space: pre; font-family: "Droid Sans Mono", "monospace", monospace; } + From de596a5716a1ad549a913cd70c772481536c5890 Mon Sep 17 00:00:00 2001 From: Moros Smith Date: Wed, 5 Jun 2024 16:10:45 -0400 Subject: [PATCH 05/31] add focus to editor --- resources/js/components/EditorPanel.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/resources/js/components/EditorPanel.js b/resources/js/components/EditorPanel.js index 45df9ae..99356ac 100644 --- a/resources/js/components/EditorPanel.js +++ b/resources/js/components/EditorPanel.js @@ -130,6 +130,11 @@ export default class EditorPanel { return (this.monacoWrapper.getEditor().getValue().length > this.maxFileSize); } + + focus() + { + this.monacoWrapper.getEditor().focus(); + } reveal(position) { From 598c6e8094ca47f91bf4f1c9455abcc6dcb23f8f Mon Sep 17 00:00:00 2001 From: Moros Smith Date: Wed, 5 Jun 2024 16:11:18 -0400 Subject: [PATCH 06/31] set the cursor position and set editor focused in the reveal function --- resources/js/components/EditorPanel.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/resources/js/components/EditorPanel.js b/resources/js/components/EditorPanel.js index 99356ac..706a75b 100644 --- a/resources/js/components/EditorPanel.js +++ b/resources/js/components/EditorPanel.js @@ -138,6 +138,8 @@ export default class EditorPanel reveal(position) { + this.monacoWrapper.getEditor().setPosition(position); + this.focus(); this.monacoWrapper.getEditor().revealPositionInCenter(position); } From 1d93b335c14dd9ff68b19c53ca6273446e615303 Mon Sep 17 00:00:00 2001 From: Moros Smith Date: Wed, 5 Jun 2024 16:12:54 -0400 Subject: [PATCH 07/31] handleDiagnostics middleware --- resources/js/lib/monacoConfig.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/resources/js/lib/monacoConfig.js b/resources/js/lib/monacoConfig.js index ce8cb9c..1db5906 100644 --- a/resources/js/lib/monacoConfig.js +++ b/resources/js/lib/monacoConfig.js @@ -52,6 +52,18 @@ export const createUserConfig = (workspaceRoot, code, codeUri) => name: 'workspace', uri: vscode.Uri.parse(workspaceRoot) }, + middleware: { + handleDiagnostics: (uri, diagnostics, next) => + { + // we only care about the main source file, let the rest of the middleware handle this one + if(uri.path != "/workspace/pgetinker.cpp") + return next(uri, diagnostics); + + window.dispatchEvent(new CustomEvent("update-problems-panel", { detail: diagnostics })); + return next(uri, diagnostics); + }, + }, + connectionOptions: { maxRestartCount: 5, } From 8fe914020b11061b3fbcd2dd440fc48b35502620 Mon Sep 17 00:00:00 2001 From: Moros Smith Date: Wed, 5 Jun 2024 16:13:12 -0400 Subject: [PATCH 08/31] wip problems in the #info-panel --- resources/js/components/InfoPanel.js | 52 ++++++++++++++++++++++++++-- 1 file changed, 49 insertions(+), 3 deletions(-) diff --git a/resources/js/components/InfoPanel.js b/resources/js/components/InfoPanel.js index d3db998..fb3b64a 100644 --- a/resources/js/components/InfoPanel.js +++ b/resources/js/components/InfoPanel.js @@ -7,6 +7,39 @@ export default class InfoPanel { this.state = state; console.log("Info panel", "constructor"); + + window.addEventListener("update-problems-panel", (event) => + { + const diagnostics = event.detail; + + document.querySelector("#info-panel").innerHTML = ""; + const wrapper = document.createElement("div"); + + diagnostics.forEach((diagnostic) => + { + const container = document.createElement("p"); + const link = document.createElement("a"); + + link.setAttribute("href", "#"); + link.setAttribute("data-line-number", diagnostic.range.start._line); + link.setAttribute("data-column", diagnostic.range.start._character); + link.setAttribute("title", diagnostic.message); + link.innerHTML = diagnostic.message; + + link.addEventListener("click", (event) => + { + const currentLink = event.target; + const lineNumber = parseInt(currentLink.getAttribute("data-line-number")) + 1; + const column = parseInt(currentLink.getAttribute("data-column")) + 1; + this.state.editorPanel.reveal({ lineNumber, column }); + }); + + container.append(link); + wrapper.append(container); + }); + + document.querySelector("#info-panel").append(wrapper); + }); } @@ -43,9 +76,22 @@ export default class InfoPanel setContent(content) { - let infoPanel = document.querySelector("#info-panel"); - infoPanel.innerHTML = `
${content}
`; - infoPanel.scrollTop = infoPanel.scrollHeight; + const infoPanel = document.querySelector("#info-panel"); + + while(infoPanel.lastElementChild) + { + infoPanel.removeChild(infoPanel.lastElementChild); + } + + if(typeof content === "string") + { + infoPanel.innerHTML = `
${content}
`; + } + else + { + infoPanel.append(content); + } + } } From d82cda9b8831d57ba77d743b875e52db290bf994 Mon Sep 17 00:00:00 2001 From: Moros Smith Date: Wed, 5 Jun 2024 22:37:02 -0400 Subject: [PATCH 09/31] pretty looking errors in the info panel --- resources/css/info-panel.scss | 44 +++++++++++++++- resources/js/components/InfoPanel.js | 77 ++++++++++++++++++++-------- 2 files changed, 99 insertions(+), 22 deletions(-) diff --git a/resources/css/info-panel.scss b/resources/css/info-panel.scss index 3c273c7..c330dbd 100644 --- a/resources/css/info-panel.scss +++ b/resources/css/info-panel.scss @@ -5,10 +5,50 @@ right: 0; bottom: 0; overflow: auto; - padding: 1rem 1rem 2rem 1rem; } -#info-panel div { +#info-panel table { font-family: "Droid Sans Mono", "monospace", monospace; + border-spacing: 0; + width: 100%; } +#info-panel table thead { + position: sticky; + font-weight: bolder; + text-decoration: underline; + inset-block-start: 0; + background-color: var(--pgetinker-background-color); +} + +#info-panel table tr.error { + background-color: rgba(255,0,0,0.2); +} + +#info-panel table tr.warning { + background-color: rgba(255,255,0,0.2); +} + +#info-panel table tr.info { + background-color: rgba(0,0,255,0.2); +} + +#info-panel table tr.hint { + background-color: rgba(0, 255, 255,0.2); +} + +#info-panel table tbody tr:hover { + background-color: rgba(255, 255, 255, 0.2); + text-decoration: underline; + cursor: pointer; +} + +#info-panel table tr { + text-align: left; +} + +#info-panel table tr th, +#info-panel table tr td { + padding: 0.3rem; + padding-left: 1rem; +} diff --git a/resources/js/components/InfoPanel.js b/resources/js/components/InfoPanel.js index fb3b64a..e7f5883 100644 --- a/resources/js/components/InfoPanel.js +++ b/resources/js/components/InfoPanel.js @@ -10,33 +10,70 @@ export default class InfoPanel window.addEventListener("update-problems-panel", (event) => { - const diagnostics = event.detail; - document.querySelector("#info-panel").innerHTML = ""; - const wrapper = document.createElement("div"); + + + let diagnostics = []; + diagnostics.push([]); + diagnostics.push([]); + diagnostics.push([]); + diagnostics.push([]); - diagnostics.forEach((diagnostic) => + event.detail.forEach((diagnostic) => { - const container = document.createElement("p"); - const link = document.createElement("a"); + diagnostics[diagnostic.severity].push(diagnostic); + }); - link.setAttribute("href", "#"); - link.setAttribute("data-line-number", diagnostic.range.start._line); - link.setAttribute("data-column", diagnostic.range.start._character); - link.setAttribute("title", diagnostic.message); - link.innerHTML = diagnostic.message; + const wrapper = document.createElement("table"); + + const header = document.createElement("thead"); + + header.innerHTML = ` + Severity + Line + Column + Message + `; - link.addEventListener("click", (event) => + const body = document.createElement("tbody"); + while(diagnostics.length > 0) + { + let currentDiagnostics = diagnostics.shift(); + currentDiagnostics.sort((a, b) => { - const currentLink = event.target; - const lineNumber = parseInt(currentLink.getAttribute("data-line-number")) + 1; - const column = parseInt(currentLink.getAttribute("data-column")) + 1; - this.state.editorPanel.reveal({ lineNumber, column }); + return (parseInt(a.range.start._line) - parseInt(b.range.start._line)); }); - - container.append(link); - wrapper.append(container); - }); + + currentDiagnostics.forEach((diagnostic) => + { + const container = document.createElement("tr"); + container.classList.toggle(["Error", "Warning", "Info", "Hint"][diagnostic.severity].toLowerCase()); + + container.innerHTML = ` + ${["Error", "Warning", "Info", "Hint"][diagnostic.severity]} + ${diagnostic.range.start._line} + ${diagnostic.range.start._character} + ${diagnostic.message} + `; + + container.setAttribute("data-line-number", diagnostic.range.start._line); + container.setAttribute("data-column", diagnostic.range.start._character); + + container.addEventListener("click", (event) => + { + event.preventDefault(); + + const lineNumber = parseInt(container.getAttribute("data-line-number")) + 1; + const column = parseInt(container.getAttribute("data-column")) + 1; + this.state.editorPanel.reveal({ lineNumber, column }); + }); + + body.append(container); + }); + } + + wrapper.append(header); + wrapper.append(body); document.querySelector("#info-panel").append(wrapper); }); From 05e52f12563c0653529e2893847861b0b092af63 Mon Sep 17 00:00:00 2001 From: Moros Smith Date: Wed, 5 Jun 2024 23:26:02 -0400 Subject: [PATCH 10/31] wrapping pre-formatted text for the info panel after builds --- resources/css/info-panel.scss | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/resources/css/info-panel.scss b/resources/css/info-panel.scss index c330dbd..403ed51 100644 --- a/resources/css/info-panel.scss +++ b/resources/css/info-panel.scss @@ -7,6 +7,16 @@ overflow: auto; } +#info-panel > div { + font-family: "Droid Sans Mono", "monospace", monospace; + width: 100%; + white-space: pre-wrap; /* Since CSS 2.1 */ + white-space: -moz-pre-wrap; /* Mozilla, since 1999 */ + white-space: -pre-wrap; /* Opera 4-6 */ + white-space: -o-pre-wrap; /* Opera 7 */ + word-wrap: break-word; /* Internet Explorer 5.5+ */ +} + #info-panel table { font-family: "Droid Sans Mono", "monospace", monospace; border-spacing: 0; From 83c6a3f1421681be837b2ad379c08e40f6fb22d6 Mon Sep 17 00:00:00 2001 From: Moros Smith Date: Wed, 5 Jun 2024 23:26:14 -0400 Subject: [PATCH 11/31] shame on moros if he leaves this here --- resources/js/app.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/resources/js/app.js b/resources/js/app.js index 2f921c7..a34a104 100644 --- a/resources/js/app.js +++ b/resources/js/app.js @@ -305,6 +305,8 @@ class PGEtinker compileSuccessHandler(data) { + // pgetinker.cpp:19:17: warning: implicit conversion from 'float' to 'int' changes value from 0.1 to 0 [-Wliteral-conversion] 19 | int a = 0.1f; | ~ ^~~~ 1 warning generated. + alert("If you're seeing this message, Moros deserves to be spanked. Go tell him he left this in here."); this.infoPanel.setContent(data.stderr); this.playerPanel.setHtml(data.html); this.compiling = false; @@ -314,6 +316,7 @@ class PGEtinker { this.setActiveTab("C++ Editor"); + alert("If you're seeing this message, Moros deserves to be spanked. Go tell him he left this in here."); this.infoPanel.setContent(stderr); this.playerPanel.setCompilingFailed(); this.compiling = false; From d04016e112518bcfb578caf80177c6645c3f3677 Mon Sep 17 00:00:00 2001 From: Moros Smith Date: Thu, 6 Jun 2024 20:17:59 -0400 Subject: [PATCH 12/31] fix mobile oversize --- resources/css/app.scss | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/resources/css/app.scss b/resources/css/app.scss index 18b93c1..5e269f2 100644 --- a/resources/css/app.scss +++ b/resources/css/app.scss @@ -53,8 +53,11 @@ body.light { html, body { + position: relative; width: 100%; height: 100%; + margin: 0; + padding: 0; overflow: hidden; font-family: 'Pixel Code', monospace; font-size: 12px; @@ -73,7 +76,7 @@ a:hover { } #app { - position: fixed; + position: absolute; top: 0; left: 0; width: 100%; @@ -216,6 +219,8 @@ nav .navbar-right-menu .menu-item { bottom: 0px; width: 100%; overflow: hidden; + margin: 0; + padding: 0; border-top: 1px solid var(--pgetinker-content-border-color); border-bottom: 1px solid var(--pgetinker-content-border-color); } From 63129eceeca902e5cf81efa7f4719eee1892dcdc Mon Sep 17 00:00:00 2001 From: Moros Smith Date: Thu, 6 Jun 2024 20:21:27 -0400 Subject: [PATCH 13/31] add guards if the monaco wrapper hasn't been started --- resources/js/components/EditorPanel.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/resources/js/components/EditorPanel.js b/resources/js/components/EditorPanel.js index 706a75b..85c47d0 100644 --- a/resources/js/components/EditorPanel.js +++ b/resources/js/components/EditorPanel.js @@ -128,16 +128,25 @@ export default class EditorPanel exceedsMaxSize() { + if(this.monacoWrapper == null) + return false; + return (this.monacoWrapper.getEditor().getValue().length > this.maxFileSize); } focus() { + if(this.monacoWrapper == null) + return; + this.monacoWrapper.getEditor().focus(); } reveal(position) { + if(this.monacoWrapper == null) + return; + this.monacoWrapper.getEditor().setPosition(position); this.focus(); this.monacoWrapper.getEditor().revealPositionInCenter(position); @@ -156,6 +165,9 @@ export default class EditorPanel updateStatusBar() { + if(this.monacoWrapper == null) + return; + let statusBar = document.querySelector("#editor-panel .status"); let cursor = `Ln ${this.monacoWrapper.getEditor().getPosition().lineNumber}, Col ${this.monacoWrapper.getEditor().getPosition().column}`; From ebb72aac55f234422bc2600f1f18184d6b99b85e Mon Sep 17 00:00:00 2001 From: Moros Smith Date: Fri, 7 Jun 2024 11:45:09 -0400 Subject: [PATCH 14/31] let monaco hover hints overlap the layout --- resources/css/app.scss | 4 ++++ resources/css/editor-panel.scss | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/resources/css/app.scss b/resources/css/app.scss index 5e269f2..7f72921 100644 --- a/resources/css/app.scss +++ b/resources/css/app.scss @@ -238,3 +238,7 @@ nav .navbar-right-menu .menu-item { @import "./dialog.scss"; @import "./responsive.scss"; + +.lm_content { + overflow: visible !important; +} diff --git a/resources/css/editor-panel.scss b/resources/css/editor-panel.scss index f470aaa..8e557f9 100644 --- a/resources/css/editor-panel.scss +++ b/resources/css/editor-panel.scss @@ -2,6 +2,7 @@ position: relative; width: 100%; height: 100%; + overflow: visible; } #editor-panel .code-editor { @@ -17,7 +18,6 @@ left: 0; right: 0; bottom: 0px; - width: 100%; height: 1.2rem; line-height: 1.2rem; font-size: 0.8rem; From 6597792caccd58c32dceb8b44dfa9e48c4e56b0a Mon Sep 17 00:00:00 2001 From: Moros Smith Date: Sat, 8 Jun 2024 00:15:52 -0400 Subject: [PATCH 15/31] gut restart attempt --- resources/js/lib/monacoWrapper.js | 30 ------------------------------ 1 file changed, 30 deletions(-) diff --git a/resources/js/lib/monacoWrapper.js b/resources/js/lib/monacoWrapper.js index 989030f..d119ad5 100644 --- a/resources/js/lib/monacoWrapper.js +++ b/resources/js/lib/monacoWrapper.js @@ -52,36 +52,6 @@ export const runCppWrapper = async (htmlElement) => { } }); - window.addEventListener("pgetinker-start-language-server", async() => - { - if(!wrapper.getLanguageClientWrapper().isStarted()) - await wrapper.getLanguageClientWrapper().start(); - }); - - window.addEventListener("pgetinker-stop-language-server", async() => - { - if(wrapper.getLanguageClientWrapper().isStarted()) - await wrapper.getLanguageClientWrapper().disposeLanguageClient(); - }); - - window.addEventListener("pgetinker-restart-language-server", async(event) => - { - if(wrapper.getLanguageClientWrapper().isStarted() || event.detail.force) - await wrapper.getLanguageClientWrapper().restartLanguageClient(); - }); - - let keepAliveInterval; - - keepAliveInterval = setInterval(() => - { - // has the language client shutdown/disconnected? - if(!wrapper.getLanguageClientWrapper().isStarted()) - { - // force restart the language server, hopefully it'll reconnect - window.dispatchEvent(new CustomEvent("pgetinker-restart-language-server", { detail: { force: true } })); - } - }, 10000); - // @ts-ignore window.addEventListener("unload", async(event) => { await wrapper.dispose(); From 7eca43111bb7a06441a07ecf63022180daf8049c Mon Sep 17 00:00:00 2001 From: Moros Smith Date: Sat, 8 Jun 2024 02:48:56 -0400 Subject: [PATCH 16/31] remove info panel --- resources/css/info-panel.scss | 64 ------------- resources/js/components/InfoPanel.js | 134 --------------------------- 2 files changed, 198 deletions(-) delete mode 100644 resources/css/info-panel.scss delete mode 100644 resources/js/components/InfoPanel.js diff --git a/resources/css/info-panel.scss b/resources/css/info-panel.scss deleted file mode 100644 index 403ed51..0000000 --- a/resources/css/info-panel.scss +++ /dev/null @@ -1,64 +0,0 @@ -#info-panel { - position: absolute; - top: 0; - left: 0; - right: 0; - bottom: 0; - overflow: auto; -} - -#info-panel > div { - font-family: "Droid Sans Mono", "monospace", monospace; - width: 100%; - white-space: pre-wrap; /* Since CSS 2.1 */ - white-space: -moz-pre-wrap; /* Mozilla, since 1999 */ - white-space: -pre-wrap; /* Opera 4-6 */ - white-space: -o-pre-wrap; /* Opera 7 */ - word-wrap: break-word; /* Internet Explorer 5.5+ */ -} - -#info-panel table { - font-family: "Droid Sans Mono", "monospace", monospace; - border-spacing: 0; - width: 100%; -} - -#info-panel table thead { - position: sticky; - font-weight: bolder; - text-decoration: underline; - inset-block-start: 0; - background-color: var(--pgetinker-background-color); -} - -#info-panel table tr.error { - background-color: rgba(255,0,0,0.2); -} - -#info-panel table tr.warning { - background-color: rgba(255,255,0,0.2); -} - -#info-panel table tr.info { - background-color: rgba(0,0,255,0.2); -} - -#info-panel table tr.hint { - background-color: rgba(0, 255, 255,0.2); -} - -#info-panel table tbody tr:hover { - background-color: rgba(255, 255, 255, 0.2); - text-decoration: underline; - cursor: pointer; -} - -#info-panel table tr { - text-align: left; -} - -#info-panel table tr th, -#info-panel table tr td { - padding: 0.3rem; - padding-left: 1rem; -} diff --git a/resources/js/components/InfoPanel.js b/resources/js/components/InfoPanel.js deleted file mode 100644 index e7f5883..0000000 --- a/resources/js/components/InfoPanel.js +++ /dev/null @@ -1,134 +0,0 @@ - -export default class InfoPanel -{ - state; - - constructor(state) - { - this.state = state; - console.log("Info panel", "constructor"); - - window.addEventListener("update-problems-panel", (event) => - { - document.querySelector("#info-panel").innerHTML = ""; - - - let diagnostics = []; - diagnostics.push([]); - diagnostics.push([]); - diagnostics.push([]); - diagnostics.push([]); - - event.detail.forEach((diagnostic) => - { - diagnostics[diagnostic.severity].push(diagnostic); - }); - - const wrapper = document.createElement("table"); - - const header = document.createElement("thead"); - - header.innerHTML = ` - Severity - Line - Column - Message - `; - - const body = document.createElement("tbody"); - while(diagnostics.length > 0) - { - let currentDiagnostics = diagnostics.shift(); - currentDiagnostics.sort((a, b) => - { - return (parseInt(a.range.start._line) - parseInt(b.range.start._line)); - }); - - currentDiagnostics.forEach((diagnostic) => - { - const container = document.createElement("tr"); - container.classList.toggle(["Error", "Warning", "Info", "Hint"][diagnostic.severity].toLowerCase()); - - container.innerHTML = ` - ${["Error", "Warning", "Info", "Hint"][diagnostic.severity]} - ${diagnostic.range.start._line} - ${diagnostic.range.start._character} - ${diagnostic.message} - `; - - container.setAttribute("data-line-number", diagnostic.range.start._line); - container.setAttribute("data-column", diagnostic.range.start._character); - - container.addEventListener("click", (event) => - { - event.preventDefault(); - - const lineNumber = parseInt(container.getAttribute("data-line-number")) + 1; - const column = parseInt(container.getAttribute("data-column")) + 1; - this.state.editorPanel.reveal({ lineNumber, column }); - }); - - body.append(container); - }); - } - - wrapper.append(header); - wrapper.append(body); - - document.querySelector("#info-panel").append(wrapper); - }); - } - - - - clear() - { - document.querySelector("#info-panel").innerHTML = ""; - } - - exists() - { - return this.informationPanelExist; - } - - focus() - { - this.state.setActiveTab("Build Information"); - } - - onInit() - { - } - - register() - { - this.state.layout.registerComponent('infoComponent', function(container) - { - container.getElement().html(` -
-
- `); - }); - } - - setContent(content) - { - const infoPanel = document.querySelector("#info-panel"); - - while(infoPanel.lastElementChild) - { - infoPanel.removeChild(infoPanel.lastElementChild); - } - - if(typeof content === "string") - { - infoPanel.innerHTML = `
${content}
`; - } - else - { - infoPanel.append(content); - } - - } -} - From dd2575d3291d1a1aa8bee9318a62ff64adcb1fbe Mon Sep 17 00:00:00 2001 From: Moros Smith Date: Sat, 8 Jun 2024 02:49:18 -0400 Subject: [PATCH 17/31] add compiler output panel --- resources/css/compiler-output-panel.scss | 18 ++++++ .../js/components/CompilerOutputPanel.js | 59 +++++++++++++++++++ 2 files changed, 77 insertions(+) create mode 100644 resources/css/compiler-output-panel.scss create mode 100644 resources/js/components/CompilerOutputPanel.js diff --git a/resources/css/compiler-output-panel.scss b/resources/css/compiler-output-panel.scss new file mode 100644 index 0000000..a9e7a81 --- /dev/null +++ b/resources/css/compiler-output-panel.scss @@ -0,0 +1,18 @@ +#compiler-output-panel { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + overflow: auto; +} + +#compiler-output-panel > div { + font-family: "Droid Sans Mono", "monospace", monospace; + width: 100%; + white-space: pre-wrap; /* Since CSS 2.1 */ + white-space: -moz-pre-wrap; /* Mozilla, since 1999 */ + white-space: -pre-wrap; /* Opera 4-6 */ + white-space: -o-pre-wrap; /* Opera 7 */ + word-wrap: break-word; /* Internet Explorer 5.5+ */ +} diff --git a/resources/js/components/CompilerOutputPanel.js b/resources/js/components/CompilerOutputPanel.js new file mode 100644 index 0000000..6ab8990 --- /dev/null +++ b/resources/js/components/CompilerOutputPanel.js @@ -0,0 +1,59 @@ + +export default class CompilerOutputPanel +{ + state; + + constructor(state) + { + this.state = state; + console.log("CompilerOutputPanel", "constructor"); + } + + clear() + { + this.getElement().innerHTML = ""; + } + + focus() + { + this.state.setActiveTab('compiler-output'); + } + + getElement() + { + return document.querySelector("#compiler-output-panel"); + } + + onInit() {} + + register() + { + this.state.layout.registerComponent('compilerOutputComponent', function(container) + { + container.getElement().html(` +
+
+ `); + }); + } + + setContent(content) + { + const element = this.getElement(); + + while(element.lastElementChild) + { + element.removeChild(element.lastElementChild); + } + + if(typeof content === "string") + { + element.innerHTML = `
${content}
`; + } + else + { + element.append(content); + } + } +} + From 435a0bcb2989ceea0742027eb219eeb1586659ad Mon Sep 17 00:00:00 2001 From: Moros Smith Date: Sat, 8 Jun 2024 02:49:35 -0400 Subject: [PATCH 18/31] refactor console panel --- resources/js/components/ConsolePanel.js | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/resources/js/components/ConsolePanel.js b/resources/js/components/ConsolePanel.js index ab67f8d..edce418 100644 --- a/resources/js/components/ConsolePanel.js +++ b/resources/js/components/ConsolePanel.js @@ -20,40 +20,38 @@ export default class ConsolePanel if(event.data.message === "console-output") { - let consoleContainer = document.querySelector("#console-panel"); - consoleContainer.innerHTML += `
${event.data.data}
`; + this.getElement().innerHTML += `
${event.data.data}
`; // auto scroll if(this.consoleAutoScrollEnabled) - consoleContainer.scrollTop = consoleContainer.scrollHeight; + this.getElement().scrollTop = this.getElement().scrollHeight; - this.state.setActiveTab("Console"); + this.state.setActiveTab("console"); } }); } clear() { - document.querySelector("#console-panel").innerHTML = ""; + this.getElement().innerHTML = ""; } - exists() + getElement() { - return this.consolePanelExist; + return document.querySelector('#console-panel'); } onInit() { - let consoleContainer = document.querySelector("#console-panel"); document.querySelector("#console-auto-scroll").addEventListener("click", () => { this.consoleAutoScrollEnabled = true; document.querySelector("#console-auto-scroll").classList.toggle("hidden", this.consoleAutoScrollEnabled); }); - consoleContainer.addEventListener("wheel", (event) => + this.getElement().addEventListener("wheel", (event) => { - let nearBottom = ((consoleContainer.scrollHeight - consoleContainer.clientHeight) <= (consoleContainer.scrollTop + 1)); + let nearBottom = ((this.getElement().scrollHeight - this.getElement().clientHeight) <= (this.getElement().scrollTop + 1)); if(nearBottom) { @@ -61,7 +59,7 @@ export default class ConsolePanel if(event.deltaY < 0) { this.consoleAutoScrollEnabled = false; - consoleContainer.scrollTop = consoleContainer.scrollHeight - 20; + this.getElement().scrollTop = this.getElement().scrollHeight - 20; document.querySelector("#console-auto-scroll").classList.toggle("hidden", this.consoleAutoScrollEnabled); } } From 32427795a4e14cc22cc8ec4eab5aeb1609cb536c Mon Sep 17 00:00:00 2001 From: Moros Smith Date: Sat, 8 Jun 2024 02:49:49 -0400 Subject: [PATCH 19/31] use new storage method in editor/code --- resources/js/components/EditorPanel.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/resources/js/components/EditorPanel.js b/resources/js/components/EditorPanel.js index 85c47d0..91a8a32 100644 --- a/resources/js/components/EditorPanel.js +++ b/resources/js/components/EditorPanel.js @@ -1,6 +1,7 @@ import { getUserConfiguration } from "../lib/monacoConfig"; import { runCppWrapper } from "../lib/monacoWrapper"; import pgetinkerCppCode from '../../example.cpp?raw'; +import { getStorageValue } from "../lib/storage"; export default class EditorPanel { @@ -59,9 +60,9 @@ export default class EditorPanel { code = document.querySelector('#code').value; } - else if(window.localStorage.getItem("pgetinkerCode")) + else if(getStorageValue("code")) { - code = JSON.parse(window.localStorage.getItem("pgetinkerCode")); + code = getStorageValue("code"); } else { From 2016a225f1c8fff776ba33d671396cb42fc5dc02 Mon Sep 17 00:00:00 2001 From: Moros Smith Date: Sat, 8 Jun 2024 02:50:21 -0400 Subject: [PATCH 20/31] add problems panel --- resources/css/app.scss | 3 +- resources/css/problems-panel.scss | 64 +++++++++++ resources/js/components/ProblemsPanel.js | 130 +++++++++++++++++++++++ 3 files changed, 196 insertions(+), 1 deletion(-) create mode 100644 resources/css/problems-panel.scss create mode 100644 resources/js/components/ProblemsPanel.js diff --git a/resources/css/app.scss b/resources/css/app.scss index 7f72921..2c3f628 100644 --- a/resources/css/app.scss +++ b/resources/css/app.scss @@ -232,9 +232,10 @@ nav .navbar-right-menu .menu-item { .hidden { display: none; } @import "./console-panel.scss"; +@import "./compiler-output-panel.scss"; @import "./editor-panel.scss"; -@import "./info-panel.scss"; @import "./player-panel.scss"; +@import "./problems-panel.scss"; @import "./dialog.scss"; @import "./responsive.scss"; diff --git a/resources/css/problems-panel.scss b/resources/css/problems-panel.scss new file mode 100644 index 0000000..8a2ad17 --- /dev/null +++ b/resources/css/problems-panel.scss @@ -0,0 +1,64 @@ +#problems-panel { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + overflow: auto; +} + +#problems-panel > div { + font-family: "Droid Sans Mono", "monospace", monospace; + width: 100%; + white-space: pre-wrap; /* Since CSS 2.1 */ + white-space: -moz-pre-wrap; /* Mozilla, since 1999 */ + white-space: -pre-wrap; /* Opera 4-6 */ + white-space: -o-pre-wrap; /* Opera 7 */ + word-wrap: break-word; /* Internet Explorer 5.5+ */ +} + +#problems-panel table { + font-family: "Droid Sans Mono", "monospace", monospace; + border-spacing: 0; + width: 100%; +} + +#problems-panel table thead { + position: sticky; + font-weight: bolder; + text-decoration: underline; + inset-block-start: 0; + background-color: var(--pgetinker-background-color); +} + +#problems-panel table tr.error { + background-color: rgba(255,0,0,0.2); +} + +#problems-panel table tr.warning { + background-color: rgba(255,255,0,0.2); +} + +#problems-panel table tr.info { + background-color: rgba(0,0,255,0.2); +} + +#problems-panel table tr.hint { + background-color: rgba(0, 255, 255,0.2); +} + +#problems-panel table tbody tr:hover { + background-color: rgba(255, 255, 255, 0.2); + text-decoration: underline; + cursor: pointer; +} + +#problems-panel table tr { + text-align: left; +} + +#problems-panel table tr th, +#problems-panel table tr td { + padding: 0.3rem; + padding-left: 1rem; +} diff --git a/resources/js/components/ProblemsPanel.js b/resources/js/components/ProblemsPanel.js new file mode 100644 index 0000000..92790d2 --- /dev/null +++ b/resources/js/components/ProblemsPanel.js @@ -0,0 +1,130 @@ + +export default class ProblemsPanel +{ + state; + + constructor(state) + { + this.state = state; + console.log("Problems panel", "constructor"); + + window.addEventListener("update-problems-panel", (event) => + { + this.getElement().innerHTML = ""; + + let diagnostics = []; + diagnostics.push([]); + diagnostics.push([]); + diagnostics.push([]); + diagnostics.push([]); + + event.detail.forEach((diagnostic) => + { + diagnostics[diagnostic.severity].push(diagnostic); + }); + + const wrapper = document.createElement("table"); + + const header = document.createElement("thead"); + + header.innerHTML = ` + Severity + Line + Column + Message + `; + + const body = document.createElement("tbody"); + + while(diagnostics.length > 0) + { + let currentDiagnostics = diagnostics.shift(); + currentDiagnostics.sort((a, b) => + { + return (parseInt(a.range.start._line) - parseInt(b.range.start._line)); + }); + + currentDiagnostics.forEach((diagnostic) => + { + const container = document.createElement("tr"); + container.classList.toggle(["Error", "Warning", "Info", "Hint"][diagnostic.severity].toLowerCase()); + + container.innerHTML = ` + ${["Error", "Warning", "Info", "Hint"][diagnostic.severity]} + ${diagnostic.range.start._line} + ${diagnostic.range.start._character} + ${diagnostic.message} + `; + + container.setAttribute("data-line-number", diagnostic.range.start._line); + container.setAttribute("data-column", diagnostic.range.start._character); + + container.addEventListener("click", (event) => + { + event.preventDefault(); + + const lineNumber = parseInt(container.getAttribute("data-line-number")) + 1; + const column = parseInt(container.getAttribute("data-column")) + 1; + this.state.editorPanel.reveal({ lineNumber, column }); + }); + + body.append(container); + }); + } + + wrapper.append(header); + wrapper.append(body); + + this.getElement().append(wrapper); + }); + } + + clear() + { + this.getElement().innerHTML = ""; + } + + focus() + { + this.state.setActiveTab("problems"); + } + + getElement() + { + return document.querySelector("#problems-panel"); + } + + onInit() {} + + register() + { + this.state.layout.registerComponent('problemsComponent', function(container) + { + container.getElement().html(` +
+
+ `); + }); + } + + setContent(content) + { + const element = this.getElement(); + + while(element.lastElementChild) + { + element.removeChild(element.lastElementChild); + } + + if(typeof content === "string") + { + element.innerHTML = `
${content}
`; + } + else + { + element.append(content); + } + + } +} + From 66868984d1480025410ad108f9182f1843ed027c Mon Sep 17 00:00:00 2001 From: Moros Smith Date: Sat, 8 Jun 2024 02:50:35 -0400 Subject: [PATCH 21/31] remove old default layout --- resources/js/lib/defaultLayout.js | 45 ------------------------------- 1 file changed, 45 deletions(-) delete mode 100644 resources/js/lib/defaultLayout.js diff --git a/resources/js/lib/defaultLayout.js b/resources/js/lib/defaultLayout.js deleted file mode 100644 index f220264..0000000 --- a/resources/js/lib/defaultLayout.js +++ /dev/null @@ -1,45 +0,0 @@ -const defaultLayout = { - settings: { - showPopoutIcon: false, - }, - content: [{ - type: 'column', - content:[{ - type: 'row', - content:[{ - type: 'component', - componentName: 'editorComponent', - componentState: {}, - isClosable: false, - title: 'C++ Editor', - },{ - type: 'component', - componentName: 'playerComponent', - componentState: {}, - isClosable: false, - title: 'Emscripten Player', - }], - },{ - type: 'stack', - id: 'information-stack', - height: 25, - content: [{ - type: 'component', - componentName: 'infoComponent', - componentState: {}, - isClosable: false, - title: 'Build Information', - id: 'info', - },{ - type: 'component', - componentName: 'consoleComponent', - componentState: {}, - isClosable: false, - title: 'Console', - id: 'console', - }] - }], - }], -}; - -export default defaultLayout; \ No newline at end of file From 5bee0a38a4e4aaa6615a38dd51bb22dea43a32f5 Mon Sep 17 00:00:00 2001 From: Moros Smith Date: Sat, 8 Jun 2024 02:50:48 -0400 Subject: [PATCH 22/31] new storage system --- resources/js/lib/storage.js | 78 +++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 resources/js/lib/storage.js diff --git a/resources/js/lib/storage.js b/resources/js/lib/storage.js new file mode 100644 index 0000000..0443954 --- /dev/null +++ b/resources/js/lib/storage.js @@ -0,0 +1,78 @@ +const prefix = "pgetinker_"; +const store = window.localStorage; + +export function conformStorage() +{ + let agree = store.getItem("pgetinkerAgreedToTerms"); + store.removeItem("pgetinkerAgreedToTerms"); + if(agree) + { + setStorageValue("agreed-to-terms", true); + } + + let code = store.getItem("pgetinkerCode"); + store.removeItem("pgetinkerCode"); + if(code) + { + setStorageValue("code", JSON.parse(code)); + } + + let theme = store.getItem("pgetinkerTheme"); + store.removeItem("pgetinkerTheme"); + if(theme) + { + setStorageValue("theme", theme); + } +} + +export function getStorageValue(key) +{ + if(typeof key !== "string") + { + console.error("setStorageValue key must be string"); + return; + } + + let value = store.getItem(prefix + key); + + try + { + return JSON.parse(value); + } + catch(e) + { + if(typeof value === "string") + return value; + } + + return null; +} + +export function setStorageValue(key, value) +{ + if(typeof value === "string") + { + store.setItem(prefix + key, value); + return; + } + + try + { + store.setItem(prefix + key, JSON.stringify(value)); + } + catch(error) + { + console.error("setStorageValue failed to JSON.stringify value", error); + } +} + +export function removeStorageKey(key) +{ + if(typeof key === "string") + { + store.removeItem(prefix + key); + } + + return undefined; +} + From adab46975a699298be0e8146e7d9933fef040f01 Mon Sep 17 00:00:00 2001 From: Moros Smith Date: Sat, 8 Jun 2024 02:51:29 -0400 Subject: [PATCH 23/31] default layouts for portrait and landscape modes --- resources/js/lib/defaultLandscapeLayout.js | 54 ++++++++++++++++++++++ resources/js/lib/defaultPortraitLayout.js | 54 ++++++++++++++++++++++ 2 files changed, 108 insertions(+) create mode 100644 resources/js/lib/defaultLandscapeLayout.js create mode 100644 resources/js/lib/defaultPortraitLayout.js diff --git a/resources/js/lib/defaultLandscapeLayout.js b/resources/js/lib/defaultLandscapeLayout.js new file mode 100644 index 0000000..f3922d4 --- /dev/null +++ b/resources/js/lib/defaultLandscapeLayout.js @@ -0,0 +1,54 @@ +const defaultLandscapeLayout = { + settings: { + showPopoutIcon: false, + }, + content: [{ + type: 'column', + content:[{ + type: 'row', + content:[{ + type: 'component', + componentName: 'editorComponent', + componentState: {}, + isClosable: false, + title: 'C++ Editor', + id: 'editor', + },{ + type: 'component', + componentName: 'playerComponent', + componentState: {}, + isClosable: false, + title: 'Emscripten Player', + id: 'player', + }], + },{ + type: 'stack', + id: 'information-stack', + height: 25, + content: [{ + type: 'component', + componentName: 'problemsComponent', + componentState: {}, + isClosable: false, + title: 'Problems', + id: 'problems', + },{ + type: 'component', + componentName: 'compilerOutputComponent', + componentState: {}, + isClosable: false, + title: 'Compiler Output', + id: 'compiler-output', + },{ + type: 'component', + componentName: 'consoleComponent', + componentState: {}, + isClosable: false, + title: 'Console', + id: 'console', + }] + }], + }], +}; + +export default defaultLandscapeLayout; \ No newline at end of file diff --git a/resources/js/lib/defaultPortraitLayout.js b/resources/js/lib/defaultPortraitLayout.js new file mode 100644 index 0000000..ea0a39a --- /dev/null +++ b/resources/js/lib/defaultPortraitLayout.js @@ -0,0 +1,54 @@ +const defaultPortraitLayout = { + settings: { + showPopoutIcon: false, + }, + content: [{ + type: 'column', + content:[{ + type: 'stack', + content:[{ + type: 'component', + componentName: 'editorComponent', + componentState: {}, + isClosable: false, + title: 'C++ Editor', + id: 'editor', + },{ + type: 'component', + componentName: 'playerComponent', + componentState: {}, + isClosable: false, + title: 'Emscripten Player', + id: 'player', + }], + },{ + type: 'stack', + id: 'information-stack', + height: 25, + content: [{ + type: 'component', + componentName: 'problemsComponent', + componentState: {}, + isClosable: false, + title: 'Problems', + id: 'problems', + },{ + type: 'component', + componentName: 'compilerOutputComponent', + componentState: {}, + isClosable: false, + title: 'Compiler Output', + id: 'compiler-output', + },{ + type: 'component', + componentName: 'consoleComponent', + componentState: {}, + isClosable: false, + title: 'Console', + id: 'console', + }] + }], + }], +}; + +export default defaultPortraitLayout; \ No newline at end of file From 8d9bc179aad6148326ed88e2581d7c740b109cc9 Mon Sep 17 00:00:00 2001 From: Moros Smith Date: Sat, 8 Jun 2024 02:52:18 -0400 Subject: [PATCH 24/31] use new storage, add new layouts, add problems panel, add compiler output panel, remove info panel --- resources/js/app.js | 100 +++++++++++++++++++++++++++----------------- 1 file changed, 61 insertions(+), 39 deletions(-) diff --git a/resources/js/app.js b/resources/js/app.js index a34a104..35784d9 100644 --- a/resources/js/app.js +++ b/resources/js/app.js @@ -2,23 +2,28 @@ import './lib/bootstrap'; import './lib/goldenLayout'; import './lib/lucide'; import version from "./lib/version"; +import { conformStorage, getStorageValue, setStorageValue } from './lib/storage'; import agreeDialog from './lib/agreeDialog'; import shareDialog from './lib/shareDialog'; import newsDialog from './lib/newsDialog'; -import defaultLayout from './lib/defaultLayout'; +import defaultLandscapeLayout from './lib/defaultLandscapeLayout'; +import defaultPortraitLayout from './lib/defaultPortraitLayout'; import supportersDialog from './lib/supportersDialog'; import ConsolePanel from './components/ConsolePanel'; +import CompilerOutputPanel from './components/CompilerOutputPanel'; import EditorPanel from './components/EditorPanel'; -import InfoPanel from './components/InfoPanel'; import PlayerPanel from './components/PlayerPanel'; +import ProblemsPanel from './components/ProblemsPanel'; +import { removeStorageKey } from './lib/storage'; class PGEtinker { consolePanel; editorPanel; - infoPanel; + compilerOutputPanel; playerPanel; + problemsPanel; layoutInitialized = false; compiling = false; @@ -29,13 +34,30 @@ class PGEtinker constructor() { - this.consolePanel = new ConsolePanel(this); - this.editorPanel = new EditorPanel(this); - this.infoPanel = new InfoPanel(this); - this.playerPanel = new PlayerPanel(this); + conformStorage(); - this.layoutConfig = window.localStorage.getItem("pgetinkerLayout"); - this.layoutConfig = (this.layoutConfig !== null) ? JSON.parse(this.layoutConfig) : defaultLayout; + this.consolePanel = new ConsolePanel(this); + this.compilerOutputPanel = new CompilerOutputPanel(this); + this.editorPanel = new EditorPanel(this); + this.playerPanel = new PlayerPanel(this); + this.problemsPanel = new ProblemsPanel(this); + + + this.layoutConfig = getStorageValue("layout"); + if(this.layoutConfig === null) + { + this.layoutConfig = defaultLandscapeLayout; + + if(document.body.clientWidth <= 750) + { + console.log("chose portrait layout"); + this.layoutConfig = defaultPortraitLayout; + } + else + { + console.log("chose landscapre layout"); + } + } this.theme = window.localStorage.getItem("pgetinkerTheme"); if(this.theme !== "dark" && this.theme !== "light") @@ -157,7 +179,7 @@ class PGEtinker if(spanElem.innerHTML == "Run") { - this.setActiveTab("Emscripten Player"); + this.setActiveTab("player"); playIconElem.classList.toggle("hidden", true); stopIconElem.classList.toggle("hidden", false); @@ -173,13 +195,15 @@ class PGEtinker if(spanElem.innerHTML == "Stop") { - this.setActiveTab("C++ Editor"); + this.setActiveTab("editor"); this.playerPanel.stop(); playIconElem.classList.toggle("hidden", false); stopIconElem.classList.toggle("hidden", true); spanElem.innerHTML = "Run"; } + + startStopElem.blur(); }); document.querySelector("#supporters").addEventListener("click", (event) => @@ -194,23 +218,20 @@ class PGEtinker newsDialog(); }); - let agreedToTerms = window.localStorage.getItem("pgetinkerAgreedToTerms"); - agreedToTerms = (agreedToTerms == null) ? false : JSON.parse(agreedToTerms); - - if(!agreedToTerms) + if(!getStorageValue("agreed-to-terms")) { agreeDialog() .then(() => { - window.localStorage.setItem("pgetinkerAgreedToTerms", JSON.stringify(true)); + setStorageValue("agreed-to-terms", true); this.SetupLayout(); }) .catch(() => { - window.localStorage.removeItem("pgetinkerCode"); - window.localStorage.removeItem("pgetinkerTheme"); - window.localStorage.removeItem("pgetinkerLayout"); - window.localStorage.removeItem("pgetinkerVersion"); + removeStorageKey("code"); + removeStorageKey("theme"); + removeStorageKey("layout"); + removeStorageKey("version"); window.location.pathname = "/disagree"; }); } @@ -220,13 +241,13 @@ class PGEtinker } } - setActiveTab(title) + setActiveTab(id) { try { let panel = this.layout.root.getItemsByFilter((item) => { - return (item.config.title == title); + return (item.config.id == id); })[0]; if(panel.parent.isStack) @@ -236,7 +257,7 @@ class PGEtinker } catch(e) { - console.log(`Failed to setActiveTab("${title}")`); + console.log(`Failed to setActiveTab("${id}")`); } } @@ -248,8 +269,8 @@ class PGEtinker return false; } - this.infoPanel.focus(); - this.infoPanel.clear(); + this.compilerOutputPanel.focus(); + this.compilerOutputPanel.clear(); this.consolePanel.clear(); this.playerPanel.setCompiling(); @@ -307,17 +328,17 @@ class PGEtinker { // pgetinker.cpp:19:17: warning: implicit conversion from 'float' to 'int' changes value from 0.1 to 0 [-Wliteral-conversion] 19 | int a = 0.1f; | ~ ^~~~ 1 warning generated. alert("If you're seeing this message, Moros deserves to be spanked. Go tell him he left this in here."); - this.infoPanel.setContent(data.stderr); + this.compilerOutputPanel.setContent(data.stderr); this.playerPanel.setHtml(data.html); this.compiling = false; } compileFailHandler(stderr) { - this.setActiveTab("C++ Editor"); + this.setActiveTab("editor"); alert("If you're seeing this message, Moros deserves to be spanked. Go tell him he left this in here."); - this.infoPanel.setContent(stderr); + this.compilerOutputPanel.setContent(stderr); this.playerPanel.setCompilingFailed(); this.compiling = false; } @@ -332,13 +353,16 @@ class PGEtinker this.consolePanel.register(); this.editorPanel.register(); - this.infoPanel.register(); + this.compilerOutputPanel.register(); this.playerPanel.register(); + this.problemsPanel.register(); this.layout.on("stateChanged", () => { if(this.layoutInitialized) - window.localStorage.setItem("pgetinkerLayout", JSON.stringify(this.layout.toConfig())); + { + setStorageValue("layout", this.layout.toConfig()); + } }); this.layout.on("initialised", async() => @@ -352,29 +376,27 @@ class PGEtinker this.consolePanel.onInit(); await this.editorPanel.onInit(); - this.infoPanel.onInit(); + this.compilerOutputPanel.onInit(); this.playerPanel.onInit(); - + this.problemsPanel.onInit(); + await this.UpdateTheme(); setTimeout(() => { document.querySelector("#pgetinker-loading").classList.toggle("display-flex", false); - this.setActiveTab("C++ Editor"); + this.setActiveTab("editor"); }, 500) }); this.layout.init(); - let pgetinkerVersion = window.localStorage.getItem("pgetinkerVersion"); - pgetinkerVersion = (pgetinkerVersion != "string") ? pgetinkerVersion : ""; - - if(version !== pgetinkerVersion) + if(version !== getStorageValue("version")) { newsDialog() .finally(() => { - window.localStorage.setItem("pgetinkerVersion", version); + setStorageValue("version", version); }); } @@ -383,7 +405,7 @@ class PGEtinker async UpdateTheme() { // save theme into localStorage - window.localStorage.setItem("pgetinkerTheme", this.theme); + setStorageValue("theme", this.theme); let light = (this.theme === "light"); From 74c986df7741e5f7bc85844379c616e2cd0cb091 Mon Sep 17 00:00:00 2001 From: Moros Smith Date: Sat, 8 Jun 2024 03:09:49 -0400 Subject: [PATCH 25/31] remove moros shaming, the task is complete --- resources/js/app.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/resources/js/app.js b/resources/js/app.js index 35784d9..9bddfe3 100644 --- a/resources/js/app.js +++ b/resources/js/app.js @@ -326,8 +326,6 @@ class PGEtinker compileSuccessHandler(data) { - // pgetinker.cpp:19:17: warning: implicit conversion from 'float' to 'int' changes value from 0.1 to 0 [-Wliteral-conversion] 19 | int a = 0.1f; | ~ ^~~~ 1 warning generated. - alert("If you're seeing this message, Moros deserves to be spanked. Go tell him he left this in here."); this.compilerOutputPanel.setContent(data.stderr); this.playerPanel.setHtml(data.html); this.compiling = false; @@ -337,7 +335,6 @@ class PGEtinker { this.setActiveTab("editor"); - alert("If you're seeing this message, Moros deserves to be spanked. Go tell him he left this in here."); this.compilerOutputPanel.setContent(stderr); this.playerPanel.setCompilingFailed(); this.compiling = false; From 2282af3ef80cfaa25ed493f6a57ea89039163d4b Mon Sep 17 00:00:00 2001 From: Moros Smith Date: Sat, 8 Jun 2024 03:10:25 -0400 Subject: [PATCH 26/31] make problems cells of specific width, so as to not change very time a new entry is added/removed --- resources/css/problems-panel.scss | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/resources/css/problems-panel.scss b/resources/css/problems-panel.scss index 8a2ad17..5cc3c34 100644 --- a/resources/css/problems-panel.scss +++ b/resources/css/problems-panel.scss @@ -31,6 +31,22 @@ background-color: var(--pgetinker-background-color); } +#problems-panel table thead tr td:nth-child(1) { + width: 15vw; +} + +#problems-panel table thead tr td:nth-child(2) { + width: 5vw; +} + +#problems-panel table thead tr td:nth-child(3) { + width: 5vw; +} + +#problems-panel table thead tr td:nth-child(4) { + width: 100%; +} + #problems-panel table tr.error { background-color: rgba(255,0,0,0.2); } From c061a9baf2cf8da1bfba00be93aed3e0bc3f9f8d Mon Sep 17 00:00:00 2001 From: Moros Smith Date: Sat, 8 Jun 2024 03:10:51 -0400 Subject: [PATCH 27/31] make problems panel focused when it's state changes. --- resources/js/components/ProblemsPanel.js | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/js/components/ProblemsPanel.js b/resources/js/components/ProblemsPanel.js index 92790d2..360a9c8 100644 --- a/resources/js/components/ProblemsPanel.js +++ b/resources/js/components/ProblemsPanel.js @@ -76,6 +76,7 @@ export default class ProblemsPanel wrapper.append(body); this.getElement().append(wrapper); + this.state.setActiveTab('problems'); }); } From 78941c5e74618c69ac7be2c2d18a1a08a34d856f Mon Sep 17 00:00:00 2001 From: Moros Smith Date: Sat, 8 Jun 2024 03:28:03 -0400 Subject: [PATCH 28/31] set focus to editor and problems panels --- resources/js/app.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/resources/js/app.js b/resources/js/app.js index 9bddfe3..4d8ca38 100644 --- a/resources/js/app.js +++ b/resources/js/app.js @@ -238,6 +238,8 @@ class PGEtinker else { this.SetupLayout(); + this.setActiveTab("editor"); + this.setActiveTab("problems"); } } From a065f7efc7481fcd60201974c8c5bdf0c3867f78 Mon Sep 17 00:00:00 2001 From: Moros Smith Date: Sat, 8 Jun 2024 13:05:03 -0400 Subject: [PATCH 29/31] only change to console on the first run of the program --- resources/js/app.js | 1 + resources/js/components/ConsolePanel.js | 15 +++++++++++++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/resources/js/app.js b/resources/js/app.js index 4d8ca38..d3a8ddc 100644 --- a/resources/js/app.js +++ b/resources/js/app.js @@ -181,6 +181,7 @@ class PGEtinker { this.setActiveTab("player"); + this.consolePanel.setFirstRun(); playIconElem.classList.toggle("hidden", true); stopIconElem.classList.toggle("hidden", false); spanElem.innerHTML = "Stop"; diff --git a/resources/js/components/ConsolePanel.js b/resources/js/components/ConsolePanel.js index edce418..32890b9 100644 --- a/resources/js/components/ConsolePanel.js +++ b/resources/js/components/ConsolePanel.js @@ -4,10 +4,13 @@ export default class ConsolePanel consoleAutoScrollEnabled = true; state; - + firstRun; + constructor(state) { this.state = state; + this.firstRun = true; + console.log("Console panel", "constructor"); window.addEventListener("message", (event) => @@ -26,7 +29,11 @@ export default class ConsolePanel if(this.consoleAutoScrollEnabled) this.getElement().scrollTop = this.getElement().scrollHeight; - this.state.setActiveTab("console"); + if(this.firstRun) + { + this.state.setActiveTab("console"); + this.firstRun = false; + } } }); } @@ -77,4 +84,8 @@ export default class ConsolePanel }); } + setFirstRun() + { + this.firstRun = true; + } } \ No newline at end of file From ac6fc8d07ff93d5111d90e691486f42d44042455 Mon Sep 17 00:00:00 2001 From: Moros Smith Date: Sat, 8 Jun 2024 13:10:47 -0400 Subject: [PATCH 30/31] update changelog --- CHANGELOG.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5325dba..4d73faf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,17 @@ All notable changes to this project will be documented in this file. Each batch It is a summary of changes that would be pertinent to the end user of the PGEtinker website. For a comprehensive history of changes made to the project, please refer to the repository's commit history. +## 2024-06-08 + +- Fixed mobile overize issue (big win for mobile) +- Added diagnostics middleware to monaco language client +- Changed Build Information panel to Compiler Output +- Added Problems panel +- Removed old default layout +- Added default layout for portrait +- Added default layout for landscape +- Added storage abstraction + ## 2024-06-04 - Added Alert when a runtime error occurs From 92c0a9d4b1e71ed126066444609ea9c0ee9b85f1 Mon Sep 17 00:00:00 2001 From: Moros Smith Date: Sat, 8 Jun 2024 13:29:22 -0400 Subject: [PATCH 31/31] adjust browser tests to match new ui elements --- tests/Browser/BrowserTest.php | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/tests/Browser/BrowserTest.php b/tests/Browser/BrowserTest.php index 48cec55..61eb3df 100644 --- a/tests/Browser/BrowserTest.php +++ b/tests/Browser/BrowserTest.php @@ -50,7 +50,8 @@ public function testShowsNewsAndUpdates(): void $this->browse(function(Browser $browser) { $browser->visit("/"); - $browser->pause(1000); + $browser->waitUntilMissing("#pgetinker-loading"); + $browser->assertSee("News and Updates"); }); } @@ -60,12 +61,10 @@ public function testDismissesNewsAndUpdates(): void $this->browse(function(Browser $browser) { $browser->visit("/"); - - $browser->pause(1000); - - $browser->click(".news"); + $browser->waitUntilMissing("#pgetinker-loading"); - $browser->pause(1000); + $browser->click(".news .content"); + $browser->waitUntilMissing(".news"); $browser->assertNotPresent(".news"); }); @@ -106,7 +105,6 @@ public function testCompilesOnClick(): void $this->browse(function(Browser $browser) { $browser->visit("/"); - $browser->waitUntilMissing("#pgetinker-loading"); $browser->click("#start-stop"); @@ -120,7 +118,6 @@ public function testSharesOnClick(): void $this->browse(function(Browser $browser) { $browser->visit("/"); - $browser->waitUntilMissing("#pgetinker-loading"); $browser->mouseover("@sharing-menu");