Reaperxxxx commited on
Commit
bd82bd3
Β·
verified Β·
1 Parent(s): 37de16f

Update public/index.html

Browse files
Files changed (1) hide show
  1. public/index.html +71 -4
public/index.html CHANGED
@@ -4,7 +4,8 @@
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
  <title>Super City β€” Character Editor</title>
7
- <link href="https://fonts.googleapis.com/css2?family=Rajdhani:wght@400;500;600;700&family=Share+Tech+Mono&display=swap" rel="stylesheet">
 
8
  <style>
9
  :root {
10
  --bg: #0a0c10;
@@ -28,7 +29,7 @@
28
  body {
29
  background: var(--bg);
30
  color: var(--text);
31
- font-family: 'Rajdhani', sans-serif;
32
  font-size: 15px;
33
  min-height: 100vh;
34
  }
@@ -81,7 +82,7 @@
81
  .panel-header { padding: 10px 14px; background: rgba(0,200,255,0.06); border-bottom: 1px solid var(--border); font-size: 11px; font-weight: 700; letter-spacing: 3px; text-transform: uppercase; color: var(--accent); display: flex; align-items: center; gap: 8px; }
82
  .panel-header .count { margin-left: auto; font-family: 'Share Tech Mono', monospace; font-size: 12px; color: var(--text-dim); font-weight: 400; letter-spacing: 0; }
83
  .search-wrap { padding: 10px; border-bottom: 1px solid var(--border); }
84
- .search-input { width: 100%; background: var(--bg); border: 1px solid var(--border-bright); color: var(--text-bright); font-family: 'Rajdhani', sans-serif; font-size: 14px; padding: 8px 10px 8px 30px; border-radius: 3px; outline: none; transition: border-color 0.2s; background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' fill='%235a7080' viewBox='0 0 16 16'%3E%3Cpath d='M11.742 10.344a6.5 6.5 0 1 0-1.397 1.398h-.001c.03.04.062.078.098.115l3.85 3.85a1 1 0 0 0 1.415-1.414l-3.85-3.85a1.007 1.007 0 0 0-.115-.099zm-5.242 1.656a5.5 5.5 0 1 1 0-11 5.5 5.5 0 0 1 0 11z'/%3E%3C/svg%3E"); background-repeat: no-repeat; background-position: 10px center; }
85
  .search-input:focus { border-color: var(--accent); }
86
  .search-input::placeholder { color: var(--text-dim); }
87
  .char-list { max-height: 520px; overflow-y: auto; scrollbar-width: thin; scrollbar-color: var(--border-bright) transparent; }
@@ -130,7 +131,7 @@
130
 
131
  /* ACTIONS */
132
  .actions-bar { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
133
- .btn { padding: 10px 22px; border: none; cursor: pointer; font-family: 'Rajdhani', sans-serif; font-size: 14px; font-weight: 700; letter-spacing: 2px; text-transform: uppercase; border-radius: 3px; transition: all 0.2s; display: flex; align-items: center; gap: 6px; }
134
  .btn-primary { background: var(--accent); color: #000; }
135
  .btn-primary:hover { background: #30dfff; box-shadow: 0 0 20px rgba(0,200,255,0.4); }
136
  .btn-secondary { background: transparent; color: var(--text); border: 1px solid var(--border-bright); }
@@ -150,6 +151,15 @@
150
  .tool-badge.ok { background: rgba(61,220,151,0.1); color: var(--civilian); border: 1px solid rgba(61,220,151,0.3); }
151
  .tool-badge.missing { background: rgba(255,68,85,0.1); color: var(--danger); border: 1px solid rgba(255,68,85,0.3); }
152
 
 
 
 
 
 
 
 
 
 
153
  /* TOAST */
154
  .toast { position: fixed; bottom: 30px; right: 30px; background: var(--panel); border: 1px solid var(--accent); color: var(--text-bright); padding: 12px 20px; border-radius: 4px; font-size: 14px; font-weight: 600; letter-spacing: 1px; box-shadow: 0 4px 20px rgba(0,0,0,0.5); transform: translateY(80px); opacity: 0; transition: all 0.3s cubic-bezier(0.34,1.56,0.64,1); z-index: 1000; }
155
  .toast.show { transform: translateY(0); opacity: 1; }
@@ -189,6 +199,15 @@
189
  <div class="upload-sub">or click to browse Β· .apk files only Β· max 200 MB</div>
190
  <input type="file" id="apkInput" accept=".apk">
191
  </div>
 
 
 
 
 
 
 
 
 
192
  <div class="progress-wrap" id="progressWrap">
193
  <div class="progress-label" id="progressLabel">Uploading…</div>
194
  <div class="progress-bar-outer"><div class="progress-bar-inner" id="progressBar"></div></div>
@@ -365,6 +384,7 @@ function uploadAPK(file) {
365
  <div class="file-info">πŸ“¦ <span class="file-info-name">${file.name}</span>
366
  &nbsp;Β·&nbsp; ${characters.length} characters loaded &nbsp;Β·&nbsp; session: ${sessionToken.split('_')[0]}</div>`;
367
  document.getElementById('editorLayout').style.display = 'grid';
 
368
  setStep(2);
369
  showToast(`βœ” Loaded ${characters.length} characters`);
370
  } else {
@@ -378,6 +398,53 @@ function uploadAPK(file) {
378
  xhr.send(form);
379
  }
380
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
381
  // ── PARSE ──────────────────────────────────────────────────────────
382
  function parseCharacters(raw) {
383
  characters = [];
 
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
  <title>Super City β€” Character Editor</title>
7
+ <link href="https://fonts.cdnfonts.com/css/copper-black" rel="stylesheet">
8
+ <link href="https://fonts.googleapis.com/css2?family=Share+Tech+Mono&display=swap" rel="stylesheet">
9
  <style>
10
  :root {
11
  --bg: #0a0c10;
 
29
  body {
30
  background: var(--bg);
31
  color: var(--text);
32
+ font-family: 'Copper Black', serif;
33
  font-size: 15px;
34
  min-height: 100vh;
35
  }
 
82
  .panel-header { padding: 10px 14px; background: rgba(0,200,255,0.06); border-bottom: 1px solid var(--border); font-size: 11px; font-weight: 700; letter-spacing: 3px; text-transform: uppercase; color: var(--accent); display: flex; align-items: center; gap: 8px; }
83
  .panel-header .count { margin-left: auto; font-family: 'Share Tech Mono', monospace; font-size: 12px; color: var(--text-dim); font-weight: 400; letter-spacing: 0; }
84
  .search-wrap { padding: 10px; border-bottom: 1px solid var(--border); }
85
+ .search-input { width: 100%; background: var(--bg); border: 1px solid var(--border-bright); color: var(--text-bright); font-family: 'Copper Black', serif; font-size: 14px; padding: 8px 10px 8px 30px; border-radius: 3px; outline: none; transition: border-color 0.2s; background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' fill='%235a7080' viewBox='0 0 16 16'%3E%3Cpath d='M11.742 10.344a6.5 6.5 0 1 0-1.397 1.398h-.001c.03.04.062.078.098.115l3.85 3.85a1 1 0 0 0 1.415-1.414l-3.85-3.85a1.007 1.007 0 0 0-.115-.099zm-5.242 1.656a5.5 5.5 0 1 1 0-11 5.5 5.5 0 0 1 0 11z'/%3E%3C/svg%3E"); background-repeat: no-repeat; background-position: 10px center; }
86
  .search-input:focus { border-color: var(--accent); }
87
  .search-input::placeholder { color: var(--text-dim); }
88
  .char-list { max-height: 520px; overflow-y: auto; scrollbar-width: thin; scrollbar-color: var(--border-bright) transparent; }
 
131
 
132
  /* ACTIONS */
133
  .actions-bar { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
134
+ .btn { padding: 10px 22px; border: none; cursor: pointer; font-family: 'Copper Black', serif; font-size: 14px; font-weight: 700; letter-spacing: 2px; text-transform: uppercase; border-radius: 3px; transition: all 0.2s; display: flex; align-items: center; gap: 6px; }
135
  .btn-primary { background: var(--accent); color: #000; }
136
  .btn-primary:hover { background: #30dfff; box-shadow: 0 0 20px rgba(0,200,255,0.4); }
137
  .btn-secondary { background: transparent; color: var(--text); border: 1px solid var(--border-bright); }
 
151
  .tool-badge.ok { background: rgba(61,220,151,0.1); color: var(--civilian); border: 1px solid rgba(61,220,151,0.3); }
152
  .tool-badge.missing { background: rgba(255,68,85,0.1); color: var(--danger); border: 1px solid rgba(255,68,85,0.3); }
153
 
154
+ /* URL UPLOAD */
155
+ .url-upload-wrap { margin-top: 12px; }
156
+ .url-upload-inner { display: flex; align-items: center; gap: 10px; background: var(--panel); border: 1px solid var(--border); border-radius: 4px; padding: 10px 14px; }
157
+ .url-label { font-family: 'Share Tech Mono', monospace; font-size: 11px; color: var(--text-dim); letter-spacing: 1px; white-space: nowrap; }
158
+ .url-input { flex: 1; background: var(--bg); border: 1px solid var(--border-bright); color: var(--text-bright); font-family: 'Share Tech Mono', monospace; font-size: 12px; padding: 7px 10px; border-radius: 3px; outline: none; transition: border-color 0.2s; }
159
+ .url-input:focus { border-color: var(--accent); }
160
+ .url-input::placeholder { color: var(--text-dim); }
161
+ .url-btn { padding: 7px 16px; font-size: 12px; white-space: nowrap; }
162
+
163
  /* TOAST */
164
  .toast { position: fixed; bottom: 30px; right: 30px; background: var(--panel); border: 1px solid var(--accent); color: var(--text-bright); padding: 12px 20px; border-radius: 4px; font-size: 14px; font-weight: 600; letter-spacing: 1px; box-shadow: 0 4px 20px rgba(0,0,0,0.5); transform: translateY(80px); opacity: 0; transition: all 0.3s cubic-bezier(0.34,1.56,0.64,1); z-index: 1000; }
165
  .toast.show { transform: translateY(0); opacity: 1; }
 
199
  <div class="upload-sub">or click to browse Β· .apk files only Β· max 200 MB</div>
200
  <input type="file" id="apkInput" accept=".apk">
201
  </div>
202
+ <!-- URL Upload -->
203
+ <div class="url-upload-wrap" id="urlUploadWrap">
204
+ <div class="url-upload-inner">
205
+ <span class="url-label">or load from URL</span>
206
+ <input class="url-input" type="text" id="apkUrlInput" placeholder="https://example.com/SuperCity.apk">
207
+ <button class="btn btn-secondary url-btn" onclick="uploadFromUrl()">⬇ Load URL</button>
208
+ </div>
209
+ </div>
210
+
211
  <div class="progress-wrap" id="progressWrap">
212
  <div class="progress-label" id="progressLabel">Uploading…</div>
213
  <div class="progress-bar-outer"><div class="progress-bar-inner" id="progressBar"></div></div>
 
384
  <div class="file-info">πŸ“¦ <span class="file-info-name">${file.name}</span>
385
  &nbsp;Β·&nbsp; ${characters.length} characters loaded &nbsp;Β·&nbsp; session: ${sessionToken.split('_')[0]}</div>`;
386
  document.getElementById('editorLayout').style.display = 'grid';
387
+ document.getElementById('urlUploadWrap').style.display = 'none';
388
  setStep(2);
389
  showToast(`βœ” Loaded ${characters.length} characters`);
390
  } else {
 
398
  xhr.send(form);
399
  }
400
 
401
+ function uploadFromUrl() {
402
+ const url = document.getElementById('apkUrlInput').value.trim();
403
+ if (!url) { showToast('Enter a URL first', true); return; }
404
+ if (!url.toLowerCase().endsWith('.apk')) { showToast('URL must point to a .apk file', true); return; }
405
+
406
+ const wrap = document.getElementById('progressWrap');
407
+ const bar = document.getElementById('progressBar');
408
+ const label = document.getElementById('progressLabel');
409
+ wrap.style.display = 'block';
410
+ bar.style.width = '10%';
411
+ label.textContent = 'Fetching APK from URL…';
412
+
413
+ fetch('/upload-url', {
414
+ method: 'POST',
415
+ headers: { 'Content-Type': 'application/json' },
416
+ body: JSON.stringify({ url }),
417
+ })
418
+ .then(res => {
419
+ bar.style.width = '80%';
420
+ label.textContent = 'Parsing characters…';
421
+ if (!res.ok) return res.json().then(e => { throw new Error(e.error); });
422
+ return res.json();
423
+ })
424
+ .then(data => {
425
+ bar.style.width = '100%';
426
+ sessionToken = data.token;
427
+ originalRaw = data.characters;
428
+ parseCharacters(data.characters);
429
+ wrap.style.display = 'none';
430
+ const fname = url.split('/').pop();
431
+ document.getElementById('fileInfoBar').style.display = 'flex';
432
+ document.getElementById('fileInfoBar').innerHTML = `
433
+ <div class="file-info">🌐 <span class="file-info-name">${fname}</span>
434
+ &nbsp;Β·&nbsp; ${characters.length} characters loaded &nbsp;Β·&nbsp; session: ${sessionToken.split('_')[0]}</div>`;
435
+ document.getElementById('editorLayout').style.display = 'grid';
436
+ document.getElementById('urlUploadWrap').style.display = 'none';
437
+ document.getElementById('uploadZone').style.display = 'none';
438
+ setStep(2);
439
+ showToast(`βœ” Loaded ${characters.length} characters from URL`);
440
+ })
441
+ .catch(err => {
442
+ wrap.style.display = 'none';
443
+ bar.style.width = '0%';
444
+ showToast('Error: ' + err.message, true);
445
+ });
446
+ }
447
+
448
  // ── PARSE ──────────────────────────────────────────────────────────
449
  function parseCharacters(raw) {
450
  characters = [];