Merge pull request #27 from outis1one/claude/read-repo-wA3y1

fix: reveal mode broken + missing await + select rendering — v2.0.10
This commit is contained in:
Outis
2026-03-27 08:45:43 -04:00
committed by GitHub
7 changed files with 33 additions and 13 deletions
+1 -1
View File
@@ -1,7 +1,7 @@
{ {
"manifest_version": 3, "manifest_version": 3,
"name": "Silent Send", "name": "Silent Send",
"version": "2.0.9", "version": "2.0.10",
"description": "Intercepts personal info and substitutes it with user-defined replacements before sending to AI services.", "description": "Intercepts personal info and substitutes it with user-defined replacements before sending to AI services.",
"browser_specific_settings": { "browser_specific_settings": {
"gecko": { "gecko": {
+1 -1
View File
@@ -1,7 +1,7 @@
{ {
"manifest_version": 3, "manifest_version": 3,
"name": "Silent Send", "name": "Silent Send",
"version": "2.0.9", "version": "2.0.10",
"description": "Intercepts personal info and substitutes it with user-defined replacements before sending to AI services.", "description": "Intercepts personal info and substitutes it with user-defined replacements before sending to AI services.",
"permissions": [ "permissions": [
"storage", "storage",
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "silent-send", "name": "silent-send",
"version": "2.0.9", "version": "2.0.10",
"private": true, "private": true,
"license": "BSL-1.1", "license": "BSL-1.1",
"description": "Browser extension that substitutes personal data before sending to AI services", "description": "Browser extension that substitutes personal data before sending to AI services",
+16 -2
View File
@@ -784,11 +784,25 @@
// Record what was actually substituted so reveal knows // Record what was actually substituted so reveal knows
for (const r of replacements) { for (const r of replacements) {
if (r.replaced && r.original) { if (r.replaced && r.original) {
// Store with lowercase key for lookup, but preserve original case // Store full replacement with lowercase key for lookup
sessionSubstitutions.set(r.replaced.toLowerCase(), { sessionSubstitutions.set(r.replaced.toLowerCase(), {
original: r.original, original: r.original,
replaced: r.replaced, // preserve original case replaced: r.replaced,
}); });
// Also store individual words so reveal pairs match identity entries
// e.g. "Ademo Demo" → store "ademo" and "demo" separately
const replacedWords = r.replaced.split(/\s+/);
const originalWords = r.original.split(/\s+/);
if (replacedWords.length > 1) {
for (let i = 0; i < replacedWords.length; i++) {
if (replacedWords[i] && originalWords[i]) {
sessionSubstitutions.set(replacedWords[i].toLowerCase(), {
original: originalWords[i],
replaced: replacedWords[i],
});
}
}
}
} }
} }
+2 -2
View File
@@ -476,7 +476,7 @@ const SilentSendSync = {
if (!keyInfo) return { data: null, decrypted: false, needsAuth: true }; if (!keyInfo) return { data: null, decrypted: false, needsAuth: true };
try { try {
const decrypted = await SilentSendCrypto.decryptWithKey(data.payload, keyInfo.key); const decrypted = await SilentSendCrypto.decryptWithKey(data.payload, keyInfo.key);
return this._handleDecryptedMeta(decrypted); return await this._handleDecryptedMeta(decrypted);
} catch { } catch {
return { data: null, decrypted: false, needsAuth: true }; return { data: null, decrypted: false, needsAuth: true };
} }
@@ -488,7 +488,7 @@ const SilentSendSync = {
if (tempKeyStore) { if (tempKeyStore) {
try { try {
const decrypted = await SilentSendCrypto.decryptWithKey(data.payload, tempKeyStore.key); const decrypted = await SilentSendCrypto.decryptWithKey(data.payload, tempKeyStore.key);
return this._handleDecryptedMeta(decrypted); return await this._handleDecryptedMeta(decrypted);
} catch { /* wrong key, fall through to prompt */ } } catch { /* wrong key, fall through to prompt */ }
} }
+1 -1
View File
@@ -591,7 +591,7 @@
</section> </section>
<footer> <footer>
<p>Silent Send v2.0.9</p> <p>Silent Send v2.0.10</p>
</footer> </footer>
</div> </div>
+11 -5
View File
@@ -338,11 +338,17 @@ async function showLockedUI() {
// --- Profiles --- // --- Profiles ---
function renderProfileSelector() { function renderProfileSelector() {
const select = $('#profileSelect'); const select = $('#profileSelect');
safeHTML(select, profiles.map(p => // Build options via DOM API — safeHTML + DOMParser mangles <option> elements
`<option value="${p.id}" ${p.id === currentProfileId ? 'selected' : ''}>` + select.replaceChildren();
`${escapeHtml(p.name)}${p.active ? '' : ' (off)'}` + for (const p of profiles) {
`</option>` const opt = new Option(
).join('')); `${p.name}${p.active ? '' : ' (off)'}`,
p.id,
false,
p.id === currentProfileId
);
select.appendChild(opt);
}
const profile = profiles.find(p => p.id === currentProfileId); const profile = profiles.find(p => p.id === currentProfileId);
$('#profileActive').checked = profile?.active ?? true; $('#profileActive').checked = profile?.active ?? true;