Notices and status bar improvements (#24459)

* Notice and status bar improvements

Status bar problems added in the same pass got the same `Date.now()` id and overwrote each other, so usually only one showed. Messages now fall back to their text as the id. The desktop status bar shows the most severe message with a count of the rest that opens a popover listing all of them, and the mobile drawer stacks them vertically instead of placing them side by side.

Dismissing a notice hid it for good, so a detector that restarted again after a dismissal was never shown. Dismiss is replaced by acknowledge, which hides a notice until it happens again, and mute, which hides it permanently. Kinds that never repeat (config and stream checks, the update notice) can only be muted. `reopen_at_count` is removed since acknowledge covers the failed login case.

* move camera CPU warnings to notices

High ffmpeg and detect CPU warnings sat in the status bar with no way to dismiss them. They're now `ffmpeg_high_cpu` and `detect_high_cpu` notices, raised per episode by the same tracker as skipped detections. Also stop failed login attempts held from before an acknowledgement from reopening the notice.

* fix mypy and handle missing cpu stats in notices
This commit is contained in:
Josh Hawkins
2026-09-24 15:39:18 -06:00
committed by GitHub
parent c959df32c9
commit 9664d9ceae
30 changed files with 1307 additions and 707 deletions
+3 -2
View File
@@ -1,9 +1,10 @@
import { createContext } from "react";
import { ProblemSeverity } from "@/types/stats";
export type StatusMessage = {
id: string;
text: string;
color?: string;
severity: ProblemSeverity;
link?: string;
};
@@ -16,7 +17,7 @@ type StatusBarMessagesContextValue = {
addMessage: (
key: string,
message: string,
color?: string,
severity?: ProblemSeverity,
messageId?: string,
link?: string,
) => string | undefined;
+5 -4
View File
@@ -3,6 +3,7 @@ import {
StatusBarMessagesContext,
StatusMessagesState,
} from "@/context/statusbar-context";
import { ProblemSeverity } from "@/types/stats";
type StatusBarMessagesProviderProps = {
children: ReactNode;
@@ -19,21 +20,21 @@ export function StatusBarMessagesProvider({
(
key: string,
message: string,
color?: string,
severity: ProblemSeverity = "error",
messageId?: string,
link?: string,
) => {
if (!key || !message) return;
const id = messageId ?? Date.now().toString();
const msgColor = color ?? "text-danger";
// the text is the fallback id, so repeating a message replaces it
const id = messageId ?? message;
setMessagesState((prevMessages) => {
const existingMessages = prevMessages[key] || [];
// Check if a message with the same ID already exists
const messageIndex = existingMessages.findIndex((msg) => msg.id === id);
const newMessage = { id, text: message, color: msgColor, link };
const newMessage = { id, text: message, severity, link };
// If the message exists, replace it, otherwise add the new message
let updatedMessages;