mirror of
https://github.com/pewdiepie-archdaemon/odysseus.git
synced 2026-07-13 12:38:02 +00:00
Polish mobile UI and editor workflows
This commit is contained in:
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user