JM Tech Power

jm-tech-power-official/Flash Download

A desktop download manager that opens up to 32 connections against one file and can send each of them out a different proxy route.

Public Uncategorized
Clone jm-tech-power-official/flash-download.jmproj
src/renderer/index.html
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="Content-Security-Policy"
      content="default-src 'none'; script-src 'self'; style-src 'self'; font-src 'self'; img-src 'self' data:; connect-src 'none'">
<title>Flash Download</title>
<link rel="stylesheet" href="fonts.css">
<link rel="stylesheet" href="styles.css">
</head>
<body>
<div id="app">

  <header id="titlebar">
    <span class="mark">
      <svg class="bolt" viewBox="0 0 24 24" aria-hidden="true"><path d="M13 2 4 14h6l-1 8 9-12h-6l1-8Z" fill="#FFB22C"/></svg>
      FLASH DOWNLOAD
    </span>
    <span class="chip chip-ok" id="route-health">—</span>
    <div class="spacer"></div>
    <div id="wctl">
      <button type="button" data-win="minimize" aria-label="Minimize">&#8212;</button>
      <button type="button" data-win="maximize" aria-label="Maximize">&#9634;</button>
      <button type="button" data-win="close" aria-label="Close">&#10005;</button>
    </div>
  </header>

  <div id="frame">
    <nav id="rail" aria-label="Sections">
      <p class="rail-lbl">Transfers</p>
      <button class="nav on" type="button" data-view="active"><span class="dot"></span><span class="lbl">Active</span><span class="ct" data-count="active">0</span></button>
      <button class="nav" type="button" data-view="queued"><span class="dot"></span><span class="lbl">Queued</span><span class="ct" data-count="queued">0</span></button>
      <button class="nav" type="button" data-view="paused"><span class="dot"></span><span class="lbl">Paused</span><span class="ct" data-count="paused">0</span></button>
      <button class="nav" type="button" data-view="done"><span class="dot"></span><span class="lbl">Finished</span><span class="ct" data-count="done">0</span></button>
      <button class="nav bad" type="button" data-view="failed"><span class="dot"></span><span class="lbl">Failed</span><span class="ct" data-count="failed">0</span></button>
      <p class="rail-lbl">Network</p>
      <button class="nav" type="button" data-view="routes"><span class="dot"></span><span class="lbl">Routes</span><span class="ct" data-count="routes">0</span></button>
      <button class="nav" type="button" data-view="settings"><span class="dot"></span><span class="lbl">Settings</span></button>
    </nav>

    <main id="main">
      <div id="capture">
        <div class="capture-in" id="capture-box">
          <svg width="13" height="13" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 3v12m0 0 4.5-4.5M12 15l-4.5-4.5M4 19h16" stroke="#5D718E" stroke-width="2.2" fill="none" stroke-linecap="round"/></svg>
          <input id="capture-url" type="text" spellcheck="false" placeholder="Paste a link to start" aria-label="Link to download">
        </div>
        <span class="kbd" id="capture-kbd">Ctrl+V to capture</span>
        <button class="btn btn-pri btn-sm" type="button" id="capture-start">Start</button>
        <h2 id="view-title" hidden>Routes</h2>
        <div class="dl-acts" id="view-actions" hidden></div>
      </div>

      <section class="view" id="view-list">
        <div id="list"></div>
        <div class="empty" id="empty">
          <svg width="26" height="26" viewBox="0 0 24 24" aria-hidden="true" style="opacity:.6"><path d="M12 3v12m0 0 4.5-4.5M12 15l-4.5-4.5M4 19h16" stroke="#5D718E" stroke-width="2" fill="none" stroke-linecap="round"/></svg>
          <h5 id="empty-title">Nothing downloading</h5>
          <p id="empty-body">Paste a link above, or copy one anywhere and Flash Download will offer it here.</p>
          <button class="btn btn-pri btn-sm" type="button" id="empty-action">Add a download</button>
        </div>
      </section>

      <section class="view view-pad" id="view-routes" hidden>
        <div class="tbl-wrap">
          <table class="tbl" id="routes-table">
            <thead><tr><th>Route</th><th>Type</th><th>Latency</th><th>Lanes now</th><th>Last error</th><th>State</th><th></th></tr></thead>
            <tbody></tbody>
          </table>
        </div>
        <p class="hint">A route is only used for downloads set to spread across the pool, or pinned to it. Three failures in a minute marks it degraded and moves its lanes elsewhere.</p>
      </section>

      <section class="view view-pad" id="view-settings" hidden>
        <div style="display:grid;gap:18px;max-width:560px">
          <div>
            <label class="fl">Default connections per download</label>
            <div class="steps" id="set-connections" role="radiogroup" aria-label="Default connections"></div>
            <p class="hint">Applied to new downloads. Servers that refuse range requests always use one.</p>
          </div>
          <div class="twocol">
            <div>
              <label class="fl" for="set-concurrent">Downloads at once</label>
              <input class="field m" id="set-concurrent" type="number" min="1" max="10">
            </div>
            <div>
              <label class="fl" for="set-limit">Speed limit</label>
              <input class="field m" id="set-limit" type="text" placeholder="unlimited">
              <p class="hint">A number in MB/s, or <span class="m">unlimited</span>. Shared across all connections.</p>
            </div>
          </div>
          <div>
            <label class="fl" for="set-dir">Save downloads to</label>
            <div class="pickrow">
              <input class="field m" id="set-dir" readonly>
              <button class="btn btn-sm" type="button" id="set-dir-pick">Choose…</button>
            </div>
          </div>
          <div style="display:grid;gap:10px">
            <label class="tg" for="set-verify"><input type="checkbox" id="set-verify"><i></i>Verify checksum after stitching</label>
            <label class="tg" for="set-clip"><input type="checkbox" id="set-clip"><i></i>Offer links copied to the clipboard</label>
            <label class="tg" for="set-drop"><input type="checkbox" id="set-drop"><i></i>Drop a route after three failures in a minute</label>
          </div>
        </div>
      </section>

      <footer id="strip"></footer>
    </main>

    <aside id="inspector"></aside>
  </div>
