diff --git a/ui/index.html b/ui/index.html index f9faa455..83ee96a6 100644 --- a/ui/index.html +++ b/ui/index.html @@ -100,7 +100,11 @@ - +
+ + + +
diff --git a/ui/media/css/main.css b/ui/media/css/main.css index 0f28ab6d..1c624934 100644 --- a/ui/media/css/main.css +++ b/ui/media/css/main.css @@ -191,15 +191,29 @@ code { background: rgb(132, 8, 0); border: 2px solid rgb(122, 29, 0); color: rgb(255, 221, 255); - width: 100%; height: 30pt; border-radius: 6px; - display: none; - margin-top: 2pt; + flex-grow: 2; } #stopImage:hover { background: rgb(177, 27, 0); } + +div#render-buttons { + gap: 3px; + margin-top: 4px; + display: none; +} +button#pause { + flex-grow: 1; + background: var(--accent-color); +} +button#resume { + flex-grow: 1; + background: var(--accent-color); + display: none; +} + .flex-container { display: flex; width: 100%; @@ -1097,3 +1111,50 @@ button#save-system-settings-btn { #ip-info div { line-height: 200%; } + +/* SCROLLBARS */ +:root { + --scrollbar-width: 14px; + --scrollbar-radius: 10px; +} + +.scrollbar-editor::-webkit-scrollbar { + width: 8px; +} + +.scrollbar-editor::-webkit-scrollbar-track { + border-radius: 10px; +} + +.scrollbar-editor::-webkit-scrollbar-thumb { + background: --background-color2; + border-radius: 10px; +} + +::-webkit-scrollbar { + width: var(--scrollbar-width); +} + +::-webkit-scrollbar-track { + box-shadow: inset 0 0 5px var(--input-border-color); + border-radius: var(--input-border-radius); +} + +::-webkit-scrollbar-thumb { + background: var(--background-color2); + border-radius: var(--scrollbar-radius); +} + +body.pause { + border: solid 12px var(--accent-color); +} + +body.wait-pause { + animation: blinker 2s linear infinite; +} + +@keyframes blinker { + 0% { border: solid 12px var(--accent-color); } + 50% { border: solid 12px var(--background-color1); } + 100% { border: solid 12px var(--accent-color); } +} diff --git a/ui/media/js/engine.js b/ui/media/js/engine.js index 7d84fafa..934ade4d 100644 --- a/ui/media/js/engine.js +++ b/ui/media/js/engine.js @@ -10,8 +10,8 @@ const IDLE_COOLDOWN = 2500 // ms const CONCURRENT_TASK_INTERVAL = 500 // ms - /** Connects to an endpoint and resumes connexion after reaching end of stream until all data is received. - * Allows closing the connexion while the server buffers more data. + /** Connects to an endpoint and resumes connection after reaching end of stream until all data is received. + * Allows closing the connection while the server buffers more data. */ class ChunkedStreamReader { #bufferedString = '' // Data received waiting to be read. @@ -264,11 +264,11 @@ function isServerAvailable() { if (typeof serverState !== 'object') { - console.error('serverState not set to a value. Connexion to server could be lost...') + console.error('serverState not set to a value. Connection to server could be lost...') return false } if (Date.now() >= serverState.time + SERVER_STATE_VALIDITY_DURATION) { - console.warn('SERVER_STATE_VALIDITY_DURATION elapsed. Connexion to server could be lost...') + console.warn('SERVER_STATE_VALIDITY_DURATION elapsed. Connection to server could be lost...') return false } switch (serverState.status) { @@ -306,7 +306,7 @@ if (await healthCheck() && isServerAvailable()) { // Force a recheck of server status before failure... continue // Continue waiting if last healthCheck confirmed the server is still alive. } - throw new Error('Connexion with server lost.') + throw new Error('Connection with server lost.') } } if (Date.now() >= serverState.time + SERVER_STATE_VALIDITY_DURATION) { diff --git a/ui/media/js/main.js b/ui/media/js/main.js index 5fbdbac7..7cb2d73c 100644 --- a/ui/media/js/main.js +++ b/ui/media/js/main.js @@ -45,6 +45,9 @@ let streamImageProgressField = document.querySelector("#stream_image_progress") let makeImageBtn = document.querySelector('#makeImage') let stopImageBtn = document.querySelector('#stopImage') +let pauseBtn = document.querySelector('#pause') +let resumeBtn = document.querySelector('#resume') +let renderButtons = document.querySelector('#render-buttons') let imagesContainer = document.querySelector('#current-images') let initImagePreviewContainer = document.querySelector('#init_image_preview_container') @@ -456,6 +459,10 @@ function makeImage() { async function onIdle() { const serverCapacity = SD.serverCapacity + if (pauseClient===true) { + await resumeClient() + } + for (const taskEntry of getUncompletedTaskEntries()) { if (SD.activeTasks.size >= serverCapacity) { break @@ -649,7 +656,7 @@ function onTaskCompleted(task, reqBody, instance, outputContainer, stepUpdate) { return } - stopImageBtn.style.display = 'none' + renderButtons.style.display = 'none' renameMakeImageButton() if (isSoundEnabled()) { @@ -734,7 +741,7 @@ async function onTaskStart(task) { ) setStatus('request', 'fetching..') - stopImageBtn.style.display = 'block' + renderButtons.style.display = 'flex' renameMakeImageButton() previewTools.style.display = 'block' } @@ -1387,6 +1394,37 @@ function linkTabContents(tab) { tab.addEventListener("click", event => selectTab(tab.id)) } +let pauseClient = false + +function resumeClient() { + if (pauseClient) { + document.body.classList.remove('wait-pause') + document.body.classList.add('pause') + } + return new Promise(resolve => { + let playbuttonclick = function () { + resumeBtn.removeEventListener("click", playbuttonclick); + resolve("resolved"); + } + resumeBtn.addEventListener("click", playbuttonclick) + }) +} + +pauseBtn.addEventListener("click", function () { + pauseClient = true + pauseBtn.style.display="none" + resumeBtn.style.display = "inline" + document.body.classList.add('wait-pause') +}) + +resumeBtn.addEventListener("click", function () { + pauseClient = false + resumeBtn.style.display = "none" + pauseBtn.style.display = "inline" + document.body.classList.remove('pause') + document.body.classList.remove('wait-pause') +}) + document.querySelectorAll(".tab").forEach(linkTabContents) window.addEventListener("beforeunload", function(e) {