diff --git a/containers/libreportal/frontend/components/dashboard/js/dashboard.js b/containers/libreportal/frontend/components/dashboard/js/dashboard.js index 141e4b0..41a0586 100755 --- a/containers/libreportal/frontend/components/dashboard/js/dashboard.js +++ b/containers/libreportal/frontend/components/dashboard/js/dashboard.js @@ -95,7 +95,14 @@ async function populateDashboardServiceButtons(installedApps) { // Setup event listeners function setupEventListeners() { - setupMobileMenu(); + // Guarded like system-loader's mobile-menu component: this is a nav nicety, + // and an unguarded call meant a missing/reordered script took the dashboard's + // app list down with it. Never let optional chrome break the page below it. + if (typeof setupMobileMenu === 'function') { + setupMobileMenu(); + } else { + console.warn('setupMobileMenu not available — mobile drawer disabled'); + } loadInstalledApps(); } diff --git a/containers/libreportal/frontend/index.html b/containers/libreportal/frontend/index.html index 478e049..502691e 100755 --- a/containers/libreportal/frontend/index.html +++ b/containers/libreportal/frontend/index.html @@ -100,6 +100,12 @@ + + diff --git a/scripts/task/crontab_task_processor.sh b/scripts/task/crontab_task_processor.sh index 26ebcd0..349dd49 100755 --- a/scripts/task/crontab_task_processor.sh +++ b/scripts/task/crontab_task_processor.sh @@ -492,6 +492,33 @@ dispatchSpecific() { # HOUSEKEEPING # ============================================================================ +# Drop queue entries whose task file no longer exists. queue.json is append-only +# from the enqueue side, so any task file removed afterwards — by housekeeping, a +# manual clean-up, a restore — leaves an id behind that the WebUI keeps fetching +# forever, one 404 per poll per orphan. Nothing else prunes it, so it only ever +# grows. Cheap: a no-op unless an id has no file. +cleanupOrphanQueueEntries() { + local queue="$TASK_DIR/queue.json" + [[ -f "$queue" ]] || return 0 + command -v jq >/dev/null 2>&1 || return 0 + + local ids orphans=() id + ids=$(jq -r '.[]?' "$queue" 2>/dev/null) || return 0 + [[ -z "$ids" ]] && return 0 + while IFS= read -r id; do + [[ -z "$id" ]] && continue + [[ -f "$TASK_DIR/${id}.json" ]] || orphans+=("$id") + done <<< "$ids" + (( ${#orphans[@]} == 0 )) && return 0 + + local filtered + filtered=$(jq -c --argjson drop "$(printf '%s\n' "${orphans[@]}" | jq -R . | jq -cs .)" \ + '[ .[] | select(. as $i | $drop | index($i) | not) ]' "$queue" 2>/dev/null) || return 0 + [[ -n "$filtered" ]] || return 0 + printf '%s' "$filtered" | runFileWrite "$queue" + logInfo "Pruned ${#orphans[@]} orphaned queue entr$( (( ${#orphans[@]} == 1 )) && echo y || echo ies ): ${orphans[*]}" +} + cleanupZeroByteFiles() { # Use the bash builtin `-s` (file size > 0) instead of forking `stat` per # file — at 100+ task files the stat fork was a measurable share of the @@ -596,6 +623,7 @@ mainLoop() { recoverOrphans dispatchPending cleanupZeroByteFiles + cleanupOrphanQueueEntries maybeRegenPoll fi done