feat(ui): add reusable warpbox wrapper and improve upload documentation

Updated static/popups/cli.html with clearer upload instructions, added a reusable warpbox shell wrapper with install steps and a function for printing the share URL, making the command more accessible and portable.
This commit is contained in:
2026-04-29 11:51:04 +03:00
parent fb80f11e72
commit ac6e8c591b
2 changed files with 130 additions and 48 deletions

View File

@@ -1,19 +1,26 @@
<h3>Upload from a terminal</h3> <h3><u>Upload Files from Terminal</u></h3>
<p>WarpBox accepts normal multipart uploads at <code>/upload</code>. The server returns JSON with a <code>box_url</code> you can open or share.</p>
<pre class="code-block"><code>curl \
-F 'files=@./my-file.zip' \
-F 'retention=1h' \
{{ origin }}/upload
</code></pre>
<h4>Reusable shell wrapper</h4> <p>WarpBox accepts normal multipart uploads at <strong><u>/upload</u></strong>. The server returns JSON with a <code>box_url</code> you can open or share.</p>
<p>This version is small, portable, and works well as a personal <code>warpbox</code> command.</p>
<pre class="code-block"><code>#!/usr/bin/env bash <div style="background:#ffffff; border-top:1px solid #808080; border-left:1px solid #808080; border-right:1px solid #ffffff; border-bottom:1px solid #ffffff; padding:10px; margin:10px 0;">
<p><strong>> Quick Upload:</strong> Use this command to upload a single file:</p>
<pre class="code-block"><code>curl \
-F 'files=@./my-file.zip' \
-F 'retention=1h' \
{{ origin }}/upload</code></pre>
</div>
<h4><u>Reusable Shell Wrapper</u></h4>
<p>This version is small, portable, and works well as a personal <strong><u>warpbox</u></strong> command.</p>
<div style="background:#ffffff; border-top:1px solid #808080; border-left:1px solid #808080; border-right:1px solid #ffffff; border-bottom:1px solid #ffffff; padding:10px; margin:10px 0;">
<p><strong>> Save this as a file</strong> called <strong><u>warpbox</u></strong> and make it executable to use it as a command:</p>
<pre class="code-block"><code>#!/usr/bin/env bash
set -euo pipefail set -euo pipefail
if [ "$#" -lt 1 ]; then if [ "$#" -lt 1 ]; then
echo "Usage: warpbox FILE [FILE ...]" >&amp;2 echo "Usage: warpbox FILE [FILE ...]" >&2
exit 64 exit 64
fi fi
endpoint="${WARPBOX_URL:-{{ origin }}}/upload" endpoint="${WARPBOX_URL:-{{ origin }}}/upload"
@@ -21,42 +28,55 @@ retention="${WARPBOX_RETENTION:-1h}"
args=(-F "retention=${retention}") args=(-F "retention=${retention}")
for file in "$@"; do for file in "$@"; do
args+=(-F "files=@${file}") args+=(-F "files=@${file}")
done done
curl --fail-with-body "${args[@]}" "${endpoint}" curl --fail-with-body "${args[@]}" "${endpoint}"</code></pre>
</code></pre> </div>
<h4>Install it</h4> <h4><u>Install the Command</u></h4>
<p>Put the wrapper somewhere on your <code>PATH</code>, then call it with one or more files.</p> <p>Put the wrapper somewhere on your <code>PATH</code>, then call it with one or more files.</p>
<pre class="code-block"><code>chmod +x ./warpbox
sudo install -m 755 ./warpbox /usr/local/bin/warpbox
warpbox ./photo.png ./archive.zip
</code></pre>
<h4>Print only the share URL</h4> <div style="background:#ffffff; border-top:1px solid #808080; border-left:1px solid #808080; border-right:1px solid #ffffff; border-bottom:1px solid #ffffff; padding:10px; margin:10px 0;">
<p>If <code>jq</code> is installed, this variant extracts the returned link and expands it to a full URL.</p> <p><strong>> Install Steps:</strong></p>
<pre class="code-block"><code>warpbox() { <ol>
local endpoint="${WARPBOX_URL:-{{ origin }}}/upload" <li>Make the script executable: <code>chmod +x ./warpbox</code></li>
local retention="${WARPBOX_RETENTION:-1h}" <li>Install to system path: <code>sudo install -m 755 ./warpbox /usr/local/bin/warpbox</code></li>
local args=(-F "retention=${retention}") <li>Use it: <code>warpbox ./photo.png ./archive.zip</code></li>
</ol>
</div>
for file in "$@"; do <h4><u>Print Only the Share URL</u></h4>
args+=(-F "files=@${file}") <p>If <strong><u>jq</u></strong> is installed, this variant extracts the returned link and expands it to a full URL.</p>
done
curl --fail-with-body -sS "${args[@]}" "${endpoint}" | <div style="background:#ffffff; border-top:1px solid #808080; border-left:1px solid #808080; border-right:1px solid #ffffff; border-bottom:1px solid #ffffff; padding:10px; margin:10px 0;">
jq -r --arg origin "${WARPBOX_URL:-{{ origin }}}" '"\($origin)\(.box_url)"' <p><strong>> Function Version:</strong> Add this function to your shell profile (like <strong><u>~/.bashrc</u></strong> or <strong><u>~/.zshrc</u></strong>):</p>
} <pre class="code-block"><code>warpbox() {
</code></pre> local endpoint="${WARPBOX_URL:-{{ origin }}}/upload"
local retention="${WARPBOX_RETENTION:-1h}"
local args=(-F "retention=${retention}")
<h4>Add password or retention</h4> for file in "$@"; do
<p>You can keep the wrapper simple and pass fixed options through environment variables or extra form fields.</p> args+=(-F "files=@${file}")
<pre class="code-block"><code>WARPBOX_RETENTION=24h warpbox ./release.tar.gz done
curl \ curl --fail-with-body -sS "${args[@]}" "${endpoint}" |
-F 'files=@./private.zip' \ jq -r --arg origin "${WARPBOX_URL:-{{ origin }}}" '"\($origin)\(.box_url)"'
-F 'retention=1h' \ }</code></pre>
-F 'password=correct-horse-battery-staple' \ </div>
{{ origin }}/upload
</code></pre> <h4><u>Add Password or Retention</u></h4>
<p>You can keep the wrapper simple and pass fixed options through <strong><u>environment variables</u></strong> or extra form fields.</p>
<div style="background:#ffffff; border-top:1px solid #808080; border-left:1px solid #808080; border-right:1px solid #ffffff; border-bottom:1px solid #ffffff; padding:10px; margin:10px 0;">
<p><strong>> Examples:</strong></p>
<p>Set <u>retention period</u> for one upload:</p>
<pre class="code-block"><code>WARPBOX_RETENTION=24h warpbox ./release.tar.gz</code></pre>
<p>Add <u>password protection</u> to a specific upload:</p>
<pre class="code-block"><code>curl \
-F 'files=@./private.zip' \
-F 'retention=1h' \
-F 'password=correct-horse-battery-staple' \
{{ origin }}/upload</code></pre>
</div>

