Spaces:
Runtime error
Runtime error
Update public/index.html
Browse files- public/index.html +55 -14
public/index.html
CHANGED
|
@@ -192,6 +192,7 @@
|
|
| 192 |
<div class="progress-bar-outer"><div class="progress-bar-inner" id="progressBar"></div></div>
|
| 193 |
</div>
|
| 194 |
<div id="fileInfoBar" style="display:none;"></div>
|
|
|
|
| 195 |
|
| 196 |
<!-- Editor -->
|
| 197 |
<div class="editor-layout" id="editorLayout" style="display:none;">
|
|
@@ -315,9 +316,21 @@ fetch('/tools').then(r => r.json()).then(tools => {
|
|
| 315 |
}
|
| 316 |
}).catch(() => {});
|
| 317 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 318 |
// ββ AUTO-INIT ββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 319 |
-
const LS_TOKEN_KEY
|
| 320 |
-
const LS_RAW_KEY
|
|
|
|
| 321 |
|
| 322 |
(function initFromServer() {
|
| 323 |
const wrap = document.getElementById('progressWrap');
|
|
@@ -342,14 +355,24 @@ const LS_RAW_KEY = 'supercity_raw';
|
|
| 342 |
sessionToken = savedToken;
|
| 343 |
originalRaw = savedRaw;
|
| 344 |
parseCharacters(savedRaw);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 345 |
wrap.style.display = 'none';
|
| 346 |
document.getElementById('fileInfoBar').style.display = 'flex';
|
| 347 |
document.getElementById('fileInfoBar').innerHTML = `
|
| 348 |
<div class="file-info">β» <span class="file-info-name">Session restored</span>
|
| 349 |
-
Β· ${characters.length} characters loaded</div>`;
|
| 350 |
document.getElementById('editorLayout').style.display = 'grid';
|
| 351 |
-
setStep(2);
|
| 352 |
-
showToast('β Session restored β
|
| 353 |
} else {
|
| 354 |
localStorage.removeItem(LS_TOKEN_KEY);
|
| 355 |
localStorage.removeItem(LS_RAW_KEY);
|
|
@@ -511,6 +534,16 @@ function saveCharacter() {
|
|
| 511 |
document.getElementById('unsavedBadge').style.display = 'none';
|
| 512 |
showToast(`β ${ch.name} saved`);
|
| 513 |
setStep(3);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 514 |
}
|
| 515 |
|
| 516 |
function resetCharacter() {
|
|
@@ -543,19 +576,27 @@ function exportAPK() {
|
|
| 543 |
})
|
| 544 |
.then(res => {
|
| 545 |
if (!res.ok) return res.json().then(e => { throw new Error(e.error); });
|
| 546 |
-
return res.
|
| 547 |
})
|
| 548 |
-
.then(
|
| 549 |
-
const url = URL.createObjectURL(blob);
|
| 550 |
-
const a = document.createElement('a');
|
| 551 |
-
a.href = url;
|
| 552 |
-
a.download = 'SuperCity_modded.apk';
|
| 553 |
-
a.click();
|
| 554 |
-
URL.revokeObjectURL(url);
|
| 555 |
btn.disabled = false;
|
| 556 |
btn.textContent = 'β¬ Export Patched APK';
|
| 557 |
-
showToast('β Patched
|
| 558 |
setStep(3);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 559 |
})
|
| 560 |
.catch(err => {
|
| 561 |
btn.disabled = false;
|
|
|
|
| 192 |
<div class="progress-bar-outer"><div class="progress-bar-inner" id="progressBar"></div></div>
|
| 193 |
</div>
|
| 194 |
<div id="fileInfoBar" style="display:none;"></div>
|
| 195 |
+
<div id="downloadBar" style="display:none; margin-top:12px;"></div>
|
| 196 |
|
| 197 |
<!-- Editor -->
|
| 198 |
<div class="editor-layout" id="editorLayout" style="display:none;">
|
|
|
|
| 316 |
}
|
| 317 |
}).catch(() => {});
|
| 318 |
|
| 319 |
+
// ββ DOWNLOAD LINK ββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 320 |
+
fetch('/download-link').then(r => r.json()).then(data => {
|
| 321 |
+
const bar = document.getElementById('downloadBar');
|
| 322 |
+
bar.style.display = 'block';
|
| 323 |
+
bar.innerHTML = `<div class="file-info" style="background:rgba(0,200,255,0.08);border-color:var(--accent);">
|
| 324 |
+
β¬ <span class="file-info-name">${data.patched ? 'β Patched APK ready' : 'Original APK'}</span> Β·
|
| 325 |
+
<a href="${data.url}" style="color:var(--accent);font-weight:700;letter-spacing:1px;" download>Click here to download</a>
|
| 326 |
+
${data.patched ? '' : ' Β· <span style="color:var(--text-dim);font-size:11px;">edit characters below to patch</span>'}
|
| 327 |
+
</div>`;
|
| 328 |
+
}).catch(() => {});
|
| 329 |
+
|
| 330 |
// ββ AUTO-INIT ββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 331 |
+
const LS_TOKEN_KEY = 'supercity_session_token';
|
| 332 |
+
const LS_RAW_KEY = 'supercity_raw';
|
| 333 |
+
const LS_EDITED_KEY = 'supercity_edited';
|
| 334 |
|
| 335 |
(function initFromServer() {
|
| 336 |
const wrap = document.getElementById('progressWrap');
|
|
|
|
| 355 |
sessionToken = savedToken;
|
| 356 |
originalRaw = savedRaw;
|
| 357 |
parseCharacters(savedRaw);
|
| 358 |
+
|
| 359 |
+
// Restore edits if any were saved
|
| 360 |
+
const savedEdited = localStorage.getItem(LS_EDITED_KEY);
|
| 361 |
+
if (savedEdited) {
|
| 362 |
+
const editedFields = savedEdited.split('|');
|
| 363 |
+
characters.forEach(ch => {
|
| 364 |
+
ch.fields = editedFields.slice(ch.startIdx, ch.startIdx + ch.fields.length);
|
| 365 |
+
});
|
| 366 |
+
}
|
| 367 |
+
|
| 368 |
wrap.style.display = 'none';
|
| 369 |
document.getElementById('fileInfoBar').style.display = 'flex';
|
| 370 |
document.getElementById('fileInfoBar').innerHTML = `
|
| 371 |
<div class="file-info">β» <span class="file-info-name">Session restored</span>
|
| 372 |
+
Β· ${characters.length} characters loaded${savedEdited ? ' Β· <b style="color:var(--accent2)">edits recovered</b>' : ''}</div>`;
|
| 373 |
document.getElementById('editorLayout').style.display = 'grid';
|
| 374 |
+
setStep(savedEdited ? 3 : 2);
|
| 375 |
+
showToast(savedEdited ? 'β Session + edits restored β ready to export' : 'β Session restored');
|
| 376 |
} else {
|
| 377 |
localStorage.removeItem(LS_TOKEN_KEY);
|
| 378 |
localStorage.removeItem(LS_RAW_KEY);
|
|
|
|
| 534 |
document.getElementById('unsavedBadge').style.display = 'none';
|
| 535 |
showToast(`β ${ch.name} saved`);
|
| 536 |
setStep(3);
|
| 537 |
+
persistEdits();
|
| 538 |
+
}
|
| 539 |
+
|
| 540 |
+
function persistEdits() {
|
| 541 |
+
// Rebuild current edited raw and save to localStorage
|
| 542 |
+
const allFields = originalRaw.split('|');
|
| 543 |
+
characters.forEach(ch => {
|
| 544 |
+
ch.fields.forEach((val, j) => { allFields[ch.startIdx + j] = val; });
|
| 545 |
+
});
|
| 546 |
+
localStorage.setItem(LS_EDITED_KEY, allFields.join('|'));
|
| 547 |
}
|
| 548 |
|
| 549 |
function resetCharacter() {
|
|
|
|
| 576 |
})
|
| 577 |
.then(res => {
|
| 578 |
if (!res.ok) return res.json().then(e => { throw new Error(e.error); });
|
| 579 |
+
return res.json();
|
| 580 |
})
|
| 581 |
+
.then(data => {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 582 |
btn.disabled = false;
|
| 583 |
btn.textContent = 'β¬ Export Patched APK';
|
| 584 |
+
showToast('β Patched β click the download link');
|
| 585 |
setStep(3);
|
| 586 |
+
// Show native browser download prompt
|
| 587 |
+
const a = document.createElement('a');
|
| 588 |
+
a.href = data.url;
|
| 589 |
+
a.download = 'supercity_modded.apk';
|
| 590 |
+
document.body.appendChild(a);
|
| 591 |
+
a.click();
|
| 592 |
+
document.body.removeChild(a);
|
| 593 |
+
// Refresh download bar
|
| 594 |
+
const bar = document.getElementById('downloadBar');
|
| 595 |
+
bar.innerHTML = `<div class="file-info" style="background:rgba(61,220,151,0.08);border-color:var(--civilian);">
|
| 596 |
+
β <span class="file-info-name" style="color:var(--civilian)">Patched APK ready</span> Β·
|
| 597 |
+
<a href="${data.url}" style="color:var(--accent);font-weight:700;letter-spacing:1px;" download="supercity_modded.apk">Click here to download again</a>
|
| 598 |
+
</div>`;
|
| 599 |
+
bar.style.display = 'block';
|
| 600 |
})
|
| 601 |
.catch(err => {
|
| 602 |
btn.disabled = false;
|