feat: blurred letterbox, portrait pairs, overlay metadata, button fixes

- Letterbox: extend edge pixels outward with blur + fade to solid color
- Portrait: detect and pair portraits side-by-side, fallback to solo
- Metadata: add overlay mode (corner badge), time field, custom date/time
  format strings (strftime), font size 1.5x, region-aware for pairs
- Buttons: swap G9/G10 to match physical layout, double-press random
  button for deep sleep, SLP indicator drawn before sleep
- Boot: remove redundant 'Loading photos' screen (saves 17s refresh)

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-08-03 15:53:06 -04:00
parent 392061bfa0
commit fe20841d9e
13 changed files with 515 additions and 72 deletions

View File

@@ -135,16 +135,31 @@ async function renderDisplay(el) {
<h2>Metadata Overlay</h2>
<ul class="checkbox-list">
<li><input type="checkbox" data-flag="1" ${flags&1?'checked':''}><span>Date</span></li>
<li><input type="checkbox" data-flag="32" ${flags&32?'checked':''}><span>Time</span></li>
<li><input type="checkbox" data-flag="2" ${flags&2?'checked':''}><span>Location</span></li>
<li><input type="checkbox" data-flag="4" ${flags&4?'checked':''}><span>People</span></li>
<li><input type="checkbox" data-flag="8" ${flags&8?'checked':''}><span>Album</span></li>
<li><input type="checkbox" data-flag="16" ${flags&16?'checked':''}><span>Camera</span></li>
</ul>
<div class="field">
<label>Position</label>
<label>Date Format</label>
<input type="text" id="dateFmt" value="${settings.date_fmt || '%Y-%m-%d'}" placeholder="%Y-%m-%d">
<small>strftime: %Y=year %m=month %d=day %b=Mon %B=Month</small>
</div>
<div class="field">
<label>Time Format</label>
<input type="text" id="timeFmt" value="${settings.time_fmt || '%H:%M:%S'}" placeholder="%H:%M:%S">
<small>strftime: %H=24h %I=12h %M=min %S=sec %p=AM/PM</small>
</div>
<div class="field">
<label>Style &amp; Position</label>
<select id="metaPos">
<option value="0" ${settings.meta_pos===0?'selected':''}>Bottom</option>
<option value="1" ${settings.meta_pos===1?'selected':''}>Top</option>
<option value="0" ${settings.meta_pos===0?'selected':''}>Caption - Bottom</option>
<option value="1" ${settings.meta_pos===1?'selected':''}>Caption - Top</option>
<option value="2" ${settings.meta_pos===2?'selected':''}>Overlay - Top Left</option>
<option value="3" ${settings.meta_pos===3?'selected':''}>Overlay - Top Right</option>
<option value="4" ${settings.meta_pos===4?'selected':''}>Overlay - Bottom Left</option>
<option value="5" ${settings.meta_pos===5?'selected':''}>Overlay - Bottom Right</option>
</select>
</div>
</div>
@@ -155,7 +170,9 @@ async function renderDisplay(el) {
await api('/api/settings', { method: 'POST', body: JSON.stringify({
img_quality: parseInt(document.getElementById('imgQuality').value),
meta_flags: flags,
meta_pos: parseInt(document.getElementById('metaPos').value)
meta_pos: parseInt(document.getElementById('metaPos').value),
date_fmt: document.getElementById('dateFmt').value,
time_fmt: document.getElementById('timeFmt').value
})});
toast('Display settings saved');
};