Compare commits

...
3 Commits
Author SHA1 Message Date
leccelecceandGitHub 85de58f6cf Merge 7739a330d8 into c007661a71 2026-07-03 10:28:30 +08:00
Blake BlackshearandGitHub c007661a71 Enhancements (#23611)
CI / AMD64 Build (push) Has been cancelled
CI / ARM Build (push) Has been cancelled
CI / Jetson Jetpack 6 (push) Has been cancelled
CI / AMD64 Extra Build (push) Has been cancelled
CI / ARM Extra Build (push) Has been cancelled
CI / Synaptics Build (push) Has been cancelled
CI / Assemble and push default build (push) Has been cancelled
* better default handling if no proxy chain is present

* add note about SameSite for jwt cookie
2026-07-02 07:05:00 -05:00
leccelecceandClaude Opus 4.8 7739a330d8 Use a distinct color palette for Frames / Detections graphs (#2)
The CPU and Frames / Detections graphs on the system metrics page both
rendered through CameraLineGraph with a single shared palette, making
the two graphs hard to tell apart at a glance.

Add an optional `colors` prop to CameraLineGraph (defaulting to the
existing palette so CPU graphs are unchanged) and give the Frames /
Detections graphs their own green/orange/cyan palette. The colors are
routed through both the chart lines and the legend dots so they stay
in sync.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 22:42:50 +01:00
3 changed files with 30 additions and 12 deletions
+16 -8
View File
@@ -254,7 +254,14 @@ rateLimiter = RateLimiter()
def get_remote_addr(request: Request):
route = list(reversed(request.headers.get("x-forwarded-for").split(",")))
# fall back to the direct TCP peer when no proxy chain is present
direct_addr = request.client.host if request.client else None
forwarded_for = request.headers.get("x-forwarded-for")
if not forwarded_for:
return direct_addr or "127.0.0.1"
route = list(reversed(forwarded_for.split(",")))
logger.debug(f"IP Route: {[r for r in route]}")
trusted_proxies = []
for proxy in request.app.frigate_config.auth.trusted_proxies:
@@ -291,13 +298,8 @@ def get_remote_addr(request: Request):
logger.debug(f"First untrusted IP: {str(ip)}")
return str(ip)
# if there wasn't anything in the route, just return the default
remote_addr = None
if hasattr(request, "remote_addr"):
remote_addr = request.remote_addr
return remote_addr or "127.0.0.1"
# every hop in the route was trusted, so fall back to the direct peer
return direct_addr or "127.0.0.1"
def _cleanup_first_load_seen() -> None:
@@ -416,6 +418,12 @@ def create_encoded_jwt(user, role, expiration, secret):
def set_jwt_cookie(response: Response, cookie_name, encoded_jwt, expiration, secure):
# TODO: ideally this would set secure as well, but that requires TLS
# SameSite is intentionally left unset (browsers default to Lax). Setting
# SameSite=Lax/Strict would stop the cookie from being sent in cross-origin
# iframes, breaking embedded views such as the Home Assistant Frigate card.
# CSRF is instead mitigated by requiring a custom X-CSRF-TOKEN header, which
# cross-origin pages cannot set without a CORS preflight that Frigate never
# grants (see check_csrf in api/fastapi_app.py).
response.set_cookie(
key=cookie_name,
value=encoded_jwt,
+8 -3
View File
@@ -11,6 +11,9 @@ import useSWR from "swr";
import { useTimeFormat } from "@/hooks/use-date-utils";
const GRAPH_COLORS = ["#5C7CFA", "#ED5CFA", "#FAD75C"];
// Distinct palette so the Frames / Detections graphs are easy to tell apart
// from the CPU graphs at a glance.
export const FPS_GRAPH_COLORS = ["#2DD4BF", "#818CFF", "#D17B88"];
type CameraLineGraphProps = {
graphId: string;
@@ -19,6 +22,7 @@ type CameraLineGraphProps = {
updateTimes: number[];
data: ApexAxisChartSeries;
isActive?: boolean;
colors?: string[];
};
export function CameraLineGraph({
graphId,
@@ -27,6 +31,7 @@ export function CameraLineGraph({
updateTimes,
data,
isActive = true,
colors = GRAPH_COLORS,
}: CameraLineGraphProps) {
const { t } = useTranslation(["views/system", "common"]);
const { data: config } = useSWR<FrigateConfig>("config", {
@@ -91,7 +96,7 @@ export function CameraLineGraph({
enabled: false,
},
},
colors: GRAPH_COLORS,
colors,
grid: {
show: false,
},
@@ -138,7 +143,7 @@ export function CameraLineGraph({
min: 0,
},
} as ApexCharts.ApexOptions;
}, [graphId, systemTheme, theme, formatTime]);
}, [graphId, colors, systemTheme, theme, formatTime]);
useEffect(() => {
ApexCharts.exec(graphId, "updateOptions", options, true, true);
@@ -162,7 +167,7 @@ export function CameraLineGraph({
<div key={label} className="flex items-center gap-1">
<MdCircle
className="size-2"
style={{ color: GRAPH_COLORS[labelIdx] }}
style={{ color: colors[labelIdx] }}
/>
<div className="text-xs text-secondary-foreground">
{t("cameras.label." + label)}
+6 -1
View File
@@ -1,5 +1,8 @@
import { useFrigateStats } from "@/api/ws";
import { CameraLineGraph } from "@/components/graph/LineGraph";
import {
CameraLineGraph,
FPS_GRAPH_COLORS,
} from "@/components/graph/LineGraph";
import CameraInfoDialog from "@/components/overlay/CameraInfoDialog";
import { ConnectionQualityIndicator } from "@/components/camera/ConnectionQualityIndicator";
import { EmptyCard } from "@/components/card/EmptyCard";
@@ -308,6 +311,7 @@ export default function CameraMetrics({
updateTimes={updateTimes}
data={overallFpsSeries}
isActive={isActive}
colors={FPS_GRAPH_COLORS}
/>
</div>
) : (
@@ -411,6 +415,7 @@ export default function CameraMetrics({
cameraFpsSeries[camera.name] || {},
)}
isActive={isActive}
colors={FPS_GRAPH_COLORS}
/>
</div>
) : (