Download src/FlyRow.tsx from gpue/flyyt: direct link, hf CLI and curl.
- Browser
- Download file 2.52 kB
-
https://huggingface.co/spaces/gpue/flyyt/resolve/main/src/FlyRow.tsx
- Command line
-
hf download hf://spaces/gpue/flyyt/src/FlyRow.tsx
-
curl -L -o FlyRow.tsx https://huggingface.co/spaces/gpue/flyyt/resolve/main/src/FlyRow.tsx
2.52 kB
| import type { FlyInstanceData } from "./useFlyLayout"; | |
| import type { ConnectionState, LiveFlyState } from "./useLiveFlyState"; | |
| export const FLY_ICON = "\u{1FAB0}"; // 🪰, same icon used for the favicon | |
| export const CONNECTION_COLOR: Record<ConnectionState, string> = { | |
| ONLINE: "#4ade80", | |
| OFFLINE: "#5a5d6b", | |
| CONNECTION_BROKEN: "#f87171", | |
| UNKNOWN: "#5a5d6b", | |
| }; | |
| interface FlyRowProps { | |
| fly: FlyInstanceData; | |
| isSelected: boolean; | |
| live: Pick<LiveFlyState, "driving" | "operatingMode" | "batteryPercent" | "connectionState"> | undefined; | |
| onClick: () => void; | |
| } | |
| export default function FlyRow({ fly, isSelected, live, onClick }: FlyRowProps) { | |
| return ( | |
| <button | |
| type="button" | |
| aria-pressed={isSelected} | |
| onClick={onClick} | |
| style={{ | |
| display: "flex", | |
| alignItems: "center", | |
| width: "100%", | |
| textAlign: "left", | |
| padding: "10px 16px", | |
| cursor: "pointer", | |
| background: isSelected ? "#8e56fc33" : "transparent", | |
| border: "none", | |
| borderLeft: isSelected ? "3px solid #8e56fc" : "3px solid transparent", | |
| color: "inherit", | |
| font: "inherit", | |
| fontSize: 14, | |
| }} | |
| > | |
| <span aria-hidden="true" style={{ marginRight: 8 }}> | |
| {FLY_ICON} | |
| </span> | |
| <span>Fly {fly.index + 1}</span> | |
| {live && ( | |
| <span style={{ marginLeft: "auto", display: "flex", alignItems: "center", gap: 6 }}> | |
| {live.driving && ( | |
| <span style={{ fontSize: 10, color: "#8b8d99" }}>{live.operatingMode === "AUTOMATIC" ? "driving" : "manual"}</span> | |
| )} | |
| {/* Battery is a real, meaningful value even with no backend | |
| connected (practice mode) -- it starts at 100 and moves via | |
| the Enter-key feed action -- so it must NOT be gated behind | |
| connectionState, unlike the driving-text/connection-dot below | |
| which only mean anything once a backend has said something. */} | |
| <span style={{ fontSize: 10, color: "#8b8d99" }}>{Math.round(live.batteryPercent)}%</span> | |
| {live.connectionState !== "UNKNOWN" && ( | |
| <span | |
| aria-hidden="true" | |
| title={live.connectionState} | |
| style={{ | |
| width: 7, | |
| height: 7, | |
| borderRadius: "50%", | |
| background: CONNECTION_COLOR[live.connectionState], | |
| flexShrink: 0, | |
| }} | |
| /> | |
| )} | |
| </span> | |
| )} | |
| </button> | |
| ); | |
| } | |