summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKen D'Ambrosio <ken@jots.org>2026-05-14 22:59:59 +0000
committerKen D'Ambrosio <ken@jots.org>2026-05-14 22:59:59 +0000
commitc76ea393777897e0c367e186d1a3b243193d8377 (patch)
treeb922795d65bcbea171ef6c2ddf6b3c80881123d2
parent6acd47c1ca27d705afe88b292a55a5170c038d2e (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.rb28
-rw-r--r--public/css/style.css8
-rw-r--r--scripts/update.rb13
-rw-r--r--views/admin/album.erb7
-rw-r--r--views/album.erb3
5 files changed, 39 insertions, 20 deletions
diff --git a/app.rb b/app.rb
index af18d44..ff7740c 100644
--- a/app.rb
+++ b/app.rb
@@ -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>