Polish mobile UI and editor workflows

This commit is contained in:
pewdiepie-archdaemon
2026-06-27 13:05:44 +00:00
parent 87e46e576a
commit 45ee5a71f4
48 changed files with 6455 additions and 1177 deletions
+31 -5
View File
@@ -27,16 +27,20 @@ function _markDismissed(ids) {
}
let _activePollInterval = null;
let _activePollInFlight = false;
let _librarySyncInFlight = false;
let _lastLibrarySyncAt = 0;
const _LIBRARY_SYNC_MIN_MS = 120000;
export function init(apiBase) {
_apiBase = apiBase;
_reconnectActive();
_reconnectActive({ includeLibrary: true, forceLibrary: true });
// Poll for active sessions periodically so research started elsewhere
// (e.g. by the agent via trigger_research) gets adopted into the
// sidebar — _reconnectActive only ran once at load before, so
// agent-started jobs never appeared until a page reload.
if (_activePollInterval) clearInterval(_activePollInterval);
_activePollInterval = setInterval(() => { _reconnectActive(); }, 12000);
_activePollInterval = setInterval(() => { _reconnectActive(); }, 20000);
}
// Allow an immediate adopt when the chat stream signals a new research
@@ -46,7 +50,13 @@ export function adoptSession(sessionId) {
_reconnectActive();
}
async function _reconnectActive() {
export function refreshLibrary(options = {}) {
return _syncLibrary(options);
}
async function _reconnectActive(options = {}) {
if (_activePollInFlight) return;
_activePollInFlight = true;
try {
// Reconnect to running tasks
const res = await fetch(`${_apiBase}/api/research/active`, { credentials: 'same-origin' });
@@ -68,7 +78,20 @@ async function _reconnectActive() {
}
}
// Load recent completed research from disk
if (options.includeLibrary) await _syncLibrary({ force: !!options.forceLibrary });
_notify();
} catch {
} finally {
_activePollInFlight = false;
}
}
async function _syncLibrary(options = {}) {
const now = Date.now();
if (_librarySyncInFlight) return;
if (!options.force && now - _lastLibrarySyncAt < _LIBRARY_SYNC_MIN_MS) return;
_librarySyncInFlight = true;
try {
const libRes = await fetch(`${_apiBase}/api/research/library?sort=recent&limit=20`, { credentials: 'same-origin' });
if (libRes.ok) {
const libData = await libRes.json();
@@ -90,9 +113,12 @@ async function _reconnectActive() {
});
}
}
_lastLibrarySyncAt = Date.now();
_notify();
} catch {}
finally {
_librarySyncInFlight = false;
}
}
function _parseDuration(s) {
+5 -4
View File
@@ -297,6 +297,7 @@ export function openPanel(focusJobId) {
_loadEndpoints().then(_restoreSavedSettings);
_clearBadge();
_updateResearchCount();
jobs.refreshLibrary?.({ force: true });
if ('Notification' in window && Notification.permission === 'default') {
try { Notification.requestPermission(); } catch {}
@@ -370,7 +371,7 @@ function _buildPanelHTML() {
</div>
<p class="memory-desc doclib-desc" style="margin-top:2px;display:flex;align-items:center;gap:6px;flex-wrap:wrap;">
<span>Multi-step web research with an LLM-in-the-loop agent</span>
<span id="research-no-past-hint" style="display:none;font:inherit;opacity:1;position:static;"> past runs in <button type="button" class="research-library-link" style="background:none;border:none;padding:0;font:inherit;color:var(--accent, var(--red));cursor:pointer;text-decoration:underline;">Library, Research</button></span>
<span id="research-no-past-hint" style="display:none;font:inherit;opacity:1;position:static;">All past research found in: <button type="button" class="research-library-link" style="background:none;border:none;padding:0;font:inherit;color:var(--accent, var(--red));cursor:pointer;text-decoration:underline;">Library, Research</button></span>
</p>
<textarea id="research-query" class="research-query" placeholder="${_pickResearchHint()}" rows="4"></textarea>
<button id="research-settings-toggle" class="research-settings-toggle${chevronCls}">
@@ -669,7 +670,7 @@ function _renderJobs() {
const allJobs = jobs.getJobs();
if (!allJobs.length) {
// No empty-state text in the body — the query box above is the call to
// action. But still surface the "All past research found in Library,
// action. But still surface the "All past research found in: Library,
// Research" hint under the main title, since the Past section won't
// render to host it (this is exactly the case the dynamic hint targets).
container.innerHTML = '';
@@ -718,7 +719,7 @@ function _renderJobs() {
}
// Dynamic Past hint: when the Past section won't render (no past items),
// surface the "All past research found in Library, Research" line under
// surface the "All past research found in: Library, Research" line under
// the main Research title instead, so the link is always discoverable.
const noPastHint = document.getElementById('research-no-past-hint');
if (noPastHint) {
@@ -783,7 +784,7 @@ function _renderJobs() {
if (key === 'past') {
const hint = document.createElement('span');
hint.className = 'research-library-hint';
hint.innerHTML = '<span>Multi-step web research with an LLM-in-the-loop agent</span> <button type="button" class="research-library-link">Library, Research</button>';
hint.innerHTML = '<span>All past research found in:</span> <button type="button" class="research-library-link">Library, Research</button>';
hint.querySelector('.research-library-link').addEventListener('click', (e) => {
e.stopPropagation();
// Close the research panel first so the Library opens ABOVE it on mobile