feat: first-run setup banner when identity is unconfigured

Shows a red warning banner at the top of the popup when no identity,
email, username, or explicit mappings are configured. The status dot
turns orange (instead of green) to indicate the extension is active
but not protecting anything yet. Banner disappears as soon as the
user saves their identity.

Prevents users from thinking they're protected when nothing has
been configured.

https://claude.ai/code/session_01Dvgwe7XMoSxnWXkih8p1Cw
This commit is contained in:
Claude
2026-03-26 02:30:09 +00:00
parent ac0ec2cd86
commit 85c6647395
3 changed files with 67 additions and 0 deletions
+34
View File
@@ -242,6 +242,40 @@ body {
white-space: nowrap; white-space: nowrap;
} }
/* First-run banner */
.first-run-banner {
display: flex;
align-items: flex-start;
gap: 10px;
padding: 10px 16px;
background: #fef2f2;
border-bottom: 1px solid #fecaca;
}
.first-run-icon {
width: 22px;
height: 22px;
border-radius: 50%;
background: #dc2626;
color: #fff;
font-size: 14px;
font-weight: 700;
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
}
.first-run-text {
font-size: 12px;
color: #991b1b;
line-height: 1.4;
}
.first-run-text strong {
font-weight: 600;
}
/* Identity tab */ /* Identity tab */
.id-section { .id-section {
margin-bottom: 12px; margin-bottom: 12px;
+9
View File
@@ -35,6 +35,15 @@
<button class="tab" data-tab="test">Test</button> <button class="tab" data-tab="test">Test</button>
</nav> </nav>
<!-- First-Run Setup Banner -->
<div class="first-run-banner" id="firstRunBanner" style="display:none">
<div class="first-run-icon">!</div>
<div class="first-run-text">
<strong>Setup required</strong> — Silent Send needs to know who you are before it can protect you.
Fill in at least your name below, then click Save Identity.
</div>
</div>
<!-- Identity Tab (Smart Patterns) --> <!-- Identity Tab (Smart Patterns) -->
<section class="tab-content active" id="tab-identity"> <section class="tab-content active" id="tab-identity">
<p class="help-text">Tell Silent Send who you are. It auto-catches all variations.</p> <p class="help-text">Tell Silent Send who you are. It auto-catches all variations.</p>
+24
View File
@@ -23,6 +23,7 @@ document.addEventListener('DOMContentLoaded', async () => {
renderActivity(); renderActivity();
loadIdentityForm(); loadIdentityForm();
updateStatusDot(); updateStatusDot();
checkFirstRun();
$('#enableToggle').checked = settings.enabled; $('#enableToggle').checked = settings.enabled;
@@ -196,6 +197,7 @@ async function saveIdentity() {
}; };
await Storage.saveIdentity(identity); await Storage.saveIdentity(identity);
checkFirstRun();
// Flash save button // Flash save button
const btn = $('#btnSaveIdentity'); const btn = $('#btnSaveIdentity');
@@ -207,6 +209,28 @@ async function saveIdentity() {
}, 1500); }, 1500);
} }
// --- First-Run Check ---
function checkFirstRun() {
const hasNames = (identity.names || []).length > 0;
const hasEmails = (identity.emails || []).length > 0 || !!identity.catchAllEmail;
const hasUsernames = (identity.usernames || []).length > 0;
const hasMappings = mappings.length > 0;
// Show banner if nothing is configured at all
const isConfigured = hasNames || hasEmails || hasUsernames || hasMappings;
const banner = $('#firstRunBanner');
banner.style.display = isConfigured ? 'none' : 'flex';
// Also update the status dot — orange if unconfigured
const dot = $('#statusDot');
if (!isConfigured && settings.enabled) {
dot.classList.add('off-site');
dot.classList.remove('disabled');
} else {
dot.classList.remove('off-site');
}
}
// --- Add Mapping --- // --- Add Mapping ---
async function addMapping() { async function addMapping() {
const real = $('#inputReal').value.trim(); const real = $('#inputReal').value.trim();