</div>

<!-- Add a download -->
<dialog id="add-dialog">
  <form class="dialog" method="dialog" id="add-form">
    <div class="dialog-h">
      <svg class="bolt" viewBox="0 0 24 24" aria-hidden="true"><path d="M13 2 4 14h6l-1 8 9-12h-6l1-8Z" fill="#FFB22C"/></svg>
      <strong>Add a download</strong>
      <span class="chip" id="add-probe" style="margin-left:auto">Checking…</span>
    </div>
    <div class="dialog-b">
      <div>
        <label class="fl" for="add-url">Link</label>
        <input class="field m" id="add-url" type="text" spellcheck="false" required>
        <p class="hint" id="add-hint"></p>
      </div>
      <div class="twocol">
        <div><label class="fl" for="add-name">Save as</label><input class="field" id="add-name" type="text"></div>
        <div><label class="fl" for="add-dir">Folder</label>
          <div class="pickrow">
            <input class="field m" id="add-dir" readonly><button class="btn btn-sm" type="button" id="add-dir-pick">…</button>
          </div>
        </div>
      </div>
      <div>
        <label class="fl">Connections</label>
        <div class="steps" id="add-connections" role="radiogroup" aria-label="Connections"></div>
        <div class="lanes compact" id="add-preview" style="margin-top:10px"></div>
        <p class="hint" id="add-preview-note"></p>
      </div>
      <div><label class="fl" for="add-route">Route</label><select class="field" id="add-route"></select></div>
      <label class="tg" for="add-verify"><input type="checkbox" id="add-verify"><i></i>Verify SHA256 after stitching</label>
    </div>
    <div class="dialog-f">
      <button class="btn btn-ghost" type="button" value="cancel" id="add-cancel">Cancel</button>
      <button class="btn" type="button" id="add-queue">Add to queue</button>
      <button class="btn btn-pri" type="submit" id="add-start">Start now</button>
    </div>
  </form>
</dialog>

<!-- Add a route -->
<dialog id="route-dialog">
  <form class="dialog" method="dialog" id="route-form">
    <div class="dialog-h"><strong>Add a route</strong></div>
    <div class="dialog-b">
      <div class="twocol">
        <div><label class="fl" for="rt-label">Name</label><input class="field" id="rt-label" placeholder="fra-1"></div>
        <div><label class="fl" for="rt-type">Type</label>
          <select class="field" id="rt-type"><option value="socks5">SOCKS5</option><option value="http">HTTP</option><option value="socks4">SOCKS4</option></select>
        </div>
      </div>
      <div class="twocol">
        <div><label class="fl" for="rt-host">Host</label><input class="field m" id="rt-host" placeholder="203.0.113.9" required></div>
        <div><label class="fl" for="rt-port">Port</label><input class="field m" id="rt-port" type="number" min="1" max="65535" placeholder="1080" required></div>
      </div>
      <div class="twocol">
        <div><label class="fl" for="rt-user">Username</label><input class="field" id="rt-user" autocomplete="off"></div>
        <div><label class="fl" for="rt-pass">Password</label><input class="field" id="rt-pass" type="password" autocomplete="off"></div>
      </div>
      <p class="hint">Flash Download tests the route as soon as you add it, and shows the latency in the pool.</p>
    </div>
    <div class="dialog-f">
      <button class="btn btn-ghost" type="button" id="rt-cancel">Cancel</button>
      <button class="btn btn-pri" type="submit">Add route</button>
    </div>
  </form>
</dialog>

<div id="menu" hidden></div>
<div id="toasts"></div>

<script src="app.js"></script>
</body>
</html>