feat: auto-provision heatmap API key + move banner below sections
The heatmap iframe now requests an Immich API key via /api/api-keys (asset.read, asset.view) on first load, caches it in localStorage, and passes it via ?apiKey= so the user doesn't have to paste one. Banner moved to the bottom of the /explore scroll container, below People and Places. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
7be768e2db
commit
b4e801e17f
|
|
@ -910,7 +910,38 @@
|
|||
}[c]));
|
||||
}
|
||||
|
||||
function injectHeatmapBanner(container) {
|
||||
// Get (or create) an Immich API key for the heatmap iframe so the user
|
||||
// isn't prompted to paste one. Cached in this origin's localStorage.
|
||||
async function getHeatmapApiKey() {
|
||||
const cached = localStorage.getItem('ls-heatmap-api-key');
|
||||
if (cached) return cached;
|
||||
try {
|
||||
const r = await fetch('/api/api-keys', {
|
||||
method: 'POST',
|
||||
headers: getAuthHeaders(),
|
||||
credentials: 'include',
|
||||
body: JSON.stringify({
|
||||
name: 'Heatmap iframe (auto)',
|
||||
permissions: ['asset.read', 'asset.view']
|
||||
})
|
||||
});
|
||||
if (!r.ok) {
|
||||
console.warn('[live-search] api-key create failed', r.status);
|
||||
return null;
|
||||
}
|
||||
const j = await r.json();
|
||||
const secret = j.secret || (j.apiKey && j.apiKey.secret);
|
||||
if (secret) {
|
||||
localStorage.setItem('ls-heatmap-api-key', secret);
|
||||
return secret;
|
||||
}
|
||||
} catch (e) {
|
||||
console.warn('[live-search] api-key create error', e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
async function injectHeatmapBanner(container) {
|
||||
if (container.querySelector('.ls-heatmap-banner')) return;
|
||||
const banner = document.createElement('div');
|
||||
banner.className = 'ls-heatmap-banner';
|
||||
|
|
@ -920,16 +951,22 @@
|
|||
<button type="button">Collapse</button>
|
||||
</div>
|
||||
<iframe class="ls-heatmap-frame"
|
||||
src="${HEATMAP_URL}"
|
||||
referrerpolicy="no-referrer"
|
||||
allow="geolocation"></iframe>
|
||||
`;
|
||||
const iframe = banner.querySelector('iframe');
|
||||
const btn = banner.querySelector('button');
|
||||
btn.addEventListener('click', () => {
|
||||
banner.classList.toggle('collapsed');
|
||||
btn.textContent = banner.classList.contains('collapsed') ? 'Expand' : 'Collapse';
|
||||
});
|
||||
container.insertBefore(banner, container.firstChild);
|
||||
// Append at the END so it lands below People + Places sections.
|
||||
container.appendChild(banner);
|
||||
|
||||
// Resolve API key then set iframe src. The heatmap app reads ?apiKey
|
||||
// and seeds its own localStorage, skipping the login prompt.
|
||||
const key = await getHeatmapApiKey();
|
||||
iframe.src = HEATMAP_URL + (key ? '?apiKey=' + encodeURIComponent(key) : '');
|
||||
}
|
||||
|
||||
async function enhanceSection(section, kind) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue