fix: auto-sync token persistence + better status display

Auto-sync now:
- Persists Gist token in the auto-sync config so it survives
  page reloads (previously only read from the input field)
- Saves token when the Gist token field changes (not just on toggle)
- Validates that credentials exist before enabling
- Shows current status: method, interval, last push/pull times
- Updated UI description to clarify it works in all browsers

https://claude.ai/code/session_01SWSwDfMVij53bCTNSCLMwn
This commit is contained in:
Claude
2026-03-27 04:01:25 +00:00
parent b7a5bcc287
commit 8cff1ae382
2 changed files with 47 additions and 14 deletions
+4 -2
View File
@@ -278,9 +278,11 @@
<!-- Auto Sync --> <!-- Auto Sync -->
<div style="margin-top:20px;padding-top:16px;border-top:1px solid #e5e7eb"> <div style="margin-top:20px;padding-top:16px;border-top:1px solid #e5e7eb">
<h3 style="font-size:13px;font-weight:600;margin:0 0 4px">Auto Sync — background polling</h3> <h3 style="font-size:13px;font-weight:600;margin:0 0 4px">Auto Sync — works in all browsers</h3>
<p class="section-desc" style="margin-bottom:8px"> <p class="section-desc" style="margin-bottom:8px">
Automatically push and pull settings on an interval. Uses the Gist or URL method configured above. Automatically push and pull settings in the background on a schedule.
Uses GitHub Gist or Custom URL — configure one of those above first, then enable auto sync here.
Changes you make locally are pushed immediately; remote changes are pulled on the interval.
</p> </p>
<div style="display:flex;gap:12px;flex-wrap:wrap;align-items:center;margin-bottom:8px"> <div style="display:flex;gap:12px;flex-wrap:wrap;align-items:center;margin-bottom:8px">
<label class="toggle" title="Enable auto sync"> <label class="toggle" title="Enable auto sync">
+43 -12
View File
@@ -1190,9 +1190,7 @@ async function initAutoSyncUI() {
$('#autoSyncEnabled').checked = config.enabled || false; $('#autoSyncEnabled').checked = config.enabled || false;
$('#autoSyncMethod').value = config.method || 'gist'; $('#autoSyncMethod').value = config.method || 'gist';
$('#autoSyncInterval').value = String(config.interval || 15); $('#autoSyncInterval').value = String(config.interval || 15);
if (config.lastPull) { updateAutoSyncStatus(config);
setAutoSyncStatus(`Last pull: ${new Date(config.lastPull).toLocaleString()}`, 'ok');
}
} }
const saveAutoSync = async () => { const saveAutoSync = async () => {
@@ -1201,26 +1199,59 @@ async function initAutoSyncUI() {
config.method = $('#autoSyncMethod').value; config.method = $('#autoSyncMethod').value;
config.interval = parseInt($('#autoSyncInterval').value, 10) || 15; config.interval = parseInt($('#autoSyncInterval').value, 10) || 15;
// Inherit token/URL from existing fields // Always grab the latest token/URL from the page fields
if (config.method === 'gist') { // AND persist them so they survive page reloads
const token = $('#gistToken').value.trim(); const gistToken = $('#gistToken').value.trim();
if (token) config.gistToken = token; if (gistToken) config.gistToken = gistToken;
} else { const customUrl = $('#customSyncUrl').value.trim();
config.url = $('#customSyncUrl').value.trim(); if (customUrl) config.url = customUrl;
config.headers = parseHeadersField($('#customSyncHeaders').value); config.headers = parseHeadersField($('#customSyncHeaders').value);
// Validate: need credentials for the chosen method
if (config.enabled) {
if (config.method === 'gist' && !config.gistToken) {
setAutoSyncStatus('Enter your GitHub PAT in the Gist section above first.', 'warn');
config.enabled = false;
$('#autoSyncEnabled').checked = false;
} else if (config.method === 'url' && !config.url) {
setAutoSyncStatus('Enter a URL in the Custom URL section above first.', 'warn');
config.enabled = false;
$('#autoSyncEnabled').checked = false;
}
} }
await SilentSendSync.saveAutoSyncConfig(config); await SilentSendSync.saveAutoSyncConfig(config);
// Tell service worker to reconfigure alarm
api.runtime.sendMessage({ type: 'autosync:config-changed' }).catch(() => {}); api.runtime.sendMessage({ type: 'autosync:config-changed' }).catch(() => {});
setAutoSyncStatus(config.enabled ? 'Auto sync enabled.' : 'Auto sync disabled.', config.enabled ? 'ok' : 'neutral'); updateAutoSyncStatus(config);
}; };
// Also save token when the Gist token field changes
$('#gistToken').addEventListener('change', async () => {
const config = (await SilentSendSync.getAutoSyncConfig()) || {};
const token = $('#gistToken').value.trim();
if (token) {
config.gistToken = token;
await SilentSendSync.saveAutoSyncConfig(config);
}
});
$('#autoSyncEnabled').addEventListener('change', saveAutoSync); $('#autoSyncEnabled').addEventListener('change', saveAutoSync);
$('#autoSyncMethod').addEventListener('change', saveAutoSync); $('#autoSyncMethod').addEventListener('change', saveAutoSync);
$('#autoSyncInterval').addEventListener('change', saveAutoSync); $('#autoSyncInterval').addEventListener('change', saveAutoSync);
} }
function updateAutoSyncStatus(config) {
if (!config?.enabled) {
setAutoSyncStatus('Auto sync disabled.', 'neutral');
return;
}
const parts = [];
parts.push(`${config.method === 'gist' ? 'GitHub Gist' : 'Custom URL'} every ${config.interval}min`);
if (config.lastPull) parts.push(`last pull: ${new Date(config.lastPull).toLocaleString()}`);
if (config.lastPush) parts.push(`last push: ${new Date(config.lastPush).toLocaleString()}`);
setAutoSyncStatus(parts.join(' · '), 'ok');
}
function setAutoSyncStatus(msg, type) { function setAutoSyncStatus(msg, type) {
const el = $('#autoSyncStatus'); const el = $('#autoSyncStatus');
if (!el) return; if (!el) return;