From ea2be319f6d2c06ec1fad620ac9d666817f54413 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=83=8B=E3=83=A5=E3=83=BC=E3=82=A8=E3=82=B9=E3=83=88?= Date: Mon, 20 Nov 2023 00:25:53 +0800 Subject: [PATCH 1/6] Update electron.cjs --- Mod Manager/src/electron.cjs | 65 +++++++++++++++++++++++++----------- 1 file changed, 46 insertions(+), 19 deletions(-) diff --git a/Mod Manager/src/electron.cjs b/Mod Manager/src/electron.cjs index 3d36192b..6d15c10b 100644 --- a/Mod Manager/src/electron.cjs +++ b/Mod Manager/src/electron.cjs @@ -4,6 +4,7 @@ const { app, BrowserWindow, ipcMain, dialog } = require("electron") const serve = require("electron-serve") const fs = require("fs") const path = require("path") +const { spawn } = require('child_process'); try { require("electron-reloader")(module) @@ -124,30 +125,56 @@ if (!lock) { }) } -ipcMain.on("deploy", () => { - let deployProcess = require("child_process").spawn("Deploy.exe --doNotPause --colors", ["--doNotPause --colors"], { - shell: true, - cwd: ".." - }) +ipcMain.on("deploy", async () => { + const deployProcess = spawn("Deploy.exe", ["--doNotPause", "--colors"], { + shell: true, + cwd: ".." + }); - let deployOutput = "" + mainWindow.webContents.send("frameworkDeployModalOpen"); - mainWindow.webContents.send("frameworkDeployModalOpen") + let deployOutputBuffer = []; + let isProcessClosed = false; + let lastSendTime = Date.now(); + const throttleInterval = 150; - deployProcess.stdout.on("data", (data) => { - deployOutput += String(data) - mainWindow.webContents.send("frameworkDeployOutput", deployOutput) - }) + const sendOutput = () => { + mainWindow.webContents.send("frameworkDeployOutput", deployOutputBuffer.join('\n')); + lastSendTime = Date.now(); + }; - deployProcess.stderr.on("data", (data) => { - deployOutput += String(data) - mainWindow.webContents.send("frameworkDeployOutput", deployOutput) - }) + let partialLine = ''; - deployProcess.on("close", (data) => { - mainWindow.webContents.send("frameworkDeployFinished") - }) -}) + const onData = (data) => { + const lines = (partialLine + data.toString()).split('\n'); + partialLine = lines.pop(); + + deployOutputBuffer.push(...lines.filter(line => line.trim() !== '')); + + if (lines.length > 0 && Date.now() - lastSendTime > throttleInterval) { + sendOutput(); + } + }; + + deployProcess.stdout.on('data', onData); + deployProcess.stderr.on('data', onData); + + await new Promise((resolve, reject) => { + deployProcess.on('close', () => { + isProcessClosed = true; + sendOutput(); + resolve(); + }); + deployProcess.on('error', (error) => { + mainWindow.webContents.send("frameworkDeployError", error.message); + reject(error); + }); + }); + + if (isProcessClosed) { + mainWindow.webContents.send("frameworkDeployFinished"); + } + }); ipcMain.on("modFileOpenDialog", () => { mainWindow.webContents.send( From 3af43a5348570760c9d41941d86bdc8790989abf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=83=8B=E3=83=A5=E3=83=BC=E3=82=A8=E3=82=B9=E3=83=88?= Date: Mon, 20 Nov 2023 00:26:55 +0800 Subject: [PATCH 2/6] Update +page.svelte --- Mod Manager/src/routes/modList/+page.svelte | 256 ++++++++++++++++---- 1 file changed, 215 insertions(+), 41 deletions(-) diff --git a/Mod Manager/src/routes/modList/+page.svelte b/Mod Manager/src/routes/modList/+page.svelte index d91bcb56..4b4ebbe5 100644 --- a/Mod Manager/src/routes/modList/+page.svelte +++ b/Mod Manager/src/routes/modList/+page.svelte @@ -5,7 +5,6 @@ import json5 from "json5" import { Button, CodeSnippet, InlineNotification, Modal, ProgressBar, Search } from "carbon-components-svelte" import AnsiToHTML from "ansi-to-html" - import throttle from "lodash/throttle" const convertAnsi = new AnsiToHTML({ newline: true, @@ -71,40 +70,125 @@ }) let changed = false - let showDropHint = false let dependencyCycleModalOpen = false let frameworkDeployModalOpen = false let deployOutput = "" - let deployOutputHTML = "" - let deployDiagnostics: string[] = [] let deployFinished = false - - window.ipc.receive("frameworkDeployModalOpen", () => { - frameworkDeployModalOpen = true - }) - - const convertOutputToHTML = throttle(() => { - deployOutputHTML = convertAnsi.toHtml(deployOutput) - - if (deployDiagnostics.length < 20) { - deployDiagnostics = deployOutput.split(/\r?\n/).filter((a) => a.match(/.*WARN.*?\t/) || a.match(/.*ERROR.*?\t/)) + let ignoreScrollEvent = false; + let autoScrollDeployOutput = true; + let userHasScrolledDeployOutput = false; + let autoScrollNotifications = true; + let userHasScrolledNotifications = false; + let notifications = []; + let outputLines: string | any[] = []; + + + $: outputLines = deployOutput.split(/\r?\n/).filter(line => line.trim() !== ''); + $: if (outputLines.length > 0 && autoScrollDeployOutput) { + requestAnimationFrame(() => { + const outputElement = document.getElementById('deployOutputElement'); + if (outputElement) { + outputElement.scrollTop = outputElement.scrollHeight; + } + }); + } + $: { let combinedNotifications = [...warnings, ...errors]; + if (combinedNotifications.length !== notifications.length) { + notifications = combinedNotifications; + scrollToBottom('notificationElement'); + } + } + $: if (outputLines.length > 0 && autoScrollDeployOutput) { + scrollToBottom('deployOutputElement'); + } + $: if (notifications.length > 0 && autoScrollNotifications) { + scrollToBottom('notificationElement'); + } + + function handleScroll(event: UIEvent & { currentTarget: EventTarget & HTMLDivElement }, elementId: string) { + if (ignoreScrollEvent) { + return; + } + + const element = event.target; + const nearBottom = element.scrollHeight - element.clientHeight <= element.scrollTop + 10; + // The error is right, so do not add a non-null assertion for it. If you do, the user will not be able to scroll in the deploy and notification output anymore. - Knew + + if (elementId === 'deployOutputElement') { + if (!nearBottom) { + userHasScrolledDeployOutput = true; + autoScrollDeployOutput = false; + } + } else if (elementId === 'notificationElement') { + if (!nearBottom) { + userHasScrolledNotifications = true; + autoScrollNotifications = false; + } } - - setTimeout(() => { - document.getElementById("deployOutputElement")?.children[0].scrollIntoView(false) - }, 100) - }, 500) - - window.ipc.receive("frameworkDeployOutput", (output: string) => { - deployOutput = output - convertOutputToHTML() - }) + } + + function scrollToBottom(elementId: string) { + requestAnimationFrame(() => { + const element = document.getElementById(elementId); + if (element) { + element.scrollTop = element.scrollHeight; + } + setTimeout(() => ignoreScrollEvent = false, 100); + }); + } + + function enableAutoScrollDeployOutput() { + autoScrollDeployOutput = true; + userHasScrolledDeployOutput = false; + scrollToBottom('deployOutputElement'); + } + + function enableAutoScrollNotifications() { + autoScrollNotifications = true; + userHasScrolledNotifications = false; + scrollToBottom('notificationElement'); + } + + window.ipc.receive("frameworkDeployModalOpen", () => { + frameworkDeployModalOpen = true + }) + + window.ipc.receive("frameworkDeployOutput", (output: string) => { + ignoreScrollEvent = true; + deployOutput = output; + outputLines = deployOutput.split(/\r?\n/).filter(line => line.trim() !== ''); + if (!userHasScrolledDeployOutput) { + scrollToBottom('deployOutputElement'); + } + }); window.ipc.receive("frameworkDeployFinished", () => { deployFinished = true }) + let warnings: any[] = []; + let errors: any[] = []; + + $: { + let warningIndex = 1; + let errorIndex = 1; + warnings = []; + errors = []; + + deployOutput.split(/\r?\n/).forEach(line => { + if (line.match(/.*WARN.*?\t/)) { + warnings.push({ message: line.replace(/.*WARN.*?\t/, ""), count: warningIndex++ }); + } else if (line.match(/.*ERROR.*?\t/)) { + errors.push({ message: line.replace(/.*ERROR.*?\t/, ""), count: errorIndex++ }); + } + }); + } + + $: totalWarnings = warnings.length; + $: totalErrors = errors.length; + $: totalNotifications = totalWarnings + totalErrors; + document.addEventListener("drop", (event) => { event.preventDefault() event.stopPropagation() @@ -448,7 +532,6 @@ on:click={() => { if (sortMods()) { deployOutput = "" - deployOutputHTML = "" deployFinished = false window.ipc.send("deploy") } else { @@ -550,24 +633,83 @@ Your mods are being deployed. This may take a while - grab a coffee or something.
-
{@html deployOutputHTML}
- {#if deployOutput.split(/\r?\n/).some((a) => a.match(/.*WARN.*?\t/)) || deployOutput.split(/\r?\n/).some((a) => a.match(/.*ERROR.*?\t/))} -
-
- {#each deployDiagnostics as line} - -
- {line.includes("WARN") ? "Warning" : "Error"} -
-
{line.replace(/.*WARN.*?\t/, "").replace(/.*ERROR.*?\t/, "")}
-
- {/each} +
handleScroll(event, 'deployOutputElement')}> + + {#each outputLines as line} +
{@html convertAnsi.toHtml(line)}
+ {/each} + + {#if userHasScrolledDeployOutput} + + {/if} + +
+ {#if warnings.length > 0 || errors.length > 0} +
+
handleScroll(event, 'notificationElement')}> + + {#each warnings as warning} + +
Warning #{warning.count}
+
{warning.message}
+
+ {/each} + + {#each errors as error} + +
Error #{error.count}
+
{error.message}
+
+ {/each} + + {#if userHasScrolledNotifications} + + {/if} +
{/if} +
+ {#if totalNotifications > 0} + + + + + {totalWarnings} + + + + + + + {totalErrors} + + {/if} +
+ + {#if deployFinished}
@@ -577,7 +719,7 @@ .filter((a) => a.length) .at(-1) .match(/\tDone in .*/) && !deployOutput.split(/\r?\n/).some((a) => a.match(/.*WARN.*?\t/))} - + Deploy successful {:else if deployOutput .split(/\r?\n/) @@ -806,4 +948,36 @@ :global(.bx--snippet.bx--snippet--single) { background-color: #262626; } + + .overflow-y-auto { + color-scheme: dark !important; + } + + :global(.bx--inline-notification) { + margin-right: 10px !important; + margin-left: 8px !important; + background:#2F2F2F !important; + max-width: 100% !important; + margin-top: 0rem !important; + margin-bottom: 0rem !important; + } + + :global(.bx--modal-content) { + overflow-y: visible !important; + } + + @media (min-width: 42rem) {:global(.bx--modal-container) { + position: relative !important; + height: auto !important; + width: 90% !important; + min-height: 30rem !important; + }} + + :global(.bx--modal-content) { + margin-bottom:1.8rem !important; + } + + :global(.bx--modal-header) { + margin-bottom:0rem !important; + } From 46af1f853af21a51c4020c5d230c67e8b56298f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=83=8B=E3=83=A5=E3=83=BC=E3=82=A8=E3=82=B9=E3=83=88?= Date: Sat, 25 Nov 2023 16:27:45 +0800 Subject: [PATCH 3/6] Update +page.svelte --- Mod Manager/src/routes/modList/+page.svelte | 64 ++++++++++++--------- 1 file changed, 37 insertions(+), 27 deletions(-) diff --git a/Mod Manager/src/routes/modList/+page.svelte b/Mod Manager/src/routes/modList/+page.svelte index 4b4ebbe5..11ca884c 100644 --- a/Mod Manager/src/routes/modList/+page.svelte +++ b/Mod Manager/src/routes/modList/+page.svelte @@ -5,6 +5,7 @@ import json5 from "json5" import { Button, CodeSnippet, InlineNotification, Modal, ProgressBar, Search } from "carbon-components-svelte" import AnsiToHTML from "ansi-to-html" + import throttle from "lodash/throttle" const convertAnsi = new AnsiToHTML({ newline: true, @@ -74,14 +75,15 @@ let dependencyCycleModalOpen = false let frameworkDeployModalOpen = false let deployOutput = "" + let deployOutputBuffer = "" let deployFinished = false - let ignoreScrollEvent = false; - let autoScrollDeployOutput = true; - let userHasScrolledDeployOutput = false; - let autoScrollNotifications = true; - let userHasScrolledNotifications = false; - let notifications = []; - let outputLines: string | any[] = []; + let ignoreScrollEvent = false + let autoScrollDeployOutput = true + let userHasScrolledDeployOutput = false + let autoScrollNotifications = true + let userHasScrolledNotifications = false + let notifications = [] + let outputLines: string | any[] = [] $: outputLines = deployOutput.split(/\r?\n/).filter(line => line.trim() !== ''); @@ -106,6 +108,16 @@ scrollToBottom('notificationElement'); } + const updateDeployOutput = throttle(() => { + deployOutput += deployOutputBuffer; + deployOutputBuffer = ""; + outputLines = deployOutput.split(/\r?\n/).filter(line => line.trim() !== ''); + + if (!userHasScrolledDeployOutput) { + scrollToBottom('deployOutputElement'); + } + }, 150); + function handleScroll(event: UIEvent & { currentTarget: EventTarget & HTMLDivElement }, elementId: string) { if (ignoreScrollEvent) { return; @@ -113,7 +125,7 @@ const element = event.target; const nearBottom = element.scrollHeight - element.clientHeight <= element.scrollTop + 10; - // The error is right, so do not add a non-null assertion for it. If you do, the user will not be able to scroll in the deploy and notification output anymore. - Knew + // The VSC error is right, so do not add a non-null assertion for it. If you do, the user will not be able to scroll in the deploy and notification output anymore. - Knew if (elementId === 'deployOutputElement') { if (!nearBottom) { @@ -128,15 +140,16 @@ } } - function scrollToBottom(elementId: string) { - requestAnimationFrame(() => { - const element = document.getElementById(elementId); - if (element) { - element.scrollTop = element.scrollHeight; - } - setTimeout(() => ignoreScrollEvent = false, 100); - }); - } + function scrollToBottom(elementId: string) { + requestAnimationFrame(() => { + requestAnimationFrame(() => { // The double requestAnimationFrame is intentional!! Without it, there is a chance the output will stop scrolling when the user didn't request it. - Knew + const element = document.getElementById(elementId); + if (element) { + element.scrollTop = element.scrollHeight; + } + }); + }); + } function enableAutoScrollDeployOutput() { autoScrollDeployOutput = true; @@ -154,14 +167,11 @@ frameworkDeployModalOpen = true }) - window.ipc.receive("frameworkDeployOutput", (output: string) => { - ignoreScrollEvent = true; - deployOutput = output; - outputLines = deployOutput.split(/\r?\n/).filter(line => line.trim() !== ''); - if (!userHasScrolledDeployOutput) { - scrollToBottom('deployOutputElement'); - } - }); + window.ipc.receive("frameworkDeployOutput", (output: string) => { + ignoreScrollEvent = true; + deployOutputBuffer += output + "\n"; + updateDeployOutput(); + }); window.ipc.receive("frameworkDeployFinished", () => { deployFinished = true @@ -645,7 +655,7 @@ {#if userHasScrolledDeployOutput}