From c2211acb15c491173883ad1e000483fa51e3233d Mon Sep 17 00:00:00 2001 From: Robbie Byrd Date: Fri, 10 Jul 2026 01:36:21 +0000 Subject: [PATCH] feat(frontend): Flight Tracker app icon via ClassicyIcons.applications.flightTracker MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit app.png was a TIFF with a .png name (browsers won't render TIFF) — converted to real 32x32 PNG. Registered with registerClassicyIcons, spreading the existing applications namespace (registration assigns shallowly). Both ClassicyWindows now carry icon={appIcon}. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_019NMS1V2keS3pTbWRemCd9o --- .../FlightTracker/FlightTracker.test.tsx | 14 +++++++++++++- .../FlightTracker/FlightTracker.tsx | 17 ++++++++++++++++- .../src/Applications/FlightTracker/app.png | Bin 0 -> 579 bytes 3 files changed, 29 insertions(+), 2 deletions(-) create mode 100644 packages/frontend/src/Applications/FlightTracker/app.png diff --git a/packages/frontend/src/Applications/FlightTracker/FlightTracker.test.tsx b/packages/frontend/src/Applications/FlightTracker/FlightTracker.test.tsx index 2e9714c4..6e9b5166 100644 --- a/packages/frontend/src/Applications/FlightTracker/FlightTracker.test.tsx +++ b/packages/frontend/src/Applications/FlightTracker/FlightTracker.test.tsx @@ -134,7 +134,11 @@ vi.mock("classicy", () => ({ /> ), MAC_OS_8_CRAYONS: [], - ClassicyIcons: { controlPanels: { location: { app: "icon.png" } } }, + ClassicyIcons: { + controlPanels: { location: { app: "icon.png" } }, + applications: {}, + }, + registerClassicyIcons: (icons: T) => icons, quitMenuItemHelper: () => ({}), registerAppEventHandler: () => {}, useAppManager: (sel: (s: unknown) => unknown) => @@ -270,6 +274,14 @@ describe("FlightTracker", () => { expect((last.positions as unknown[]).length).toBe(1); }); + it("registers app.png as the app icon and passes it to every window", () => { + render(); + expect(windowProps.length).toBeGreaterThan(0); + for (const w of windowProps) { + expect(String(w.icon)).toMatch(/app\.png/); + } + }); + it("clears the selection when the selected flight leaves the airborne set (e.g. after a seek)", () => { // useFlightTrack fires a real fetch once a flight is selected; stub it out // so the test only exercises the selection-clearing behavior under test. diff --git a/packages/frontend/src/Applications/FlightTracker/FlightTracker.tsx b/packages/frontend/src/Applications/FlightTracker/FlightTracker.tsx index b62e8510..de555b60 100644 --- a/packages/frontend/src/Applications/FlightTracker/FlightTracker.tsx +++ b/packages/frontend/src/Applications/FlightTracker/FlightTracker.tsx @@ -9,10 +9,12 @@ import { ClassicyWindow, MAC_OS_8_CRAYONS, quitMenuItemHelper, + registerClassicyIcons, useAppManager, useAppManagerDispatch, useClassicyDateTime, } from "classicy"; +import appIconPng from "./app.png"; import { type ChangeEvent, type FC, @@ -58,10 +60,21 @@ const BASEMAP_URL = (import.meta.env.VITE_FLIGHT_BASEMAP_URL as string | undefined) ?? "https://files.911realtime.org/maps/na-basemap.pmtiles"; +// This app's own icon, registered into the shared registry at +// ClassicyIcons.applications.flightTracker.app. registerClassicyIcons assigns +// shallowly, so the existing applications namespace is spread in to keep +// classicy's bundled app icons intact. +const ICONS = registerClassicyIcons({ + applications: { + ...ClassicyIcons.applications, + flightTracker: { app: appIconPng }, + }, +}); + export const FlightTracker: FC = () => { const appId = "FlightTracker.app"; const appName = "Flight Tracker"; - const appIcon = ClassicyIcons.controlPanels.location.app as string; + const appIcon = ICONS.applications.flightTracker.app; const isRunning = useAppManager( (s) => appId in (s.System.Manager.Applications.apps ?? {}), @@ -361,6 +374,7 @@ export const FlightTracker: FC = () => { { eTB0%`?HfLc_7RRV5-R>+UcDH7HPQr>s6Gnz3r;+8#b538JW z<`404^#!HW-w{ws(f9p7B~eX4f&-UGoXx8upp?QG!!%6*v~7#E_H=Qj6yE#8d6!bK zBmvAM_8tJ|+#!k2D+JoMMQcq60c$PB7>qG=UB^)|EtM$eT_PZ`))GR%7z03zadUAA zo^#$Mp=x|UDTTFm9?M~TJRZat0Z1t^48wZyMKDQ08Sb(VNbsgeBf~K8dc9U8Y7Mq31@OJ2=kvJ=o>H23@0?quDTJ__jwLRo zKz5l@Vw$EoIDq$lrBba~RVx5L<#Yt++Nq2C_x2-=Y6&4B!J$Hd<;fSPYugt1ky#*Pk$jKDGUTmx zT#IoW-@dzD1*O&QVR=Beo-IbF0J8T!1JzG0E~VhC4+yqAVGq@1conqWD%j@+Kfur|Jd;xiH$${V` RAF}`e002ovPDHLkV1nms`^x|T literal 0 HcmV?d00001