Merge pull request #6 from rubiidev18alt/codex/add-loading-circle-next-to-downloading-text

Add animated loader/progress UI and smarter progress text parsing
This commit is contained in:
rubiidev18alt 2026-03-13 16:28:17 -07:00 committed by GitHub
commit 124fb9dbcb
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 99 additions and 6 deletions

View file

@ -22,7 +22,7 @@
<div id="loader"> <div id="loader">
<div class="loader-content"> <div class="loader-content">
<div class="loader-spinner"></div> <div class="loader-spinner"></div>
<div id="loader-text">CONNECTING...</div> <div id="loader-text"><span id="loader-text-label">CONNECTING</span><span class="loading-dots animate" id="loader-dots" aria-hidden="true"><span>.</span><span>.</span><span>.</span></span></div>
</div> </div>
</div> </div>
@ -92,7 +92,10 @@
</div> </div>
<div class="progress-container" id="progress-container"> <div class="progress-container" id="progress-container">
<div class="progress-text" id="progress-text">Downloading...</div> <div class="progress-text-wrap" id="progress-text-wrap">
<span class="loader-spinner progress-spinner" id="progress-spinner" aria-hidden="true"></span>
<div class="progress-text" id="progress-text"><span id="progress-text-label">Downloading</span><span class="loading-dots" id="progress-dots" aria-hidden="true"><span>.</span><span>.</span><span>.</span></span><span id="progress-text-suffix"></span></div>
</div>
<div class="progress-bar-bg"> <div class="progress-bar-bg">
<div class="progress-bar-fill" id="progress-bar-fill"></div> <div class="progress-bar-fill" id="progress-bar-fill"></div>
</div> </div>

View file

@ -1125,7 +1125,11 @@ async function fetchGitHubData() {
const offlineInd = document.getElementById('offline-indicator'); const offlineInd = document.getElementById('offline-indicator');
if (loader) loader.style.display = 'flex'; if (loader) loader.style.display = 'flex';
if (loaderText) loaderText.textContent = "SYNCING: " + repo; if (loaderText) {
const loaderLabel = document.getElementById('loader-text-label');
if (loaderLabel) loaderLabel.textContent = "SYNCING: " + repo;
else loaderText.textContent = "SYNCING: " + repo;
}
const hideLoader = () => { const hideLoader = () => {
if (loader) { if (loader) {
@ -1416,8 +1420,29 @@ function setProcessingState(active) {
function updateProgress(percent, text) { function updateProgress(percent, text) {
const bar = document.getElementById('progress-bar-fill'); const bar = document.getElementById('progress-bar-fill');
if (bar) bar.style.width = percent + "%"; if (bar) bar.style.width = percent + "%";
const label = document.getElementById('progress-text-label');
const dots = document.getElementById('progress-dots');
const suffix = document.getElementById('progress-text-suffix');
const txt = document.getElementById('progress-text'); const txt = document.getElementById('progress-text');
if (text && txt) txt.textContent = text;
if (!text) return;
if (label && dots && suffix) {
const match = text.match(/^(Downloading)(?:\.{0,3})?(.*)$/i);
if (match) {
label.textContent = match[1];
suffix.textContent = match[2] || '';
dots.classList.add('animate');
return;
}
label.textContent = text;
suffix.textContent = '';
dots.classList.remove('animate');
return;
}
if (txt) txt.textContent = text;
} }
async function handleElectronFlow(url) { async function handleElectronFlow(url) {

View file

@ -568,12 +568,71 @@ body.steamdeck-mode .sidebar {
transition: width 0.2s ease-out; transition: width 0.2s ease-out;
} }
.progress-text-wrap {
display: flex;
align-items: center;
justify-content: flex-start;
gap: 8px;
margin-bottom: 6px;
}
.progress-spinner {
width: 12px;
height: 12px;
border-width: 2px;
border-color: #333;
border-top-color: var(--mc-progress-fill);
margin: 0;
flex-shrink: 0;
animation-duration: 1s;
}
.progress-text { .progress-text {
color: #fff; color: #fff;
font-size: 20px; font-size: 20px;
text-shadow: 2px 2px 0 #000; text-shadow: 2px 2px 0 #000;
margin-bottom: 6px; text-align: left;
text-align: center; display: inline-flex;
align-items: center;
}
.loading-dots {
display: inline-flex;
width: 1.8em;
justify-content: flex-start;
}
.loading-dots span {
visibility: hidden;
}
.loading-dots.animate span:nth-child(1) {
animation: dotCycle1 1.1s steps(1, end) infinite;
}
.loading-dots.animate span:nth-child(2) {
animation: dotCycle2 1.1s steps(1, end) infinite;
}
.loading-dots.animate span:nth-child(3) {
animation: dotCycle3 1.1s steps(1, end) infinite;
}
@keyframes dotCycle1 {
0%, 49% { visibility: hidden; }
50%, 100% { visibility: visible; }
}
@keyframes dotCycle2 {
0%, 32% { visibility: hidden; }
33%, 66% { visibility: visible; }
67%, 100% { visibility: hidden; }
}
@keyframes dotCycle3 {
0%, 16% { visibility: hidden; }
17%, 82% { visibility: visible; }
83%, 100% { visibility: hidden; }
} }
.modal-overlay { .modal-overlay {
@ -803,12 +862,18 @@ body.steamdeck-mode .sidebar {
background: rgba(0,0,0,0.8); background: rgba(0,0,0,0.8);
} }
.loader-content { .loader-content {
position: relative; position: relative;
z-index: 1; z-index: 1;
text-align: center; text-align: center;
} }
#loader-text {
display: inline-flex;
align-items: center;
}
.loader-spinner { .loader-spinner {
width: 80px; width: 80px;
height: 80px; height: 80px;