Skip to content

Commit 453cc96

Browse files
MrChengLenclaude
andcommitted
feat(ui): drop-zone hint mode separation (convert vs compress)
The homepage drop-zone advertised "Supported: HEIC · JPG · PNG · WebP · BMP · TIFF · GIF · DOCX · PDF · TXT · MD · XLSX · CSV · JSON · MP4 · MOV · AVI · MKV · WebM · MP3 · WAV · FLAC · OGG · M4A" regardless of the mode toggle, even though the compress path only accepts a much narrower subset (JPG/PNG/WebP/TIFF + MP4/AVI/MOV/MKV/WebM). Users would upload an MP3 in compress mode, see a 422, and bounce. Adds two side-by-side hint blocks in index.html (`supported-convert`, `supported-compress`) and toggles `hidden` from app.js::setMode based on the active mode. Server-side validation is unchanged — this is purely a UI affordance to set expectations correctly before upload. New tests/test_homepage_drop_zone_modes.py asserts both blocks are present with the expected `hidden` defaults so a future template refactor can't silently revert this. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent ab796ef commit 453cc96

3 files changed

Lines changed: 54 additions & 1 deletion

File tree

app/static/js/app.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,17 @@ function setMode(mode) {
120120
compressMode = 'quality';
121121
}
122122

123+
// Drop-zone help text differs per mode: convert covers all source formats,
124+
// compress is limited to JPG/PNG/WebP/TIFF + MP4/AVI/MOV/MKV/WebM. The
125+
// server rejects mismatches anyway, but showing the right list up-front
126+
// keeps users from uploading e.g. an MP3 only to see a 422.
127+
const supConv = document.getElementById('supported-convert');
128+
const supComp = document.getElementById('supported-compress');
129+
if (supConv && supComp) {
130+
supConv.classList.toggle('hidden', mode !== 'convert');
131+
supComp.classList.toggle('hidden', mode !== 'compress');
132+
}
133+
123134
updateConvertOptionsVisibility();
124135
renderFileList();
125136
updateQualityVisibility();

app/templates/index.html

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,11 +47,15 @@ <h1 class="text-h-page text-ink">{{ _('Convert & Compress Files') }}</h1>
4747
</svg>
4848
<p class="text-gray-400">{{ _('Drag & drop your files here') }}</p>
4949
<p class="text-xs text-gray-600">{{ _('or click to browse (multi-file supported)') }}</p>
50-
<p class="text-xs text-gray-700 mt-2">
50+
<p id="supported-convert" class="text-xs text-gray-700 mt-2">
5151
{{ _('Supported: HEIC · JPG · PNG · WebP · BMP · TIFF · GIF') }}<br>
5252
{{ _('DOCX · PDF · TXT · MD · XLSX · CSV · JSON') }}<br>
5353
{{ _('MP4 · MOV · AVI · MKV · WebM · MP3 · WAV · FLAC · OGG · M4A') }}
5454
</p>
55+
<p id="supported-compress" class="hidden text-xs text-gray-700 mt-2">
56+
{{ _('Supported: JPG · PNG · WebP · TIFF') }}<br>
57+
{{ _('MP4 · MOV · AVI · MKV · WebM') }}
58+
</p>
5559
</div>
5660

5761
<div id="drop-selected" class="hidden space-y-2">
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# SPDX-License-Identifier: AGPL-3.0-or-later
2+
"""Drop-zone help text must carry both mode-specific blocks.
3+
4+
The convert and compress modes accept different input formats — convert
5+
covers all source formats including audio and documents, while compress
6+
only handles JPG/PNG/WebP/TIFF and MP4/AVI/MOV/MKV/WebM. The homepage
7+
renders both lists side-by-side; `app/static/js/app.js::setMode()`
8+
toggles their visibility. If a future refactor drops one of the two
9+
elements, the user sees a stale or empty caption — this test fails first.
10+
"""
11+
12+
from __future__ import annotations
13+
14+
15+
def test_homepage_carries_both_supported_lists(client):
16+
res = client.get("/")
17+
assert res.status_code == 200
18+
html = res.text
19+
assert 'id="supported-convert"' in html, "convert-mode caption missing"
20+
assert 'id="supported-compress"' in html, "compress-mode caption missing"
21+
22+
23+
def test_compress_caption_lists_only_image_and_video_formats(client):
24+
"""Compress mode must NOT advertise audio, document, or spreadsheet formats —
25+
those have no compressor. Adding them back would mislead the user."""
26+
res = client.get("/")
27+
assert res.status_code == 200
28+
html = res.text
29+
30+
start = html.find('id="supported-compress"')
31+
assert start != -1
32+
end = html.find("</p>", start)
33+
block = html[start:end]
34+
35+
for forbidden in ["MP3", "WAV", "FLAC", "OGG", "M4A", "DOCX", "PDF", "XLSX", "CSV"]:
36+
assert forbidden not in block, (
37+
f"compress-mode caption advertises {forbidden} but no compressor exists for it"
38+
)

0 commit comments

Comments
 (0)