Commit Graph

1045 Commits

Author SHA1 Message Date
Elie Habib
be485ad1c2 chore: switch license to AGPL-3.0, externalize Sentry DSN
- Replace MIT with AGPL-3.0-only to enforce attribution on derivatives
- Move hardcoded Sentry DSN to VITE_SENTRY_DSN env var
- Add null-coalesce guards for i18n legend keys and SVG viewBox
- Extend Sentry ignoreErrors with 7 additional noise patterns
2026-02-19 07:24:47 +04:00
Elie Habib
572f380856 release: v2.4.0 — live webcams, mobile detection fix, sentry triage
- Live Webcams Panel with region filters and grid/single view (#111)
- Mobile detection: width-only, touch notebooks get desktop layout (#113)
- Le Monde RSS URL fix, workbox precache HTML, panel ordering migration
- Sentry: ML timeout catch, YT player guards, maplibre noise filters
- Changelog for v2.4.0
v2.4.0
2026-02-19 01:25:05 +04:00
Elie Habib
aa36426293 Merge branch 'fix/mobile-detection-width-only'
# Conflicts:
#	src/styles/main.css
2026-02-19 01:23:55 +04:00
Elie Habib
c68a75928a fix(sentry): triage 5 unresolved issues — 3 fixes, 2 noise filters
- ml-worker: catch unload-model timeout instead of leaking unhandled rejection
- LiveNewsPanel: optional chaining on playVideo/pauseVideo for edge cases
  where YT IFrame API player object isn't fully initialized
- main.ts: add noise filter for Firefox i18next "too much recursion"
- main.ts: extend maplibre beforeSend filter for null 'id'/'type' crashes
2026-02-19 01:10:02 +04:00
Elie Habib
c13efa468d Improve mobile map popup usability quirks (sheet/touch/controls layout) (#109)
## Summary

Improve mobile map popup usability for touch screen

## Type of change

- [ ] Bug fix
- [ ] New feature
- [ ] New data source / feed
- [ ] New map layer
- [x] Refactor / code cleanup
- [ ] Documentation
- [ ] CI / Build / Infrastructure

## Affected areas

- [x] Map / Globe
- [ ] News panels / RSS feeds
- [ ] AI Insights / World Brief
- [ ] Market Radar / Crypto
- [ ] Desktop app (Tauri)
- [ ] API endpoints (`/api/*`)
- [ ] Config / Settings
- [ ] Other: <!-- specify -->

## Checklist

- [ ] Tested on [worldmonitor.app](https://worldmonitor.app) variant
- [ ] Tested on [tech.worldmonitor.app](https://tech.worldmonitor.app)
variant (if applicable)
- [ ] New RSS feed domains added to `api/rss-proxy.js` allowlist (if
adding feeds)
- [ ] No API keys or secrets committed
- [ ] TypeScript compiles without errors (`npm run typecheck`)

## Screenshots

<!-- If applicable, add screenshots or screen recordings -->
2026-02-19 01:04:05 +04:00
Elie Habib
9aa210a1b1 Disable intelligence alerts on mobile (#110)
## Summary

<!-- Brief description of what this PR does -->

## Type of change

- [ ] Bug fix
- [x] New feature
- [ ] New data source / feed
- [ ] New map layer
- [ ] Refactor / code cleanup
- [ ] Documentation
- [ ] CI / Build / Infrastructure

## Affected areas

- [ ] Map / Globe
- [ ] News panels / RSS feeds
- [ ] AI Insights / World Brief
- [ ] Market Radar / Crypto
- [ ] Desktop app (Tauri)
- [ ] API endpoints (`/api/*`)
- [ ] Config / Settings
- [x] Other: Notifications

## Checklist

- [x] Tested on [worldmonitor.app](https://worldmonitor.app) variant
- [x] Tested on [tech.worldmonitor.app](https://tech.worldmonitor.app)
variant (if applicable)
- [ ] New RSS feed domains added to `api/rss-proxy.js` allowlist (if
adding feeds)
- [ ] No API keys or secrets committed
- [ ] TypeScript compiles without errors (`npm run typecheck`)

## Screenshots

<!-- If applicable, add screenshots or screen recordings -->
2026-02-19 01:03:35 +04:00
Elie Habib
315e94ed0f feat: add live webcams panel with localized labels (#111)
## Summary

<!-- A set of multiple live webcams to monitor the world live 😃  -->

## Type of change

- [ ] Bug fix
- [x] New feature
- [x] New data source / feed
- [ ] New map layer
- [ ] Refactor / code cleanup
- [ ] Documentation
- [ ] CI / Build / Infrastructure

## Affected areas

- [ ] Map / Globe
- [ ] News panels / RSS feeds
- [ ] AI Insights / World Brief
- [ ] Market Radar / Crypto
- [ ] Desktop app (Tauri)
- [ ] API endpoints (`/api/*`)
- [ ] Config / Settings
- [ ] Other: <!-- specify -->

## Checklist

- [x] Tested on [worldmonitor.app](https://worldmonitor.app) variant
- [ ] Tested on [tech.worldmonitor.app](https://tech.worldmonitor.app)
variant (if applicable)
- [ ] New RSS feed domains added to `api/rss-proxy.js` allowlist (if
adding feeds)
- [x] No API keys or secrets committed
- [x] TypeScript compiles without errors (`npm run typecheck`)

## Screenshots

<!-- If applicable, add screenshots or screen recordings -->
2026-02-19 01:03:04 +04:00
Masaki
9106297563 fix: use viewport width only for mobile detection (fixes touch notebooks)
- Remove (pointer: coarse) from mobile detection so touch-capable
  desktops (e.g. ROG Flow X13) get desktop layout instead of mobile
- Define MOBILE_BREAKPOINT_PX (768) in utils and use in
  isMobileDevice(); CSS @media (max-width: 768px) kept in sync
- MobileWarningModal uses isMobileDevice() for consistent behavior

Ref: https://github.com/koala73/worldmonitor/discussions/94
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-19 05:59:58 +09:00
Elie Habib
9d61d1512f fix(webcams): replace Dubai/Istanbul with Tel Aviv/Mecca, RTL fix
- Swap Dubai → Tel Aviv (live conflict coverage webcam)
- Swap Istanbul → Mecca (Kaaba 24/7 livestream)
- Fix margin-right → margin-inline-end on back button for RTL
2026-02-19 00:56:25 +04:00
Elie Habib
606ce98026 feat(webcams): add LA and Miami to fill Americas grid to 4
- Los Angeles Venice Beach (EO_1LWqsCNE) — confirmed live
- Miami Biscayne Bay (5YCajRjvWCg) — confirmed live
2026-02-19 00:46:14 +04:00
Elie Habib
b865ec94e8 fix(webcams): curate ALL grid to Jerusalem, Tehran, Kyiv, Washington 2026-02-19 00:43:12 +04:00
Elie Habib
a58fb4ad62 fix(webcams): replace dead Tokyo feed, reorder Asia-Pacific
- Tokyo: DjdUEyjx8GM (maintenance) → 4pu9sF5Qssw (Tokyo Live Camera 4K)
- Reorder: Taipei → Shanghai → Tokyo → Seoul (strait hotspot first)
2026-02-19 00:42:12 +04:00
Elie Habib
7a25db9208 fix(webcams): idle resume bug and mobile single-view escape
- Idle handler now clears isIdle and re-renders on user activity
  (was permanently paused after 5min timeout)
- Add grid back button in single-view switcher row for mobile
  (view toggle hidden at <=768px left users stuck)
2026-02-19 00:37:10 +04:00
Elie Habib
817bc9016e fix(webcams): diverse ALL grid, reorder feeds, fix icons and Berlin
- ALL grid now picks one feed per region (was showing 4x mideast)
- Jerusalem & Tehran adjacent (conflict hotspots)
- Replace broken Berlin with Paris Eiffel Tower webcam
- Switch toolbar SVG icons from stroke to fill for dark mode clarity
2026-02-19 00:34:13 +04:00
Elie Habib
a68d77b588 feat(download): add Linux (.AppImage) to download banner
CI already builds AppImage for Linux — this adds the missing UI:
- linux-appimage pattern in api/download.js
- Linux UA detection and button in DownloadBanner
- i18n key added to all 13 locale files
2026-02-19 00:25:05 +04:00
Elie Habib
3fa60ea498 fix(rss): add 8 missing domains to proxy allowlist
france24, euronews, lemonde, dw, africanews, lasillavacia,
channelnewsasia, thehindu were returning 403 in production.
2026-02-19 00:24:56 +04:00
Elie Habib
356967f7db fix(ui): repair malformed HTML tags in panel template literals
Spaces inside HTML tags (e.g. `< span class= "trend-up" >`) caused
browsers to render raw markup text instead of elements. Fixed ~45
instances across CIIPanel, ServiceStatusPanel, and StrategicPosturePanel.
2026-02-19 00:24:46 +04:00
Elie Habib
935a58abd4 feat: add live webcams panel with localized labels 2026-02-19 00:01:31 +04:00
Elie Habib
de34ccd8d7 Disable intelligence alerts on mdl 2026-02-18 23:51:53 +04:00
Elie Habib
00e5e7299a Improve mobile map popup QA 2026-02-18 23:31:44 +04:00
Elie Habib
943b5e41cd fix(ml): resolve beta mode race condition and timeout failures
- Fix summarization race: check isModelLoaded before attempting browser
  T5, fall through to cloud providers while model loads in background
- Increase modelLoadTimeoutMs 30s→600s and inferenceTimeoutMs 45s→120s
  to accommodate first-time model downloads
- Use flan-t5-small (60MB) instead of flan-t5-base (250MB) in beta mode
  for country brief fallback
- Skip ML summarization in country brief when model not loaded to avoid
  blocking UX
- Broadcast model-loaded notifications from worker on implicit loads so
  manager's loadedModels stays in sync
- Suppress ONNX CleanUnusedInitializersAndNodeArgs warnings via
  ort.env.logLevel
- Fix non-monotonic progress reporting with separate warm/cold step counts
2026-02-18 22:54:15 +04:00
Elie Habib
265a4b7bc7 fix(sentry): guard .closest() call on non-Element event target in Panel dragstart handler
e.target can be a text node when dragging text content inside a panel.
Text nodes lack .closest(), causing TypeError. Add instanceof Element check.

Resolves Sentry P2: TypeError: o.closest is not a function
2026-02-18 22:31:56 +04:00
Elie Habib
e2926d0ba2 feat(i18n): Comprehensive Localization & Regional Intelligence (#103)
## Summary
This release introduces comprehensive localization support, transforming
WorldMonitor into a truly global intelligence platform.

### Key Features
- **Multilingual UI**: Full support for 12 languages (EN, FR, ES, DE,
IT, PT, NL, SV, RU, AR, CN, JP).
- **RTL Support**: Native right-to-left layout for Arabic and Hebrew,
including mirrored UI components and correct text alignment.
- **Regional Intelligence**: 
  - Dynamic feed selection based on language preference.
- Dedicated regional monitoring panels for Africa, LatAm, Middle East,
and Asia.
  - Granular error handling for regionally blocked feeds.
- **AI Integration**: On-demand translation and summarization of news
items using localized prompts.

### Technical Changes
- **Refactoring**: Overhauled \src/services/i18n.ts\ and
\src/config/feeds.ts\ to support dynamic loading.
- **Styling**: Added \src/styles/rtl-overrides.css\ using logical CSS
properties for maintenance-free RTL support.
- **Cleanup**: Resolved CSS lint warnings and improved code quality.

### Verification
- **Build**: \
pm run build\ passed successfully.
- **Manual Testing**: Verified RTL layout, language switching, and
regional feed loading.
2026-02-18 22:12:18 +04:00
Elie Habib
fb7711bfe4 merge: sync latest main and resolve App import conflict 2026-02-18 21:50:43 +04:00
Elie Habib
7446fb53a3 merge: resolve main conflicts in App and feeds for PR #103 2026-02-18 21:49:15 +04:00
Elie Habib
f87c882fc3 feat: add developer beta mode for T5-small evaluation (#108)
Console-activated (beta=true) mode that swaps browser summarization to
Flan-T5-small (60MB) as first provider with comparison logging against
Groq. Persists via localStorage, shows amber BETA badge in header.

## Summary

<!-- Brief description of what this PR does -->

## Type of change

- [ ] Bug fix
- [ ] New feature
- [ ] New data source / feed
- [ ] New map layer
- [ ] Refactor / code cleanup
- [ ] Documentation
- [ ] CI / Build / Infrastructure

## Affected areas

- [ ] Map / Globe
- [ ] News panels / RSS feeds
- [ ] AI Insights / World Brief
- [ ] Market Radar / Crypto
- [ ] Desktop app (Tauri)
- [ ] API endpoints (`/api/*`)
- [ ] Config / Settings
- [ ] Other: <!-- specify -->

## Checklist

- [ ] Tested on [worldmonitor.app](https://worldmonitor.app) variant
- [ ] Tested on [tech.worldmonitor.app](https://tech.worldmonitor.app)
variant (if applicable)
- [ ] New RSS feed domains added to `api/rss-proxy.js` allowlist (if
adding feeds)
- [ ] No API keys or secrets committed
- [ ] TypeScript compiles without errors (`npm run typecheck`)

## Screenshots

<!-- If applicable, add screenshots or screen recordings -->
2026-02-18 21:47:17 +04:00
Elie Habib
d5f8345509 feat: add developer beta mode for T5-small evaluation
Console-activated (beta=true) mode that swaps browser summarization to
Flan-T5-small (60MB) as first provider with comparison logging against
Groq. Persists via localStorage, shows amber BETA badge in header.
2026-02-18 21:45:52 +04:00
Elie Habib
0564db5e99 fix(i18n): scope caches by locale and lazy-load translations 2026-02-18 21:43:05 +04:00
Elie Habib
06074a2d7b fix: validate API response data before reporting ok, narrow maplibre noise filter to stack-checked beforeSend 2026-02-18 21:06:14 +04:00
Elie Habib
7c46ddeb9e fix: wire up missing API status indicators (GDELT Doc, EIA, USASpending, Cyber Threats)
- GDELT Doc: rename 'GDELT' → 'GDELT Doc' to match StatusPanel allowlist
- EIA: add updateApi calls in loadOilAnalytics
- USASpending: add updateApi calls in loadGovernmentSpending
- Cyber Threats API: add updateApi calls alongside existing feed updates
2026-02-18 20:54:02 +04:00
Elie Habib
ad3e2ba529 fix(sentry): broaden Failed to fetch filter to match domain-suffixed variants 2026-02-18 20:44:21 +04:00
Elie Habib
564ea5b433 fix(sentry): narrow shader link filter to null-only to preserve real GLSL error signal 2026-02-18 20:00:18 +04:00
Elie Habib
e85b4331bb fix(sentry): filter maplibre internal null-access crashes (light, placement) 2026-02-18 19:57:44 +04:00
Elie Habib
2da05f172d fix: guard YT player .mute()/.unMute() with optional chaining, filter WebGL link errors
- LiveNewsPanel: player.mute/unMute may not exist before onReady (WORLDMONITOR-16)
- main.ts: add /Program failed to link/ noise filter (WORLDMONITOR-18)
2026-02-18 19:55:14 +04:00
Elie Habib
65618da405 fix: add console.warn to silent storage catch blocks for diagnosability 2026-02-18 19:51:49 +04:00
Elie Habib
0d08c23d85 fix: isolate baseline writes from fetch/render and guard snapshot rejections
- Wrap updateBaseline() in try/catch inside loadNewsCategory and intel
  path so IndexedDB write failures don't delete successfully fetched
  and rendered news data (P1)
- Add .catch() to saveCurrentSnapshot() initial call and setInterval
  callback to prevent unhandled promise rejections from IndexedDB
  readwrite failures (P2)
2026-02-18 19:43:14 +04:00
Elie Habib
a0f8bcb3bc fix(sentry): safari fullscreen void return, narrow module-import filter, IndexedDB write-drop
- webkitRequestFullscreen returns void (not Promise) on Safari — use
  try/catch instead of .catch() to avoid undefined.catch() throw
- Module-import beforeSend filter: only suppress when stack frames
  originate from browser extensions, not by URL domain check
- withTransaction: throw on readwrite InvalidStateError after retry
  instead of silently returning undefined (prevents write-drop)
2026-02-18 19:39:42 +04:00
Elie Habib
dfd5ffcbee fix(sentry): fullscreen Promise catch, narrow fetch filter, and classList guards
- toggleFullscreen: use void .catch() for Promise-based requestFullscreen/
  exitFullscreen + webkit prefix fallback for iOS Safari (WORLDMONITOR-11/13)
- Narrow /^TypeError: Failed to fetch/ to exact match (was suppressing real
  API failures). Move module-import-failed to beforeSend with extension/
  webview context check instead of blanket ignore (WORLDMONITOR-15)
- Guard classList?.contains and target.closest?. on event targets that may
  not be Elements (WORLDMONITOR-Z/10)
- Add noise filters: Fullscreen request denied, requestFullscreen,
  vc_text_indicators_context (WORLDMONITOR-12)
2026-02-18 19:33:58 +04:00
Elie Habib
ffd99b0c58 fix(sentry): guard deck.gl setProps during WebGL context loss and add noise filters
Prevent getProjection null crash when WebGL context is lost by tracking
webglLost flag and skipping all setProps/layer rebuild calls until restored.
Add ignoreErrors for IndexedDB iOS kills, Twitter WebView injection, and
CSP unsafe-eval from extensions.
2026-02-18 18:05:30 +04:00
Elie Habib
7bbae36cb7 fix(sentry): broaden Failed to fetch filter to catch domain-suffixed variants
Browser extensions intercept window.fetch causing "Failed to fetch
(gamma-api.polymarket.com)" to leak as unhandled rejection. Remove
the $ anchor so the pattern matches any suffix.
2026-02-18 17:45:51 +04:00
Elie Habib
065fae2ed8 fix: expand Sentry noise filtering and address code review findings
- Add beforeSend filter to drop minified 1-3 char library errors (e.g., "vd")
- Filter transient network errors (Load failed, Failed to fetch, cancelled)
- Filter browser extension errors (runtime.sendMessage, Java object is gone)
- Filter non-Error promise rejections and SVG image load failures
- Filter MapLibre imageManager null ref during WebGL context restore
- Reset YouTube API promise on load failure to allow retry on next init
- Move USASpending timeout cleanup to finally block
- Log snapshot cleanup errors instead of silently swallowing
2026-02-18 17:42:52 +04:00
Elie Habib
609e372a3d fix: gracefully handle IndexedDB connection-closing errors on iOS
- withTransaction now returns undefined instead of throwing when
  InvalidStateError persists after retry (transient browser event)
- Add .catch() to fire-and-forget cleanOldSnapshots() call
2026-02-18 15:24:24 +04:00
Elie Habib
12d85320e2 fix: filter non-actionable Sentry errors (autoplay, WebView, deck.gl, extensions)
- Add NotAllowedError, InvalidAccessError, importScripts to Sentry ignoreErrors
- Add global unhandledrejection handler for YouTube IFrame API autoplay blocks
- Add onError handler to deck.gl MapboxOverlay for internal render-cycle races
2026-02-18 15:22:53 +04:00
Elie Habib
54f417d8fc fix: resolve Sentry errors — IndexedDB stale connection, USASpending timeout, WebGL context loss, RSS 403s
- storage.ts: add withTransaction() retry wrapper for IndexedDB InvalidStateError on iOS/Safari tab backgrounding
- usa-spending.ts: add 20s AbortController timeout to prevent Safari "Load failed" on stalled POST
- App.ts: add catch to runGuarded() to prevent unhandled rejections from task runner
- main.ts: add Sentry ignoreErrors for WebGL context loss and ResizeObserver loop
- DeckGLMap.ts: add webglcontextlost/restored handlers for graceful GPU recovery
- feeds.ts: route rsshub.app feeds (NHK, MIIT, MOFCOM) through Railway proxy, switch Nikkei Asia and ECFR to Google News proxy
- finance.ts: switch Nikkei Asia to Google News proxy, remove unused railwayRss helper
2026-02-18 14:25:59 +04:00
Elie Habib
30e2dda448 fix: gracefully handle YouTube IFrame API load failure
Resolve instead of reject when the script fails to load (ad blocker,
network issue). Guard initializePlayer against missing YT.Player.
Prevents noisy unhandled rejection errors in Sentry.
2026-02-18 14:07:23 +04:00
Elie Habib
941475eb79 feat: integrate Sentry browser error tracking
Initializes @sentry/browser early in main.ts with environment
detection (production/preview/development). Disabled on localhost
and Tauri desktop. Traces sampled at 10%.
2026-02-18 13:56:31 +04:00
Lib-LOCALE
f8270689a0 feat(i18n): comprehensive localization, RTL support, and regional feeds revamp 2026-02-18 10:38:17 +01:00
Elie Habib
71a62e5bb4 fix: gate SignalModal auto-popup on findings toggle (#101)
## Summary
- PR #97 hid the badge but the `SignalModal` kept auto-opening on new
signals — this is what the reporter was still seeing
- Gates all 5 automatic `this.signalModal?.show()` calls behind
`this.findingsBadge?.isEnabled()` so disabling Intelligence Findings
also suppresses the full-screen popup overlay and sounds
- Signal history is still recorded (`addToSignalHistory`) even when
popup is suppressed, so re-enabling the toggle shows them

Closes #89

## Test plan
- [x] Disable Intelligence Findings via PANELS toggle or right-click
- [x] Wait for signal refresh cycle — no full-screen popup should appear
- [x] Re-enable → popups resume on next signal detection
- [x] Build succeeds with no type errors

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-02-18 13:16:17 +04:00
Elie Habib
cb242f1b2c feat: add La Silla Vacía (Colombia) to LATAM feeds (#102)
## Summary
- Adds [La Silla Vacía](https://www.lasillavacia.com) RSS feed (`/rss`)
to the `latam` feed category
- Adds source tier entry (Tier 3 — specialty/investigative)
- Colombian independent outlet covering political power structures,
governance, and armed conflict

Ref #96

## Test plan
- [ ] Verify feed loads in LATAM news panel (content is in Spanish)
- [ ] Confirm no duplicate or broken entries in feed list

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-02-18 13:15:33 +04:00
Sebastien Melki
dae0de6d99 feat: add La Silla Vacía (Colombia) to LATAM feeds
Add lasillavacia.com RSS feed to improve Latin American political
coverage. Independent Colombian investigative outlet covering governance,
armed conflict, and regional power dynamics.

Ref #96

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 10:51:31 +02:00