mirror of
https://github.com/koala73/worldmonitor.git
synced 2026-04-25 17:14:57 +02:00
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
This commit is contained in:
32
.claudedocs/sentry-triage/2026-02-19.md
Normal file
32
.claudedocs/sentry-triage/2026-02-19.md
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
# Sentry Triage — 2026-02-19
|
||||||
|
|
||||||
|
Commit: `09174fd` on `main`
|
||||||
|
|
||||||
|
## Issues Triaged (5)
|
||||||
|
|
||||||
|
### ACTIONABLE — Fixed in Code
|
||||||
|
|
||||||
|
| ID | Title | Events | Users | Fix |
|
||||||
|
|---|---|---|---|---|
|
||||||
|
| WORLDMONITOR-1G | `Error: ML request unload-model timed out after 120000ms` | 30 | 27 | Wrapped `unloadModel()` in try/catch; timeout no longer leaks as unhandled rejection. Cleans up `loadedModels` set on failure. |
|
||||||
|
| WORLDMONITOR-1F | `Error: ML request unload-model timed out after 120000ms` | 9 | 9 | Same root cause as 1G (different release build hash). |
|
||||||
|
| WORLDMONITOR-1K | `TypeError: this.player.playVideo is not a function` | 1 | 1 | Added optional chaining (`playVideo?.()`, `pauseVideo?.()`) in `LiveNewsPanel.ts`. YT IFrame API player object may not have methods ready during initialization race. |
|
||||||
|
|
||||||
|
### NOISE — Filtered
|
||||||
|
|
||||||
|
| ID | Title | Events | Users | Filter |
|
||||||
|
|---|---|---|---|---|
|
||||||
|
| WORLDMONITOR-1J | `InternalError: too much recursion` | 1 | 1 | i18next internal `translate -> extractFromKey` cycle on Firefox 147. Added `/too much recursion/` to `ignoreErrors`. |
|
||||||
|
| WORLDMONITOR-1H | `TypeError: Cannot read properties of null (reading 'id')` | 1 | 1 | maplibre-gl internal render crash (`_drawLayers -> renderLayers`). Extended `beforeSend` regex to suppress null `id`/`type` when stack is in map chunk. |
|
||||||
|
|
||||||
|
## Files Modified
|
||||||
|
|
||||||
|
| File | Change |
|
||||||
|
|---|---|
|
||||||
|
| `src/services/ml-worker.ts` | `unloadModel()`: try/catch around `this.request()`, clean `loadedModels` on failure |
|
||||||
|
| `src/components/LiveNewsPanel.ts` | Optional chaining on `playVideo?.()` and `pauseVideo?.()` |
|
||||||
|
| `src/main.ts` | Added `/too much recursion/` to `ignoreErrors`; extended maplibre `beforeSend` filter for null `id`/`type` |
|
||||||
|
|
||||||
|
## Sentry Status
|
||||||
|
|
||||||
|
All 5 issues marked **resolved (in next release)** via API. They will auto-reopen if errors recur after deployment.
|
||||||
27
CHANGELOG.md
27
CHANGELOG.md
@@ -2,6 +2,33 @@
|
|||||||
|
|
||||||
All notable changes to World Monitor are documented here.
|
All notable changes to World Monitor are documented here.
|
||||||
|
|
||||||
|
## [2.4.0] - 2026-02-19
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- **Live Webcams Panel**: 2x2 grid of live YouTube webcam feeds from global hotspots with region filters (Middle East, Europe, Asia-Pacific, Americas), grid/single view toggle, idle detection, and full i18n support (#111)
|
||||||
|
- **Linux download**: added `.AppImage` option to download banner
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- **Mobile detection**: use viewport width only for mobile detection; touch-capable notebooks (e.g. ROG Flow X13) now get desktop layout (#113)
|
||||||
|
- **Webcam feeds**: curated Tel Aviv, Mecca, LA, Miami; replaced dead Tokyo feed; diverse ALL grid with Jerusalem, Tehran, Kyiv, Washington
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- **Le Monde RSS**: English feed URL updated (`/en/rss/full.xml` → `/en/rss/une.xml`) to fix 404
|
||||||
|
- **Workbox precache**: added `html` to `globPatterns` so `navigateFallback` works for offline PWA
|
||||||
|
- **Panel ordering**: one-time migration ensures Live Webcams follows Live News for existing users
|
||||||
|
- **Mobile popups**: improved sheet/touch/controls layout (#109)
|
||||||
|
- **Intelligence alerts**: disabled on mobile to reduce noise (#110)
|
||||||
|
- **RSS proxy**: added 8 missing domains to allowlist
|
||||||
|
- **HTML tags**: repaired malformed tags in panel template literals
|
||||||
|
- **ML worker**: wrapped `unloadModel()` in try/catch to prevent unhandled timeout rejections
|
||||||
|
- **YouTube player**: optional chaining on `playVideo?.()` / `pauseVideo?.()` for initialization race
|
||||||
|
- **Panel drag**: guarded `.closest()` on non-Element event targets
|
||||||
|
- **Beta mode**: resolved race condition and timeout failures
|
||||||
|
- **Sentry noise**: added filters for Firefox `too much recursion`, maplibre `_layers`/`id`/`type` null crashes
|
||||||
|
|
||||||
## [2.3.9] - 2026-02-18
|
## [2.3.9] - 2026-02-18
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "world-monitor",
|
"name": "world-monitor",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "2.3.9",
|
"version": "2.4.0",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"lint:md": "markdownlint-cli2 '**/*.md'",
|
"lint:md": "markdownlint-cli2 '**/*.md'",
|
||||||
|
|||||||
@@ -2253,6 +2253,14 @@ export class App {
|
|||||||
panelOrder.unshift('live-news');
|
panelOrder.unshift('live-news');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// live-webcams MUST follow live-news (one-time migration for existing users)
|
||||||
|
const webcamsIdx = panelOrder.indexOf('live-webcams');
|
||||||
|
if (webcamsIdx !== -1 && webcamsIdx !== panelOrder.indexOf('live-news') + 1) {
|
||||||
|
panelOrder.splice(webcamsIdx, 1);
|
||||||
|
const afterNews = panelOrder.indexOf('live-news') + 1;
|
||||||
|
panelOrder.splice(afterNews, 0, 'live-webcams');
|
||||||
|
}
|
||||||
|
|
||||||
// Desktop configuration should stay easy to reach in Tauri builds.
|
// Desktop configuration should stay easy to reach in Tauri builds.
|
||||||
if (this.isDesktopApp) {
|
if (this.isDesktopApp) {
|
||||||
const runtimeIdx = panelOrder.indexOf('runtime-config');
|
const runtimeIdx = panelOrder.indexOf('runtime-config');
|
||||||
|
|||||||
@@ -411,7 +411,7 @@ const FULL_FEEDS: Record<string, Feed[]> = {
|
|||||||
{
|
{
|
||||||
name: 'Le Monde',
|
name: 'Le Monde',
|
||||||
url: {
|
url: {
|
||||||
en: rss('https://www.lemonde.fr/en/rss/full.xml'),
|
en: rss('https://www.lemonde.fr/en/rss/une.xml'),
|
||||||
fr: rss('https://www.lemonde.fr/rss/une.xml')
|
fr: rss('https://www.lemonde.fr/rss/une.xml')
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ Sentry.init({
|
|||||||
if (frames.some(f => /^(chrome|moz)-extension:/.test(f.filename ?? ''))) return null;
|
if (frames.some(f => /^(chrome|moz)-extension:/.test(f.filename ?? ''))) return null;
|
||||||
}
|
}
|
||||||
// Suppress maplibre internal null-access crashes (light, placement) only when stack is in map chunk
|
// Suppress maplibre internal null-access crashes (light, placement) only when stack is in map chunk
|
||||||
if (/this\.light is null|can't access property "type", \w+ is undefined|Cannot read properties of null \(reading '(id|type)'\)/.test(msg)) {
|
if (/this\.style\._layers|this\.light is null|can't access property "type", \w+ is undefined|Cannot read properties of null \(reading '(id|type)'\)/.test(msg)) {
|
||||||
if (frames.some(f => /\/map-[A-Za-z0-9]+\.js/.test(f.filename ?? ''))) return null;
|
if (frames.some(f => /\/map-[A-Za-z0-9]+\.js/.test(f.filename ?? ''))) return null;
|
||||||
}
|
}
|
||||||
return event;
|
return event;
|
||||||
|
|||||||
@@ -196,7 +196,7 @@ export default defineConfig({
|
|||||||
},
|
},
|
||||||
|
|
||||||
workbox: {
|
workbox: {
|
||||||
globPatterns: ['**/*.{js,css,ico,png,svg,woff2}'],
|
globPatterns: ['**/*.{js,css,html,ico,png,svg,woff2}'],
|
||||||
globIgnores: ['**/ml-*.js', '**/onnx*.wasm'],
|
globIgnores: ['**/ml-*.js', '**/onnx*.wasm'],
|
||||||
navigateFallback: '/index.html',
|
navigateFallback: '/index.html',
|
||||||
navigateFallbackDenylist: [/^\/api\//, /^\/settings/],
|
navigateFallbackDenylist: [/^\/api\//, /^\/settings/],
|
||||||
|
|||||||
Reference in New Issue
Block a user