diff options
| author | Ken D'Ambrosio <ken@jots.org> | 2026-05-14 22:59:59 +0000 |
|---|---|---|
| committer | Ken D'Ambrosio <ken@jots.org> | 2026-05-14 22:59:59 +0000 |
| commit | c76ea393777897e0c367e186d1a3b243193d8377 (patch) | |
| tree | b922795d65bcbea171ef6c2ddf6b3c80881123d2 | |
| parent | 6acd47c1ca27d705afe88b292a55a5170c038d2e (diff) | |
Hide transcoded originals from non-admins; mark them visually for admins
update.rb records transcoded_to in album.json (even on re-runs where
the MP4 already exists) so the marker survives across scans.
app.rb filters files with transcoded_to from non-admin views.
album.erb renders them greyed-out with an amber "⚠ original" badge in
admin mode. admin/album.erb marks the edit-table row and shows the
target filename under the original.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
| -rw-r--r-- | app.rb | 28 | ||||
| -rw-r--r-- | public/css/style.css | 8 | ||||
| -rw-r--r-- | scripts/update.rb | 13 | ||||
| -rw-r--r-- | views/admin/album.erb | 7 | ||||
| -rw-r--r-- | views/album.erb | 3 |
5 files changed, 39 insertions, 20 deletions
@@ -90,20 +90,22 @@ helpers do entries = files.filter_map do |name| meta = (data['files'] || {})[name] || {} next if meta['visible'] == false && !admin? + next if meta['transcoded_to'] && !admin? { - name: name, - title: meta['title'] || name, - caption: meta['caption'], - visible: meta.fetch('visible', true), - type: media_type_for(name), - taken_at: meta['taken_at'], - width: meta['width'], - height: meta['height'], - duration: meta['duration'], - camera: meta['camera'], - aperture: meta['aperture'], - shutter: meta['shutter'], - iso: meta['iso'], + name: name, + title: meta['title'] || name, + caption: meta['caption'], + visible: meta.fetch('visible', true), + type: media_type_for(name), + taken_at: meta['taken_at'], + width: meta['width'], + height: meta['height'], + duration: meta['duration'], + camera: meta['camera'], + aperture: meta['aperture'], + shutter: meta['shutter'], + iso: meta['iso'], + transcoded_to: meta['transcoded_to'], } end diff --git a/public/css/style.css b/public/css/style.css index 41dfd0a..062b187 100644 --- a/public/css/style.css +++ b/public/css/style.css @@ -379,6 +379,14 @@ legend { padding: 0 8px; color: var(--text-dim); font-size: .85rem; } .files-table { font-size: .78rem; } } +/* ── Unplayable originals (admin-only) ─────────────────────────────────── */ +.unplayable-original { opacity: .45; } +.unplayable-badge { position: absolute; top: 6px; left: 6px; background: rgba(0,0,0,.7); + color: #f0a500; font-size: .68rem; padding: 2px 5px; + border-radius: 3px; pointer-events: none; } +tr.original-file td { opacity: .5; } +.transcoded-label { display: block; font-size: .72rem; color: #c07000; font-style: italic; margin-top: 2px; } + /* ── Admin delete ──────────────────────────────────────────────────────── */ .delete-cell { text-align: center; } .delete-check { accent-color: #c0392b; width: 16px; height: 16px; cursor: pointer; } diff --git a/scripts/update.rb b/scripts/update.rb index a4969d3..9953505 100644 --- a/scripts/update.rb +++ b/scripts/update.rb @@ -64,16 +64,21 @@ def process_dir(dir) .each do |name| base = File.basename(name, '.*') target = "#{base}.mp4" - next if current.include?(target) # already transcoded on a previous run + if current.include?(target) + # MP4 already exists — just ensure the marker is recorded + data['files'][name] ||= {} + data['files'][name]['transcoded_to'] = target + next + end full = File.join(dir, name) dest = File.join(dir, target) puts " Transcoding: #{name} → #{target}" transcode_to_mp4(full, dest) if File.exist?(dest) data['files'][name] ||= {} - data['files'][name]['visible'] ||= false # hide original; admin can override - current << target # include in processing pass below - puts " → done (original hidden)" + data['files'][name]['transcoded_to'] = target + current << target + puts " → done" else warn " Transcode failed: #{name}" end diff --git a/views/admin/album.erb b/views/admin/album.erb index f28d515..15a043f 100644 --- a/views/admin/album.erb +++ b/views/admin/album.erb @@ -70,9 +70,12 @@ <% @files.each do |name| %> <% meta = (@data['files'] || {})[name] || {} %> <% file_rel = @rel.empty? ? name : "#{@rel}/#{name}" %> - <tr> + <tr<%= ' class="original-file"' if meta['transcoded_to'] %>> <td><img src="/thumb/<%= file_rel %>" width="60" height="60" loading="lazy" style="object-fit:cover"></td> - <td class="filename"><code><%= name %></code></td> + <td class="filename"> + <code><%= name %></code> + <% if meta['transcoded_to'] %><span class="transcoded-label">→ <%= meta['transcoded_to'] %></span><% end %> + </td> <td><input type="text" name="file_caption[<%= name %>]" value="<%= ERB::Util.html_escape(meta['caption'].to_s) %>" placeholder="caption…"></td> <td class="visible-cell"> <input type="hidden" name="file_visible[<%= name %>]" value="0"> diff --git a/views/album.erb b/views/album.erb index 8577bdb..64bf763 100644 --- a/views/album.erb +++ b/views/album.erb @@ -54,7 +54,7 @@ <div class="grid" id="photo-grid"> <% @entries.each_with_index do |e, i| %> <% file_rel = @rel.empty? ? e[:name] : "#{@rel}/#{e[:name]}" %> - <div class="card media-card<%= ' hidden-item' unless e[:visible] %>" + <div class="card media-card<%= ' hidden-item' unless e[:visible] %><%= ' unplayable-original' if e[:transcoded_to] %>" data-index="<%= i %>" data-type="<%= e[:type] %>" data-src="/media/<%= file_rel %>" @@ -66,6 +66,7 @@ <% if e[:type] == :video %><span class="type-badge video-badge">▶</span><% end %> <% if e[:type] == :video && e[:duration] %><span class="duration-badge"><%= format_duration(e[:duration]) %></span><% end %> <% if e[:type] == :audio %><span class="type-badge audio-badge">♪</span><% end %> + <% if e[:transcoded_to] %><span class="unplayable-badge">⚠ original</span><% end %> </div> <% if e[:caption] %> <div class="card-meta"><p class="card-caption"><%= e[:caption] %></p></div> |
