feat: add settings view with capture toggle and blacklist management

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
adlee-was-taken
2026-04-12 12:25:25 -04:00
parent baf6416805
commit ff19faff03
3 changed files with 104 additions and 2 deletions

View File

@@ -0,0 +1,98 @@
/// Settings view — capture toggle, prompt style, and blacklist management.
import { sendMessage, navigate, escapeHtml } from '../popup';
import type { IdfotoSettings } from '../../shared/types';
export async function renderSettings(app: HTMLElement): Promise<void> {
app.innerHTML = '<div class="pad" style="text-align:center; padding-top:20px;"><span class="spinner"></span></div>';
// Load settings and blacklist in parallel
const [settingsResp, blacklistResp] = await Promise.all([
sendMessage({ type: 'get_settings' }),
sendMessage({ type: 'get_blacklist' }),
]);
const settings: IdfotoSettings = settingsResp.ok
? (settingsResp.data as { settings: IdfotoSettings }).settings
: { captureEnabled: false, captureStyle: 'bar' };
const blacklist: string[] = blacklistResp.ok
? (blacklistResp.data as { blacklist: string[] }).blacklist
: [];
const blacklistHtml = blacklist.length > 0
? blacklist.map((h) => `
<div style="display:flex; align-items:center; justify-content:space-between; padding:4px 0; border-bottom:1px solid #21262d;">
<span style="font-size:12px; overflow:hidden; text-overflow:ellipsis;">${escapeHtml(h)}</span>
<button class="idfoto-remove-bl" data-hostname="${escapeHtml(h)}" style="
background:transparent; color:#f85149; border:none; cursor:pointer;
font-size:11px; padding:2px 6px;
">remove</button>
</div>
`).join('')
: '<p class="muted" style="font-size:12px;">no blacklisted sites</p>';
app.innerHTML = `
<div class="pad" style="padding-top:12px;">
<div style="display:flex; align-items:center; margin-bottom:16px;">
<button id="settings-back" class="btn" style="font-size:11px; margin-right:8px;">&larr;</button>
<span style="font-size:14px; font-weight:600;">settings</span>
</div>
<div style="margin-bottom:16px;">
<label style="display:flex; align-items:center; gap:8px; cursor:pointer; font-size:13px;">
<input type="checkbox" id="capture-enabled" ${settings.captureEnabled ? 'checked' : ''}>
auto-detect logins
</label>
</div>
<div style="margin-bottom:16px;">
<div style="font-size:12px; color:#8b949e; margin-bottom:6px;">prompt style</div>
<div style="display:flex; gap:8px;">
<button id="style-bar" class="btn" style="font-size:11px; ${settings.captureStyle === 'bar' ? 'background:#1f6feb; color:#fff;' : ''}">bar</button>
<button id="style-toast" class="btn" style="font-size:11px; ${settings.captureStyle === 'toast' ? 'background:#1f6feb; color:#fff;' : ''}">toast</button>
</div>
</div>
<div>
<div style="font-size:12px; color:#8b949e; margin-bottom:6px;">blacklisted sites</div>
<div id="blacklist-container">
${blacklistHtml}
</div>
</div>
</div>
`;
// Back button
document.getElementById('settings-back')?.addEventListener('click', () => {
navigate('locked');
});
// Capture enabled toggle
document.getElementById('capture-enabled')?.addEventListener('change', async (e) => {
const checked = (e.target as HTMLInputElement).checked;
await sendMessage({ type: 'update_settings', settings: { captureEnabled: checked } });
});
// Style buttons
document.getElementById('style-bar')?.addEventListener('click', async () => {
await sendMessage({ type: 'update_settings', settings: { captureStyle: 'bar' } });
renderSettings(app);
});
document.getElementById('style-toast')?.addEventListener('click', async () => {
await sendMessage({ type: 'update_settings', settings: { captureStyle: 'toast' } });
renderSettings(app);
});
// Blacklist remove buttons
document.querySelectorAll('.idfoto-remove-bl').forEach((btn) => {
btn.addEventListener('click', async () => {
const hostname = (btn as HTMLElement).dataset.hostname;
if (hostname) {
await sendMessage({ type: 'remove_blacklist', hostname });
renderSettings(app);
}
});
});
}

View File

@@ -52,5 +52,5 @@ export function renderUnlock(app: HTMLElement): void {
}
const settingsBtn = document.getElementById('settings-btn');
settingsBtn?.addEventListener('click', () => navigate('setup'));
settingsBtn?.addEventListener('click', () => navigate('settings'));
}