View File

@@ -1,17 +1,79 @@
<h3>Help &amp; FAQ</h3> <h3><u>Help &amp; FAQ</u></h3>
<div style="background:#ffffff; border-top:1px solid #808080; border-left:1px solid #808080; border-right:1px solid #ffffff; border-bottom:1px solid #ffffff; padding:10px; margin:0 0 12px;">
<p><strong>> Fast path:</strong> Add files, choose any Box Options you need, then start the upload. WarpBox creates one share link for the whole box.</p>
<ol>
<li><strong>Add files:</strong> drag files onto the window or use <span class="kbd">Ctrl</span> + <span class="kbd">O</span>.</li>
<li><strong>Check options:</strong> set expiry, password, ZIP download, or one-time download before uploading.</li>
<li><strong>Upload:</strong> press <span class="kbd">Ctrl</span> + <span class="kbd">U</span> or use the Upload button.</li>
<li><strong>Share:</strong> copy the returned link with <span class="kbd">Ctrl</span> + <span class="kbd">L</span>.</li>
</ol>
</div>
<section class="shortcut-section"> <section class="shortcut-section">
<h4>Keyboard shortcuts</h4> <h4><u>Keyboard Shortcuts</u></h4>
<ul class="shortcut-list"> <ul class="shortcut-list">
<li><span><span class="kbd">Ctrl</span> + <span class="kbd">O</span></span><span> Browse for files.</span></li> <li><span><span class="kbd">Ctrl</span> + <span class="kbd">O</span></span><span> Browse for files.</span></li>
<li><span><span class="kbd">Ctrl</span> + <span class="kbd">U</span></span><span> Start the current upload.</span></li> <li><span><span class="kbd">Ctrl</span> + <span class="kbd">U</span></span><span> Start the current upload.</span></li>
<li><span><span class="kbd">Ctrl</span> + <span class="kbd">K</span></span><span> Copy the full cURL command.</span></li> <li><span><span class="kbd">Ctrl</span> + <span class="kbd">K</span></span><span> Copy the full cURL command.</span></li>
<li><span><span class="kbd">Ctrl</span> + <span class="kbd">L</span></span><span> Copy the share URL after upload.</span></li> <li><span><span class="kbd">Ctrl</span> + <span class="kbd">L</span></span><span> Copy the share URL after upload.</span></li>
<li><span><span class="kbd">F1</span></span><span> Open this window.</span></li> <li><span><span class="kbd">F1</span></span><span> Open this help window.</span></li>
<li><span><span class="kbd">Esc</span></span><span> Close menus and popups.</span></li> <li><span><span class="kbd">Esc</span></span><span> Close menus and popups.</span></li>
</ul> </ul>
</section> </section>
<h4><u>Common Questions</u></h4>
<div class="faq-list"> <div class="faq-list">
<div class="faq-item"><p><strong>Can I password protect uploads?</strong></p><p>Yes. Set a password in Box Options before starting the upload.</p></div> <div class="faq-item">
<div class="faq-item"><p><strong>What happens if one file fails?</strong></p><p>The failed row stays red, successful files remain available, and WarpBox marks the failed file in the manifest.</p></div> <p><strong>What is a box?</strong></p>
<div class="faq-item"><p><strong>Are all options server-backed?</strong></p><p>Expiry, password, ZIP download, and one-time download are sent to the backend. Notes like box name, custom slug, and API key mode are saved locally until backend support exists.</p></div> <p>A box is the temporary share page WarpBox creates after upload. It can contain one file or many files, plus the manifest that records upload status.</p>
</div>
<div class="faq-item">
<p><strong>Can I password protect uploads?</strong></p>
<p>Yes. Set a password in Box Options before starting the upload. Anyone opening the box must enter that password before downloading protected files.</p>
</div>
<div class="faq-item">
<p><strong>How does expiry work?</strong></p>
<p>The expiry value is sent with the upload as <code>retention</code>. After that period, the server may delete the box and its files according to the running WarpBox configuration.</p>
</div>
<div class="faq-item">
<p><strong>What does one-time download do?</strong></p>
<p>One-time download tells the backend to treat a file or box as burn-after-read. After a successful download, the link should no longer be reusable.</p>
</div>
<div class="faq-item">
<p><strong>Can people download everything at once?</strong></p>
<p>Enable ZIP download before uploading. When supported by the backend, the share page offers a single archive for the box.</p>
</div>
<div class="faq-item">
<p><strong>What happens if one file fails?</strong></p>
<p>The failed row stays red, successful files remain available, and WarpBox marks the failed file in the manifest so you can tell what needs another attempt.</p>
</div>
<div class="faq-item">
<p><strong>Can I upload from terminal or automation?</strong></p>
<p>Yes. Use the CLI help window for ready-made <code>curl</code>, shell, Node.js, Go, and Java examples. Copy command with <span class="kbd">Ctrl</span> + <span class="kbd">K</span>.</p>
</div>
<div class="faq-item">
<p><strong>Are all options server-backed?</strong></p>
<p>Expiry, password, ZIP download, and one-time download are sent to the backend. Box name, custom slug, and API key mode are saved locally until backend support exists.</p>
</div>
</div>
<h4><u>Troubleshooting</u></h4>
<div class="faq-list">
<div class="faq-item">
<p><strong>Upload button is disabled.</strong></p>
<p>Add at least one file, remove duplicates if prompted, and check Upload Limits for configured box and single-file limits.</p>
</div>
<div class="faq-item">
<p><strong>Copy failed.</strong></p>
<p>Some browsers block clipboard access outside secure contexts or direct user gestures. WarpBox shows a fallback text box so the link or command can be selected manually.</p>
</div>
<div class="faq-item">
<p><strong>Shared link opens but download fails.</strong></p>
<p>The box may be expired, consumed by one-time download, password-protected, or removed by server cleanup. Re-upload the file if the box is no longer available.</p>
</div>
<div class="faq-item">
<p><strong>Large file fails early.</strong></p>
<p>Check Upload Limits first. If the file is inside limits, retry on a stable connection or use the terminal upload flow so the exact server error is visible.</p>
</div>
</div> </div>