feat: add opt-in browser domain activity tracking

This commit is contained in:
2026-07-12 17:37:25 +08:00
parent e67a7e4ff7
commit 7461790934
17 changed files with 718 additions and 24 deletions
+30
View File
@@ -126,6 +126,19 @@ input {
color: #e5e7eb;
}
textarea {
box-sizing: border-box;
width: 100%;
margin-top: 5px;
border: 1px solid #374151;
border-radius: 4px;
padding: 7px 8px;
resize: vertical;
background: #0f172a;
color: #e5e7eb;
font: inherit;
}
select {
box-sizing: border-box;
width: 100%;
@@ -142,6 +155,23 @@ input[type="file"] {
font-size: 12px;
}
.tracking-toggle {
display: flex;
align-items: center;
gap: 7px;
color: #e8ecf3 !important;
cursor: pointer;
}
.tracking-toggle input {
width: auto;
margin: 0;
}
.tracking-settings .hint {
margin: 8px 0 4px;
}
.hint {
margin: 0;
font-size: 12px;
+14
View File
@@ -24,6 +24,10 @@
<span id="pending-label">Pending</span>
<strong id="pending-count">0</strong>
</div>
<div class="row">
<span id="activity-pending-label">Activity batches</span>
<strong id="activity-pending-count">0</strong>
</div>
<div class="row url-row">
<span id="url-label">URL</span>
<code id="receiver-url"></code>
@@ -55,6 +59,16 @@
<button id="save-settings" class="secondary">Save</button>
</section>
<section class="settings tracking-settings">
<label class="tracking-toggle" for="passive-activity-enabled">
<input id="passive-activity-enabled" type="checkbox">
<span id="passive-activity-label">Track active domain time</span>
</label>
<p id="passive-activity-disclosure" class="hint">Optional. Collects only the active domain and time spent there. It never sends page URLs, titles, text, keystrokes, or page contents.</p>
<label id="passive-activity-exclusions-label" for="passive-activity-exclusions">Excluded domains</label>
<textarea id="passive-activity-exclusions" rows="3" spellcheck="false" placeholder="youtube.com"></textarea>
</section>
<p id="context-menu-hint" class="hint">Selection and link captures are available from the page context menu.</p>
<p id="status"></p>
</main>
+20 -2
View File
@@ -11,7 +11,10 @@
var languageSelectEl = document.getElementById('language-select');
var fileInputEl = document.getElementById('file-input');
var pendingCountEl = document.getElementById('pending-count');
var pendingActivityCountEl = document.getElementById('activity-pending-count');
var statusDotEl = document.getElementById('status-dot');
var passiveActivityEnabledEl = document.getElementById('passive-activity-enabled');
var passiveActivityExclusionsEl = document.getElementById('passive-activity-exclusions');
var MAX_FILE_TEXT_LENGTH = 2 * 1024 * 1024;
var MAX_FILE_BYTES = 8 * 1024 * 1024;
var catalogs = { en: {}, ru: {} };
@@ -23,6 +26,7 @@
subtitle: 'popup.subtitle',
'receiver-label': 'label.receiver',
'pending-label': 'label.pending',
'activity-pending-label': 'label.activityPending',
'url-label': 'label.url',
'file-label': 'label.file',
'receiver-url-label': 'label.receiverUrl',
@@ -35,7 +39,10 @@
'context-menu-hint': 'hint.contextMenu',
'language-system-option': 'language.system',
'language-en-option': 'language.en',
'language-ru-option': 'language.ru'
'language-ru-option': 'language.ru',
'passive-activity-label': 'label.passiveActivity',
'passive-activity-disclosure': 'hint.passiveActivityDisclosure',
'passive-activity-exclusions-label': 'label.passiveActivityExclusions'
};
function browserLocale() {
@@ -122,9 +129,16 @@
currentState = state || {};
var settings = currentState.settings || {};
pendingCountEl.textContent = String(currentState.pendingCount || 0);
pendingActivityCountEl.textContent = String(currentState.pendingActivityCount || 0);
receiverUrlEl.textContent = settings.receiverUrl || '';
if (document.activeElement !== receiverInputEl) receiverInputEl.value = settings.receiverUrl || '';
if (document.activeElement !== receiverTokenInputEl) receiverTokenInputEl.value = settings.receiverToken || '';
passiveActivityEnabledEl.checked = settings.passiveActivityEnabled === true;
if (document.activeElement !== passiveActivityExclusionsEl) {
passiveActivityExclusionsEl.value = Array.isArray(settings.passiveActivityExcludedDomains)
? settings.passiveActivityExcludedDomains.join('\n')
: '';
}
applyReceiverState(currentState);
}
@@ -142,7 +156,11 @@
return {
receiverUrl: receiverInputEl.value.trim(),
receiverToken: receiverTokenInputEl.value.trim(),
language: currentPreference
language: currentPreference,
passiveActivityEnabled: passiveActivityEnabledEl.checked === true,
passiveActivityExcludedDomains: passiveActivityExclusionsEl.value.split(/[\n,]/).map(function (value) {
return value.trim();
}).filter(Boolean)
};
}