fix: date false-positive, partial-word highlights, cross-browser sync

Bug fixes:
- Date (possible DOB) pattern now requires context words (born, birthday,
  dob, etc.) before firing — prevents spurious warnings on page-load API
  calls that happen to contain ISO dates in conversation history.
- Highlight regex now uses word boundaries (\b) so short substitute values
  (e.g. "aud") no longer match inside unrelated words like "Claude".
- Both TreeWalkers in content.js now skip the extension's own UI elements
  (.ss-autodetect-warning, .ss-presend-warning, .ss-reveal-badge) to
  prevent the highlight API from marking text in the extension's banners.

Settings sync:
- New src/lib/sync.js: exportSyncCode / importSyncCode (base64 JSON) for
  manual copy-paste across any browser combination. Newest lastModified
  timestamp wins; force flag available to override.
- browser.storage.sync support: when "Browser account sync" is enabled the
  extension automatically pushes/pulls via Firefox Sync or Chrome account,
  chunked to stay within per-item quota limits.
- storage.js now writes ss_lastModified on every save so conflict resolution
  has an accurate timestamp.
- service-worker.js listens for both local and sync storage changes to keep
  all copies in sync.
- New "Sync Between Browsers" section in options.html with Generate/Copy/
  Import Sync Code UI and the browser sync toggle.

https://claude.ai/code/session_01TKpSR9M8JgHLXCp5CeDsQP
This commit is contained in:
Claude
2026-03-26 14:13:22 +00:00
parent 2e79e02bd3
commit 84f6e675db
6 changed files with 340 additions and 12 deletions
+20 -3
View File
@@ -7,6 +7,7 @@
*/
import Storage from '../lib/storage.js';
import SilentSendSync from '../lib/sync.js';
import api from '../lib/browser-polyfill.js';
// Track substitution counts per tab
@@ -296,11 +297,24 @@ async function updateIcon(settings) {
}
}
// Update icon when settings, identity, or mappings change
api.storage.onChanged.addListener(async (changes) => {
// Update icon when settings, identity, or mappings change; push to sync storage if enabled
api.storage.onChanged.addListener(async (changes, areaName) => {
if (changes.ss_settings || changes.ss_identity || changes.ss_mappings) {
const settings = await Storage.getSettings();
await updateIcon(settings);
// Push to browser.storage.sync when local data changes (same-browser cross-device)
if (areaName === 'local' && settings.browserSync) {
await SilentSendSync.pushToSyncStorage();
}
}
// When sync storage changes (another device pushed new data), pull it into local
if (areaName === 'sync' && (changes.ss_sync_meta || Object.keys(changes).some(k => k.startsWith('ss_sync_chunk_')))) {
const settings = await Storage.getSettings();
if (settings.browserSync) {
await SilentSendSync.pullFromSyncStorage();
}
}
});
@@ -311,8 +325,11 @@ api.runtime.onInstalled.addListener(async () => {
await updateIcon(settings);
});
// Also set icon on startup (service worker wake)
// Also set icon on startup (service worker wake) + pull any newer sync data
(async () => {
const settings = await Storage.getSettings();
await updateIcon(settings);
if (settings.browserSync) {
await SilentSendSync.pullFromSyncStorage();
}
})();