diff options
| author | Ken D'Ambrosio <ken@jots.org> | 2026-05-12 14:45:00 +0000 |
|---|---|---|
| committer | Ken D'Ambrosio <ken@jots.org> | 2026-05-12 14:45:00 +0000 |
| commit | b47fdda4fe1bf6fe90d0ba30eedac435dde7c034 (patch) | |
| tree | 81f1921bedaf9e86e65d511c6bacbddd4697c7df /app.rb | |
| parent | 67a19fed3ff7ff9a40d489863fcef432cdba0913 (diff) | |
Add photo counts, EXIF details, video duration badges, slideshow launcher UI
- Album cards show recursive photo count (bubbles up through sub-albums).
- Lightbox info panel shows camera, aperture, shutter speed, and ISO;
update.rb now extracts and stores these EXIF fields.
- Video thumbnail cards show a duration badge (e.g. "1:23").
- Slideshow launcher redesigned: button on its own line, with Shuffle /
Full screen / Interval options on a second line, all inside a rounded
border to make the grouping clear.
- Fixed album-actions alignment so Interval sits level with the checkboxes.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Diffstat (limited to 'app.rb')
| -rw-r--r-- | app.rb | 30 |
1 files changed, 30 insertions, 0 deletions
@@ -96,6 +96,11 @@ helpers do 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'], } end @@ -118,11 +123,36 @@ helpers do name: name, title: sub_data['title'] || name, cover: album_cover(sub_dir, sub_data), + count: media_count(sub_dir, sub_data), } end data['sort_reverse'] ? albums.reverse : albums end + def media_count(dir, data) + files = data['files'] || {} + direct = Dir.children(dir) + .count { |n| MEDIA_EXTS.include?(File.extname(n).downcase.delete_prefix('.')) && + (admin? || (files[n] || {}).fetch('visible', true)) } + sub_total = Dir.children(dir) + .select { |n| !n.start_with?('.') && File.directory?(File.join(dir, n)) } + .sum do |n| + sub_dir = File.join(dir, n) + sub_data = load_album(sub_dir) + next 0 if sub_data['visible'] == false && !admin? + media_count(sub_dir, sub_data) + end + direct + sub_total + end + + def format_duration(secs) + return nil unless secs + s = secs.to_i + h, s = s.divmod(3600) + m, s = s.divmod(60) + h > 0 ? format('%d:%02d:%02d', h, m, s) : format('%d:%02d', m, s) + end + def album_cover(dir, data) cover = data['cover'] return cover if cover && cover != '__random__' && File.exist?(File.join(dir, cover)) |
