Compare commits

...

3 Commits

Author SHA1 Message Date
f7cce5ceec feat: Add upload completion hint and increase notification debounce timer
Co-authored-by: aider (gemini/gemini-2.5-pro) <aider@aider.chat>
2026-01-22 09:46:01 -07:00
bc1cff21c5 fix: Prevent 'duplicate' status from triggering success banner 2026-01-22 09:45:59 -07:00
d48d51bdc3 feat: Display 'All uploads complete' banner on finish
Co-authored-by: aider (gemini/gemini-2.5-pro) <aider@aider.chat>
2026-01-22 09:36:12 -07:00
2 changed files with 28 additions and 2 deletions

View File

@@ -235,7 +235,7 @@ def _schedule_batch_notification():
asyncio.create_task(send_batch_notification())
async def reset_telegram_debounce():
"""Resets the 30s timer for batch completion notification."""
"""Resets the 120s timer for batch completion notification."""
if not SETTINGS.telegram_bot_api_key or not TELEGRAM_OWNER_ID:
return
@@ -244,7 +244,7 @@ async def reset_telegram_debounce():
if _batch_complete_timer:
_batch_complete_timer.cancel()
loop = asyncio.get_event_loop()
_batch_complete_timer = loop.call_later(10, _schedule_batch_notification)
_batch_complete_timer = loop.call_later(120, _schedule_batch_notification)
async def add_file_to_batch(filename: str, size: int, album_name: str, is_invite: bool):
"""Adds a completed file to the batch list."""
@@ -1127,6 +1127,17 @@ async def api_upload_chunk_complete(request: Request) -> JSONResponse:
await send_progress(session_id_local, item_id_local, "error", 100, "Failed to save file locally")
return JSONResponse({"error": "local_save_failed"}, status_code=500)
@app.post("/api/uploads/batch_complete_hint")
async def api_batch_complete_hint(request: Request) -> JSONResponse:
"""
Client-side hint that a batch of uploads has completed.
This triggers the batch notification immediately instead of waiting for the debounce timer.
"""
# session_id from body is optional, for future use, but not currently used
# because the batch is global.
await send_batch_notification()
return JSONResponse({"ok": True})
# ---------- Auth & Albums & Invites APIs ----------

View File

@@ -34,6 +34,7 @@ try {
} catch {}
let items = [];
let socket;
let allCompleteBannerShown = false;
// Status precedence: never regress (e.g., uploading -> done shouldn't go back to uploading)
const STATUS_ORDER = { queued: 0, checking: 1, uploading: 2, duplicate: 3, done: 3, error: 4 };
@@ -92,6 +93,7 @@ function addItem(file, relativePath){
const resolvedPath = (relativePath !== undefined) ? relativePath : (file.webkitRelativePath || '');
const it = { id, file, name: file.name, size: file.size, status: 'queued', progress: 0, relativePath: resolvedPath };
items.unshift(it);
allCompleteBannerShown = false;
render();
}
@@ -155,6 +157,19 @@ function render(){
document.getElementById('countDone').textContent=c.done;
document.getElementById('countDup').textContent=c.dup;
document.getElementById('countErr').textContent=c.err;
if (!allCompleteBannerShown && items.length > 0) {
const isComplete = items.every(it => FINAL_STATES.has(it.status));
const hasSuccess = items.some(it => it.status === 'done');
if (isComplete && hasSuccess) {
showBanner("All uploads complete.", "ok");
allCompleteBannerShown = true;
// Hint to backend that this batch is done, to trigger notification sooner
try {
fetch('/api/uploads/batch_complete_hint', { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({ session_id: sessionId }) }).catch(()=>{});
} catch {}
}
}
}
// --- WebSocket progress ---