| <!doctype html> |
| <html lang="en"> |
| <head> |
| <meta charset="utf-8" /> |
| <meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover" /> |
| <title>DOTO — Temp Upload</title> |
|
|
| <link rel="stylesheet" href="/static/css/styles.css" /> |
| |
| <style> |
| @font-face { |
| font-family: "DOTO"; |
| src: local("DOTO"), local("Doto"), local("Doto-Bold"); |
| font-weight: 700; |
| font-style: normal; |
| } |
| |
| |
| .modal-overlay { |
| position: fixed; |
| inset: 0; |
| background: rgba(0,0,0,0.55); |
| display: none; |
| align-items: center; |
| justify-content: center; |
| z-index: 2000; |
| } |
| |
| .modal { |
| background: #fff; |
| border-radius: 14px; |
| width: 90%; |
| max-width: 480px; |
| padding: 0; |
| box-shadow: 0 10px 30px rgba(0,0,0,0.25); |
| transform: scale(0.8); |
| opacity: 0; |
| transition: all 0.3s ease-in-out; |
| overflow: hidden; |
| } |
| |
| .modal.show { |
| transform: scale(1); |
| opacity: 1; |
| } |
| |
| .modal header { |
| display: flex; |
| justify-content: space-between; |
| align-items: center; |
| padding: 12px 16px; |
| background: #f5f5f5; |
| font-weight: bold; |
| border-bottom: 1px solid #ddd; |
| } |
| |
| .modal header strong { |
| font-size: 1rem; |
| } |
| |
| #closeApi { |
| background: none; |
| border: none; |
| font-size: 1.2rem; |
| cursor: pointer; |
| color: #333; |
| } |
| |
| .modal-body { |
| padding: 16px; |
| font-size: 0.95rem; |
| } |
| |
| .modal-body p { |
| margin: 6px 0; |
| } |
| |
| .curl { |
| margin: 12px 0; |
| background: #f7f7f7; |
| border-radius: 6px; |
| padding: 10px; |
| position: relative; |
| } |
| |
| .curl pre { |
| white-space: pre-wrap; |
| word-wrap: break-word; |
| font-size: 0.85rem; |
| margin: 0 0 8px 0; |
| } |
| |
| .curl button { |
| position: absolute; |
| top: 8px; |
| right: 8px; |
| font-size: 0.8rem; |
| } |
| |
| .dev { |
| margin-top: 12px; |
| text-align: center; |
| } |
| |
| .dev strong { |
| color: #222; |
| } |
| |
| .dev .muted { |
| color: #666; |
| font-size: 0.8rem; |
| } |
| </style> |
| </head> |
| <body class="theme-light"> |
| <div class="app"> |
| <header class="topbar"> |
| <div class="brand">DOTO</div> |
| <div class="meta"> |
| <button id="apiBtn" class="icon-btn" title="API & Developer">/></button> |
| </div> |
| </header> |
|
|
| <main class="main"> |
| <section class="upload-card" id="uploadCard"> |
| <div class="placeholder" id="placeholder"> |
| <img src="/static/images/placeholder.gif" alt="placeholder" class="placeholder-gif"/> |
| <div class="placeholder-text"> |
| <strong>Drop a file or tap to upload</strong> |
| <small>Files expire ~3 hours • max 2GB</small> |
| </div> |
| <input id="fileInput" type="file" class="file-input" /> |
| </div> |
|
|
| <div class="preview" id="preview" hidden> |
| <div class="preview-left"> |
| <div id="previewThumb" class="preview-thumb"></div> |
| </div> |
| <div class="preview-right"> |
| <div id="previewName" class="filename"></div> |
| <div id="previewSize" class="filesize"></div> |
| <div class="progress-wrap"> |
| <progress id="uploadProgress" value="0" max="100"></progress> |
| <div id="progressText" class="progress-text"></div> |
| </div> |
| </div> |
| </div> |
| </section> |
|
|
| <section class="history" id="historySection"> |
| <div class="history-header"> |
| <strong>Recent uploads</strong> |
| <button id="clearHistory" class="link-btn">Clear</button> |
| </div> |
| <div id="historyList" class="history-list"></div> |
| </section> |
| </main> |
|
|
| <footer class="sticky-footer"> |
| <div class="left"> |
| <button id="uploadBtn" class="big-btn">Upload</button> |
| </div> |
| <div class="right actions"> |
| <button id="copyBtn" class="small-btn" title="Copy link">Copy</button> |
| <button id="viewBtn" class="small-btn" title="View">View</button> |
| <button id="dlBtn" class="small-btn" title="Download">Download</button> |
| </div> |
| </footer> |
| </div> |
|
|
| |
| <div id="apiModal" class="modal-overlay"> |
| <div class="modal"> |
| <header> |
| <strong>API & Developer</strong> |
| <button id="closeApi" class="icon-btn">✕</button> |
| </header> |
| <div class="modal-body"> |
| <p><strong>Version:</strong> <span id="apiVersion">{{ api_version }}</span></p> |
| <p><strong>Upload endpoint:</strong> <code>/api/upload</code></p> |
| <p><strong>Max size:</strong> <code>{{ max_bytes }} bytes</code></p> |
| <p><strong>Expiry:</strong> ~{{ expire_seconds }} seconds</p> |
| <div class="curl"> |
| <label>cURL example</label> |
| <pre id="curlExample">curl -X POST -F "file=@/path/to/file" https://your-space-url/api/upload</pre> |
| <button id="copyCurl" class="link-btn">Copy</button> |
| </div> |
| <hr/> |
| <div class="dev"> |
| <small>Made by <strong>Aditya Devarshi</strong></small><br/> |
| <small class="muted">Files are public to anyone with the link. Avoid sensitive uploads.</small> |
| </div> |
| </div> |
| </div> |
| </div> |
|
|
| <script> |
| |
| window.APP_CONFIG = { |
| API_VERSION: "{{ api_version }}", |
| MAX_BYTES: {{ max_bytes }}, |
| EXPIRE_SECONDS: {{ expire_seconds }} |
| } |
| |
| const apiBtn = document.getElementById("apiBtn"); |
| const apiModal = document.getElementById("apiModal"); |
| const closeApi = document.getElementById("closeApi"); |
| const copyCurl = document.getElementById("copyCurl"); |
| const curlExample = document.getElementById("curlExample"); |
| |
| |
| apiBtn.addEventListener("click", () => { |
| apiModal.style.display = "flex"; |
| requestAnimationFrame(() => { |
| apiModal.querySelector(".modal").classList.add("show"); |
| }); |
| }); |
| |
| |
| function closeModal() { |
| const modalCard = apiModal.querySelector(".modal"); |
| modalCard.classList.remove("show"); |
| setTimeout(() => { |
| apiModal.style.display = "none"; |
| }, 300); |
| } |
| |
| closeApi.addEventListener("click", closeModal); |
| apiModal.addEventListener("click", (e) => { |
| if (e.target === apiModal) closeModal(); |
| }); |
| |
| |
| copyCurl.addEventListener("click", () => { |
| navigator.clipboard.writeText(curlExample.innerText).then(() => { |
| copyCurl.innerText = "Copied!"; |
| setTimeout(() => (copyCurl.innerText = "Copy"), 1500); |
| }); |
| }); |
| </script> |
| <script src="/static/js/app.js"></script> |
| </body> |
| </html> |
|
|