128 lines
3.7 KiB
JavaScript
128 lines
3.7 KiB
JavaScript
// Verstak Bridge — Popup Script
|
||
// Shows connection status, queue count, and recent events.
|
||
|
||
const STORAGE_KEY = 'verstak_queue';
|
||
const BRIDGE_KEY = 'verstak_bridge_config';
|
||
const RECENT_KEY = 'verstak_recent';
|
||
|
||
document.addEventListener('DOMContentLoaded', () => {
|
||
updateUI();
|
||
restoreToggleState();
|
||
|
||
document.getElementById('sync-btn').addEventListener('click', forceSync);
|
||
document.getElementById('track-toggle').addEventListener('change', onToggle);
|
||
document.getElementById('config-btn').addEventListener('click', () => {
|
||
// For now, just show bridge config in console
|
||
chrome.storage.local.get(BRIDGE_KEY, (data) => {
|
||
console.log('[verstak] bridge config:', data[BRIDGE_KEY]);
|
||
});
|
||
});
|
||
});
|
||
|
||
function updateUI() {
|
||
chrome.storage.local.get([STORAGE_KEY, BRIDGE_KEY, RECENT_KEY], (data) => {
|
||
const queue = data[STORAGE_KEY] || [];
|
||
const config = data[BRIDGE_KEY] || {};
|
||
const recent = data[RECENT_KEY] || [];
|
||
|
||
// Queue count
|
||
document.getElementById('queue-count').textContent = queue.length;
|
||
|
||
// Bridge status
|
||
const statusEl = document.getElementById('bridge-status');
|
||
const portEl = document.getElementById('bridge-port');
|
||
const dotEl = document.getElementById('status-dot');
|
||
|
||
if (config.bridgeReachable) {
|
||
statusEl.textContent = 'Доступен';
|
||
statusEl.className = 'value online';
|
||
dotEl.className = 'dot online';
|
||
portEl.textContent = config.port || '?';
|
||
} else {
|
||
statusEl.textContent = 'Недоступен';
|
||
statusEl.className = 'value offline';
|
||
dotEl.className = 'dot offline';
|
||
portEl.textContent = config.lastPing ? '—' : 'проверка...';
|
||
}
|
||
|
||
// Recent events
|
||
renderRecent(recent, config.bridgeReachable);
|
||
});
|
||
}
|
||
|
||
function renderRecent(events, reachable) {
|
||
const list = document.getElementById('event-list');
|
||
list.innerHTML = '';
|
||
|
||
if (!events || events.length === 0) {
|
||
list.innerHTML = '<p class="empty">Нет событий</p>';
|
||
return;
|
||
}
|
||
|
||
// Show last 5
|
||
const lastFive = events.slice(-5).reverse();
|
||
for (const ev of lastFive) {
|
||
const item = document.createElement('div');
|
||
item.className = 'event-item';
|
||
item.innerHTML = `
|
||
<div class="domain">${escapeHtml(ev.domain || '?')}</div>
|
||
<div class="title">${escapeHtml(truncate(ev.title || ev.url, 60))}</div>
|
||
<div class="duration">${ev.active_seconds || 0}с${reachable ? '' : ' (ожидает)'}</div>
|
||
`;
|
||
list.appendChild(item);
|
||
}
|
||
}
|
||
|
||
function forceSync() {
|
||
const btn = document.getElementById('sync-btn');
|
||
btn.disabled = true;
|
||
btn.textContent = '⏳ Отправка...';
|
||
|
||
// Ask background to flush
|
||
chrome.runtime.sendMessage({ type: 'FORCE_FLUSH' }, (response) => {
|
||
setTimeout(() => {
|
||
updateUI();
|
||
btn.disabled = false;
|
||
btn.textContent = '🔄 Отправить сейчас';
|
||
}, 1000);
|
||
});
|
||
}
|
||
|
||
function onToggle(e) {
|
||
const enabled = e.target.checked;
|
||
chrome.storage.local.set({ 'verstak_tracking_enabled': enabled });
|
||
|
||
// Notify background
|
||
chrome.runtime.sendMessage({ type: 'SET_TRACKING', enabled });
|
||
}
|
||
|
||
function restoreToggleState() {
|
||
chrome.storage.local.get('verstak_tracking_enabled', (data) => {
|
||
const enabled = data.verstak_tracking_enabled !== false;
|
||
document.getElementById('track-toggle').checked = enabled;
|
||
});
|
||
}
|
||
|
||
// Listen for updates from background
|
||
chrome.runtime.onMessage.addListener((msg) => {
|
||
if (msg.type === 'UI_UPDATE') {
|
||
updateUI();
|
||
}
|
||
});
|
||
|
||
// --- Helpers ---
|
||
|
||
function truncate(s, n) {
|
||
if (!s) return '';
|
||
return s.length > n ? s.substring(0, n) + '...' : s;
|
||
}
|
||
|
||
function escapeHtml(s) {
|
||
if (!s) return '';
|
||
return s
|
||
.replace(/&/g, '&')
|
||
.replace(/</g, '<')
|
||
.replace(/>/g, '>')
|
||
.replace(/"/g, '"');
|
||
}
|