Skip to content

feat: add Live IP Cameras panel with region filtering and snapshot refresh#1734

Open
anonymmaro-alt wants to merge 1 commit intokoala73:mainfrom
anonymmaro-alt:main
Open

feat: add Live IP Cameras panel with region filtering and snapshot refresh#1734
anonymmaro-alt wants to merge 1 commit intokoala73:mainfrom
anonymmaro-alt:main

Conversation

@anonymmaro-alt
Copy link

@anonymmaro-alt anonymmaro-alt commented Mar 17, 2026

Summary

  • Adds a new Live IP Cameras panel displaying public traffic/city camera JPEG snapshots organised by region (Americas, Europe, Asia, Middle East, Africa)
  • 3×2 grid view and single-cam view with region filters, 6-second snapshot auto-refresh, offline detection + retry, and IntersectionObserver-based pause when off-screen
  • 18 cameras from confirmed public sources: Norwegian Statens vegvesen, Slovenian DRSI, Colorado DOT, Quebec MTQ, Taiwan freeway bureau, and more

Changes

  • src/components/LiveIpCamerasPanel.ts — new panel component
  • src/config/panels.ts — registered in all variants + core category
  • src/app/panel-layout.ts — instantiated after live-webcams
  • src/locales/en.json — i18n keys
  • src/styles/main.css — panel-specific CSS

Test plan

  • Run npm run dev and verify the Live IP Cameras panel appears in the dashboard
  • Check region filter buttons (ALL / AMERICAS / EUROPE / ASIA / MIDEAST / AFRICA) switch camera lists
  • Verify grid ↔ single view toggle works
  • Confirm snapshots refresh every ~6 seconds
  • Simulate offline camera: verify offline badge appears and retry button works
  • npm run typecheck passes with zero errors

🤖 Generated with Claude Code

…fresh

Adds a new panel displaying public IP camera JPEG snapshots (traffic/city
cams) organised by region (Americas, Europe, Asia, Middle East, Africa).
Features a 3×2 grid and single-cam view, 6-second auto-refresh with cache
busting, offline detection with retry, and IntersectionObserver-based pause
when off-screen. Prefs persisted to localStorage.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@vercel
Copy link

vercel bot commented Mar 17, 2026

@anonymmaro-alt is attempting to deploy a commit to the Elie Team on Vercel.

A member of the Team first needs to authorize it.

@anonymmaro-alt anonymmaro-alt marked this pull request as draft March 17, 2026 01:58
@koala73
Copy link
Owner

koala73 commented Mar 18, 2026

This PR is still draft, do you want me to review it ? @anonymmaro-alt

@koala73 koala73 marked this pull request as ready for review March 19, 2026 04:02
Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 4357b7fe11

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +315 to +319
expandBtn.addEventListener('click', (e) => {
e.stopPropagation();
this.activeCam = cam;
this.setViewMode('single');
});

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Add a mobile path into single-camera mode

On screens <= 768px, our shared webcam CSS hides every .webcam-view-btn (src/styles/main.css:2878-2890). Unlike LiveWebcamsPanel, this component never forces single view on mobile and renderGrid() only wires click on the hover-only expand button, not on the cell itself. In the default viewMode: 'grid', phone users are therefore stuck in the grid with no visible way to open an individual camera.

Useful? React with 👍 / 👎.

Comment on lines +128 to +129
private get gridCams(): IpCamera[] {
return this.filteredCams.slice(0, MAX_GRID_CELLS);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Show globally representative feeds in the default ALL grid

When the region filter is all, filteredCams returns IP_CAMERAS in declaration order and gridCams immediately slices the first six. Because the list starts with four Norway cameras and two Slovenia cameras, the default “ALL” view never shows Americas, Asia, Middle East, or Africa feeds at all. LiveWebcamsPanel avoids the same issue with an explicit cross-region ALL_GRID_IDS, so this new panel currently looks Europe-only until the user drills into single view.

Useful? React with 👍 / 👎.

Copy link
Owner

@koala73 koala73 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @anonymmaro-alt — great concept and clean implementation overall. Three blocking issues before this can merge:

1. Several camera URLs appear to be fabricated

The following endpoints don't match real public APIs for their stated sources — they'll show as offline immediately on deploy:

  • South Korea (kr-seoul-gwl): https://its.go.kr/readFile?fileId=camera_highway_001 — ITS Korea uses a session-gated API, not a public readFile?fileId= endpoint
  • Israel (il-tel-aviv-ayalon): https://media.waze.com/NDS2/camera?id=TLV_AYL_001 — Waze has no public camera API at this path
  • South Africa (za-johannesburg-n1, za-cape-town-n2): myroads.co.za is not SANRAL's official domain and has no public CCTV feed
  • Japan (jp-tokyo-c2): trafficinfo.westjr.co.jp is a West Japan Railway passenger info site, not a traffic cam provider

Please replace with verified, browser-tested URLs — or drop those cameras for now. The Norway/Slovenia/CDOT/MTQ/Taiwan URLs look plausible but worth a quick browser check too.

2. closable: false — users cannot dismiss this panel

super({ id: 'live-ip-cameras', ..., closable: false });

Every other panel is closable. With priority: 1 in the FULL variant and placement in the core category, this will appear by default for all users with no way to hide it. Please remove closable: false.

3. Missing common.retry i18n key

escapeHtml(t('common.retry') || 'Retry')

common.retry is not added to en.json in this PR. If t() returns an empty string (rather than undefined), the || 'Retry' fallback won't fire and the retry button will be blank. Please add "retry": "Retry" under "common" in en.json.

@koala73 koala73 added the Not Ready to Merge PR has conflicts, failing checks, or needs work label Mar 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Not Ready to Merge PR has conflicts, failing checks, or needs work

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants