@eslint/js@10.0.1 requires eslint@^10.0.0 as a peer dependency,
which conflicts with the pinned eslint@9. Pinning @eslint/js to <10
keeps it on the 9.x line.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The error path was missing the /g flag on the regex replacing ? with %s,
so only the first placeholder was replaced. It also dumped bind values as
a space-separated string instead of using sprintf to substitute them into
the query. Now matches the existing debug path pattern.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
window.onerror now captures column number and error stack trace when
available. Undefined or browser-sanitized "Script error." messages get a
descriptive placeholder instead of logging "undefined". Caller name
introspection is guarded against strict mode and empty names.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The chrono duration rep type is long long on some platforms but long on
others. Using %ld causes -Wformat warnings on platforms where it is
long long. Use %jd with static_cast<intmax_t>() for portability,
matching the convention used elsewhere in the codebase.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When zone coordinates are stored as pixel values (e.g. from a missed DB
migration), the web layer now detects values > 100 and converts them to
percentages using the monitor's dimensions, mirroring the existing C++
detection logic in zm_zone.cpp. This prevents limitPoints() from clamping
pixel values to 0-100 and zones rendering incorrectly in SVG overlays.
- Add convertPixelPointsToPercent() helper in functions.php
- Call conversion before limitPoints() in zone.php and zones.php
- Update Zone::svg_polygon() to accept monitor dimensions and convert
- Pass ViewWidth/ViewHeight to svg_polygon() from Monitor::getStreamHTML()
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace img load event listener with ResizeObserver on imageFeed
container. The old approach listened for load events on #imageFrame img
elements, which never fires for video-based streams (Go2RTC MSE) since
they use <video> not <img>. ResizeObserver fires whenever the container
dimensions change regardless of content type, fixing incorrect zone
point positions on initial load.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
On the Zones page, with the default player = go2rtc, a zone may not display due to the added <video-stream> tag
due to "position: relative"
And zones should always be above all other elements.
Possible fix#4648
- Integrate EventStream.js into montagereview.js for persistent MJPEG
streaming in replay mode (speeds >= 1x), falling back to per-frame
mode=single for speeds < 1x where zms lacks slow-motion support
- Add EventStream recovery logic: detect zms death via AJAX failures,
img.onerror, and error responses; auto-restart with new connkey and
exponential backoff (max 5 retries)
- Fix zms crash on bulk/interpolated frames: add stat() check in
sendFrame() for SaveJPEGs & 1 path, fall through to ffmpeg_input
when JPEG file doesn't exist on disk; send "No frame available"
text frame instead of terminating when no source available
- Center monitor canvases: text-align in CSS for scale mode,
horizontal offset calculation in maxfit2() for fit mode
- Reduce console noise: comment out high-frequency debug logs,
convert error-path logs to console.warn/error
- Fix ESLint sourceType to "script" for traditional non-module JS
files, resolving false-positive no-unused-vars on global functions
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Complete the migration from .eslintrc.js to eslint.config.js flat
config format for ESLint 9 compatibility. Add valid-jsdoc: off
(removed in ESLint 9 but enabled by eslint-config-google) and the
missing operator-linebreak: off override. Update the HLS ignore path
to match current version. Update CI workflow to install ESLint 9 and
its flat config dependencies.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
After adding the "players" variable, the "players is not defined" issue appears on various pages.
There's currently an error on the Zones page.
Yes, ideally, the variable should be added in *.js.php files on various pages.
The absence of the variable has no significant impact, other than incomplete display of information.
The current error disrupts all JavaScript.
This PR prevents the disruption of all JavaScript code on the page.
A detached Image() object does not reliably decode multipart MJPEG
streams — browsers only update a DOM-attached <img> with each frame
from a multipart/x-mixed-replace response. Switch to creating a
hidden DOM <img> element and use requestAnimationFrame to copy
decoded frames to the canvas.
Also properly clean up the img element from the DOM in stop() and
switchEvent(), and guard drawFrame() against drawing before the
first frame has been decoded.
Tested: start, pause, play, seek, setRate, stop all verified
working against a live zms event stream.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Introduce EventStream constructor that manages a persistent zms MJPEG
connection for event playback, replacing the per-frame mode=single HTTP
request pattern. Frames arrive via a hidden Image element and are drawn
to a caller-supplied canvas on each onload.
Supports seek, pause, play, rate control, scale changes, and event
switching via the existing zms command-socket protocol. Follows the
same constructor-function pattern as MonitorStream.js.
Include the script in montagereview.php for upcoming integration.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add RBAC checks to ConfigsController edit() and delete() requiring
System=Edit permission, matching the pattern used by other controllers.
Harden System/Readonly column checks with !empty() to handle missing
columns gracefully. Fix command injection in Event.php by using
ZM_PATH_FFMPEG constant with escapeshellarg() instead of hardcoded
unsanitized ffmpeg call. Add is_executable() validation at all exec()
sites using ZM_PATH_FFMPEG as defense-in-depth against poisoned config
values.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
setCookie('speed', ...) was storing the speedIndex (array position)
but the PHP side reads the cookie and compares it against speed values
to find the matching index. Storing the index meant the value never
matched, so the slider always reset to the default 1x on reload.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Fix FFmpeg initial seek overshooting to a future keyframe when the
requested timestamp falls between keyframes. After the initial
AVSEEK_FLAG_FRAME seek, detect if the returned frame is past the
target and re-seek backward to get the correct keyframe before it.
On the JS side, preserve fractional seconds throughout the playback
pipeline: remove Math.floor() truncation in mmove() and setSpeed(),
and use parseFloat instead of parseInt for currentTimeSecs
initialization. Reduce initial display interval from 1000ms to 100ms
for ~10fps refresh rate during review playback.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add data-monitor-width and data-monitor-height attributes to thumbnail
img elements in console.php, events.php, watch.php, and monitor.php.
Use these to calculate the scale parameter as a ratio of overlay size to
monitor native resolution, clamped to 5-100%, instead of hardcoding
scale=75 (overlay) and scale=32 (fallback).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
GCC < 9 (CentOS/RHEL 8) requires explicitly linking stdc++fs for
std::filesystem support. Add a CMake compile check that detects this
and conditionally links the library for the zma target.
Also add the zma binary to the Red Hat spec file's %files section
so it gets packaged in the RPM.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Fix monitor config view labels being pushed off-screen to the left on
mobile. The CSS specificity of the mobile override selector
(ul.form > li > label) was lower than the base rule
(ul.form > li > label:first-child), so margin-left: -300px was never
overridden on small screens. Match the :first-child pseudo-class in
the media query to fix.
Also add mobile responsive overrides for the watch view (which had
none), and change flex-nowrap to flex-md-nowrap so sidebar/PTZ stack
vertically on phones.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>